Using Protocol Buffers

I’ve written once before about using protocol buffers, using the protobuf-net library, but I didn’t go into any depth regarding the .proto file which is used for the IDL. Let’s rectify this.

Introduction

Protocol buffers are simply a way to define a “language-neutral, “platform-neutral, extensible mechanism for serializing structed data”. What this really means is this is a specification (and tooling) for creating binary data. This data might exist as files or streamed over HTTP or any other type of stream. Think of Protocol Buffers as CSV, XML or the likes, but obviously being binary these resultant streams would generally be more compact than these other formats.

Proto file format

I’m not going to cover the .proto syntax in full as it’s already available at Language Guide (proto3), but as I build up an example .proto file I will cover the pieces that I add to the file as I go.

We’re going to want to create a .proto file which we be used to declare our messages/data. Currently the latest syntax supported is “proto3” and we declare the version we support in our .proto file. If you do not specify the syntax, currently this syntax will default to proto2 syntax.

So first off create a file with the .proto extension – I’m doing this within Visual Studio which supports Protocol Buffer syntax highlighting etc.

To declare the supported syntax we start off by adding the following line (I’m going to use proto3 syntax in the post, there are several differences between proto3 and proto2)

syntax = "proto3";

Packages/Namespaces

Whilst it’s optional, the next thing we’ll add is a package which, whilst optional, is useful for code generation in your preferred language. For example in Java this maps directly to the Java package name and in C# and C++ this maps to the namespace of the code.

We can actually override the package/namespace name for Java and C# by using option java_package and/or option csharp_namespace instead or as well as the package line. Obviously we might wish to have all three in our .proto file so the file can be used to generate for Ruby, Go, C++ etc. as well as explicit definitions of Java and C#

So let’s add a package

package music;

option java_package = "com.putridparrot.music";
option csharp_namespace = "PutridParrot.Music";

Types

Scalar types are supported, such as double, float, int32, int64 etc. along with the string type.

Enum’s are all supported, so let’s add an enum to our file

/*
 Note definitions, where two letters are used,
 the first denotes the # (sharp) and the second 
 the b (flat)
*/
enum Note {
   C = 0;
   CD = 1;
   D = 2;
   DE = 3;
   E = 4;
   F = 5;
   FG = 6;
   G = 7;
   GA = 8;
   A = 9;
   AB = 10;
   B = 11;
}

We need to define the possible values for the enum and these must have a zero element. This obviously gives us a default value (hence zero should be your enum default value).

We’ve also added a multi-line comment using /* */ syntax, single line comments using // are also supported.

A message type can be viewed as a composite type, such as structs, i.e. we can combine types, so let’s create a request and response type (the response will be used in my next post on gRPC)

message NotesRequest {
   Note key = 1;
   string name = 2;
}

message NotesResponse {
   Note key = 1;
   string name = 2;
   repeated Note notes = 3;
}

Notice the use of = 1 etc. these are field numbers and each field must have a unique field number.

As per the Google documentation, fields in the range 1 through 15 take one byte to encode, fields 16 through to 2047 take two bytes. So yes, you could have up to 2047 fields in a message, if you really wanted.

Notice in the NotesResponse message we define a repeated keyword which denotes this field can be repeated, think of this like an array (or list) field.

Code Generation

One of the key things XML gave developers was a specification which allow developers to write tools for generating code from the data specifications. Protocol Buffers is no different and ofcourse, this makes such specification more usable to the developer.

The tool we use is protoc.exe. If you’re using Visual Studio/nuget you can install Google.Protobuf.Tools via nuget. This will then be installed to ${SolutionDir)packages\Google.Protobuf.Tools.3.6.0\tools\windows_x86 (or whichever OS you’re supporting).

Now we can run this tool from nant, or other build tools, or as a pre-build event, i.e. selecting your project in Visual Studio, right mouse clicking, selecting Properties then Build Events.

Here’s an example command (formatted to make it readable)

$(SolutionDir)packages\Google.Protobuf.Tools.3.6.0\tools\windows_x86\protoc.exe 
$(ProjectDir)Proto\music.proto 
-I=$(ProjectDir)Proto 
--csharp_out=$(ProjectDir)

The first line is obviously the location of the installed protoc.exe. Next up we declare where the proto file(s) is/are. We can use wildcard, i.e. *.proto, but if we have several different location for the files we will probably need to run the command multiple times.

The -I= allows us to define import directories. This isn’t really needed in the example here as we’re not importing anything. Finally we declare that we want to generate C# code into the project folder.

Note: If you want to generate the code into another folder you’ll need to ensure it already exists, protoc will not create it for you.

Once run, this command will create a C# file which will include the types/messages as well as serialization/deserialization code.

If you’re using Visual Studio to create an application which uses Protocol Buffers, then you’ll need to install the nuget package Google.Protobuf to install the library that the generated source references.

Serializing/Deserializing

Let’s create a Visual Studio Console application, in the project folder add a Proto folder (which will contain our *.proto) files. Now, added the two nuget packages (previously mentioned, Google.Protobuf.Tools and Google.Protobuf).

Next, create a file in the Proto folder named music.proto which should look like this

syntax = "proto3";

package music;

option java_package = "com.putridparrot.music";
option csharp_namespace = "PutridParrot.Music";

/*
 Note definitions, where two letters are used,
 the first denotes the # (sharp) and the second 
 the b (flat)
*/
enum Note {
   C = 0;
   CD = 1;
   D = 2;
   DE = 3;
   E = 4;
   F = 5;
   FG = 6;
   G = 7;
   GA = 8;
   A = 9;
   AB = 10;
   B = 11;
}

message NotesRequest {
   Note key = 1;
   string name = 2;
}

message NotesResponse {
	Note key = 1;
	string name = 2;
	repeated Note notes = 3;
} 

Next, add to the Pre-Build event for the solution the command line (listed previously) to generate the C# from the .proto file.

Lastly, let’s just add the following using clauses to Program.cs

using PutridParrot.Music;
using Google.Protobuf;

and here’s the code to place in Main

var request = new NotesRequest
{
   Key = Note.C,
   Name = "Major"
};

using (var w = File.Create(@"C:\Data\request.dat"))
{
   request.WriteTo(w);
}

NotesRequest request2;
using (var r = File.OpenRead(@"C:\Data\request.dat"))
{
   request2 = NotesRequest.Parser.ParseFrom(r);
}

This will create a file request.dat with the request instance data and then, if all goes well, load the contents of the file into the request2 variable and that’s all there is to it.

We can stream the object using the WriteTo and ParseForm methods but Protocol Buffers also supports gRPC which we’ll look at in the next post.

Code available here https://github.com/putridparrot/blog-projects/tree/master/ProtocolBuffers/CSharp

It’s been a long time JDBC…

As I’m working in Java again. I’m having to reacquaint myself with various Java lanaguge features and libraries.

It’s been a long time since I’ve had to use JDBC, but here’s a snippet of code to demonstrate a accessing an Oracle LDAP datasource.

// import java.sql.*;

Properties connectionProps = new Properties();
connectionProps.put("user", "YOUR_USER_NAME");
connectionProps.put("password", "YOUR_PASSWORD");

Connection conn = DriverManager.getConnection(
   "jdbc:oracle:thin:@ldap://SOME_URL:SOME_PORT/,cn=OracleContext,dc=putridparrot,dc=com",
                    connectionProps);

Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery("select id, blob from SOME_TABLE");

while(rs.next()) {
   String id = rs.getString(1);
   String blob = rs.getString(2);
   // do something with the results
}

Where to store your application data?

Actually I don’t intend to answer the question “Where to store your application data?” because this will depend on your requirements, but what this post will look at is, some of the options available and hopefully help shed light on what best suits your application.

Application data can be separated into two types, user specific data and application specific data (or if you prefer “All User” data).

Obviously multiple user’s might have access to a single machine but an application may be available to all users of a machine, hence we need a way to store settings specific to each user on the machine, for example user preferences. However we also may have application specific data, maybe the application stores a list of URL’s specific, in essence global settings.

Let’s look at some of our options for storing data…

Within your application’s folder

Obviously we could simply store configuration data etc. along with the application, one way to locate this folder is, as follows

var folder = Path.GetDirectoryName(
   Assembly.GetExecutingAssembly().Location) +
   Path.DirectorySeparatorChar + 
   SettingsFileName;

Here we might store a file for application specific data then create another file using the username (here we can use the Environment.UserName) of the user logged into the machine for each user.

This is a simple solution and in some cases more than adequate, plus it has the benefit that if we delete the application (i.e. it wasn’t installed via an installer) then we delete any configuration files.

Program Data

The ProgramData folder is on the system drive and is hidden by default (see C:\ProgramData). As can be inferred from the name, it’s generally used for settings specific to the application itself, i.e. not based upon specific users on a machine.

We can access it using the following code

var folder = Path.Combine(
   Environment.GetFolderPath(
      Environment.SpecialFolder.CommonApplicationData),
      "YourAppName");

Interestingly you can access the ProgramData using C:\Users\AllUsers in File Explorer, although File Explorer will state that you are in C:\Users\AllUsers it’s the same folder as C:\ProgramData.

Program Data can also be located using the environment variable %programdata%.

User Data

So we’ve seen that we can use the Environment.UserName to combine with our file name to create user files, but Windows already has the capability locations for user data. Plus, depending how your OS is set up, this data may be used across any machine a user logs into (known as Roaming).

The default location for the following “User Data” folders is under the location C:\Users\<username>\AppData

Local

The Local folder can be located using the special folder LocalApplicationData, for example

var folder = Path.Combine(
   Environment.GetFolderPath(
      Environment.SpecialFolder.LocalApplicationData),
      "YourAppName");

and is also available via the environment variable %localappdata%.

This location contains data that cannot be stored in the Roaming folder, for example data that’s specific to the machine the user is logged into or that is too large to store in a synchronized roaming folder (i.e. where Roaming folders are synchronized with a server).

Roaming

As hinted at in the section on the Local folder. The Roaming folder can be synchronized with a server, i.e. this is a profile which is accessible from other machines that a user logs into on the same domain. Hence anything stored here will “follow” the user around and so is very useful for preferences, favourites etc. However the space available may be limited depending upon quota settings or other space limitations.

To access this folder we simply use the ApplicationData special folder or environment variable %appdata%, for example

var folder = Path.Combine(
   Environment.GetFolderPath(
      Environment.SpecialFolder.ApplicationData),
      "YourAppName");

LocalLow

The LocalLow folder is basically a restricted version of the Local folder. The data is not synchronized with a server and hence does not move from the machine its created on and it has a lower level of access.

When I say “restricted” or “lower level access” basically this means the application being run, itself has security constraints placed upon it.

The LocalLow folder does not have an entry within the SpecialFolder enumeration, so access the folder you need to use the following (copied from Thomans Levesque’s answer on StackOverflow – https://stackoverflow.com/questions/4494290/detect-the-location-of-appdata-locallow)

[DllImport("shell32.dll")]
static extern int SHGetKnownFolderPath(
   [MarshalAs(UnmanagedType.LPStruct)] Guid rfid, 
   uint dwFlags, 
   IntPtr hToken, 
   out IntPtr pszPath);

public static string GetFolderLocalLow()
{
   var pszPath = IntPtr.Zero;
   try
   {
      var hr = SHGetKnownFolderPath(folderGuid, 0, IntPtr.Zero, out pszPath);
      if (hr < 0)
      {
         throw Marshal.GetExceptionForHR(hr);
      }
      return Marshal.PtrToStringAuto(pszPath);
   }
   finally
   {
      if (pszPath != IntPtr.Zero)
      {
         Marshal.FreeCoTaskMem(pszPath);
      }
   }
}

Accessing location via the environment variables

In a few places I’ve shown the environment variable for each of the locations mentioned. We can also use these variables to locate the folders, for example

var location = 
   Environment.ExpandEnvironmentVariables("%AppData%")

This will result in returning the Roaming folder location, but what’s nice is this static method will work with environment variables combined with file locations (as you’d probably expect), so for example

var location = 
   Environment.ExpandEnvironmentVariables("%AppData%\MyApp")

This will return a path along the lines C:\Users\<username>\AppData\Roaming\MyApp

Source added to https://github.com/putridparrot/blog-projects/tree/master/FileLocations

The WPF Hyperlink

WPF comes with a HyperLink class, but it’s from the System.Windows.Documents namespace, so is mean’t to be embedded within a textual control, such as a TextBlock (i.e. it’s not a standalone control like the System.Windows.Forms.LinkLabel) and within WPF it doesn’t support opening the supplied Uri in an associated process.

Let’s see it’s usage in some XAML

<TextBlock>
   <Hyperlink NavigateUri="http://putridparrot.com/blog/the-wpf-hyperlink">
   The WPF Hyperlink
   </Hyperlink>
</TextBlock>

This XAML will display a the text “The WPF Hyperlink” with underline and when you move your mouse over the link it’ll change colour and the mouse cursor will change to the hand cursor, but clicking on the link will not result in any web browser (or other associated application opening). We must implement such functionality ourselves either responding to the Click event or supplying an ICommand to the Command property.

Here’s a simple example of the sort of code we’d use to running the Uri via it’s associated application.

var process = new Process
{
   StartInfo = new ProcessStartInfo(Uri)
};
process.Start();

We can use databinding to supply the NavigateUri in the standard way, but if you wanted to change the displayed text, then we need to embed another control into the Hyperlink. For example, here we’re using another class from the System.Windows.Documents namespace, the Run class

<TextBlock>
   <Hyperlink NavigateUri="{Binding Uri}">
      <Run>
         <Run.Text>
            <Binding Path="DisplayText"/>
         </Run.Text>
      </Run>
   </Hyperlink>
</TextBlock>

Turning XAML into objects using XamlReader

I couldn’t come up with a good title for this post, basically the post is about taking a XAML declared Style and finding the easiest way to turn this into a Style object in code.

I had a problem whereby I ended up with multiple style objects which were exactly the same except for the DataItem they were binding to. This ended up meaning I had lots of duplicate XAML code, apart from one difference. Once I started making the code more dynamic (it was adding columns to the Infragistics XamDataGrid) this XAML became almost useless as I needed to create a style for each dynamically added column and hence really need to generate the Style in code.

If you’ve done anything much with code behind for such things as creating Style objects or replicating XAML code you’ve probably found the code doesn’t always map directly to the XAML, and if you already have XAML that works, why not simply reused it.

Note: The reason the code doesn’t always map is that it includes resources, converters and other XAML magically things that are automatically applied, for example converting colour names to colour values, or field lengths etc.

So let’s simple copy our XAML into a string in code and then programmatically change the DataItem field and then generate our Style object from this.

Here’s an example of the XAML as a string

var styleString = 
   "<Style TargetType=\"{x:Type idp:CellValuePresenter}\">" +
   "<Setter Property=\"Template\">" +
   "<Setter.Value>" +
   "<ControlTemplate>" +
   "<Grid>" +
   "<ListBox ItemsSource=\"{Binding DataItem." + source + "}\">" +
   "<ListBox.ItemTemplate>" +
   "<DataTemplate>" +
   "<TextBlock HorizontalAlignment=\"Stretch\" Text=\"{Binding}\"/>" +
   "</DataTemplate>" +
   "</ListBox.ItemTemplate>" +
   "<ListBox.ItemsPanel>" +
   "<ItemsPanelTemplate>" +
   "<StackPanel Orientation=\"Vertical\"/>" +
   "</ItemsPanelTemplate>" +
   "</ListBox.ItemsPanel>" +
   "</ListBox>" +
   "</Grid>" +
   "</ControlTemplate>" +
   "</Setter.Value>" +
   "</Setter>" +
   "</Style>";

In the above we’d obviously supply the source variable and this will then form part of our XAML style. To turn this into a Style object we need to use the XamlReader.Parse method. Before we can use the XamlReader.Parse method we also need to create the namespaces (context items) that we would expect from our XAML code, in this case we create a ParseContent object and assign our namespaces, then pass this into the XamlReader.Parse method also with the styleString. Our code might look like the following

public Style CreateStyle(string source)
{
   var context = new ParserContext();
   context.XmlnsDictionary.Add
   ("", 
    "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
   context.XmlnsDictionary.Add
   ("x", 
    "http://schemas.microsoft.com/winfx/2006/xaml");

   // other namespaces for XamaDataGrid etc.

   var styleString = 
      "<Style TargetType=\"{x:Type dataPresenter:CellValuePresenter}\">" +
      "<Setter Property=\"Template\">" +
      "<Setter.Value>" +
      "<ControlTemplate>" +
      "<Grid>" +
      "<ListBox ItemsSource=\"{Binding DataItem." + source + "}\">" +
      "<ListBox.ItemTemplate>" +
      "<DataTemplate>" +
      "<TextBlock HorizontalAlignment=\"Stretch\" Text=\"{Binding}\"/>" +
      "</DataTemplate>" +
      "</ListBox.ItemTemplate>" +
      "<ListBox.ItemsPanel>" +
      "<ItemsPanelTemplate>" +
      "<StackPanel Orientation=\"Vertical\"/>" +
      "</ItemsPanelTemplate>" +
      "</ListBox.ItemsPanel>" +
      "</ListBox>" +
      "</Grid>" +
      "</ControlTemplate>" +
      "</Setter.Value>" +
      "</Setter>" +
      "</Style>";

   return (Style)XamlReader.Parse(styleString, context);
}

That’s it – much simpler that create each piece of the Style using C# objects and allows us to first test our XAML out then reused it to generate our objects in code.

Note: If your code relied on namespaces/assemblies which are not already loaded you will have to load them into memory yourself before they can be used in this way.

Xamarin Forms (>= 3.0) supports CSS

In my previous post Styles in Xamarin Forms I demonstrated creating a simple styles using XAML Style objects. However, as of version 3.0 of Xamarin Forms, you can also use CSS (Cascading Style Sheet) files/syntax to define your styles.

XAML Style is quite a verbose way of defining styles but if you’re used to WPF or UWP it’s probably something you’re quite happy with. If, however, you come from a web background you’ll probably be used to CSS files instead. Now you can use similar syntax to define your styles for Xamarin Forms (3.0 or above).

If you create a standard mobile application in Visual Studio you’ll get a simple ContentPage based application – as per the previous post we’re going to start off by simply defining a Lime green background for our ContentPage’s.

Now simply add a CSS file (mine’s named Styles.css) to your solution and set it’s Build Action to Embedded resource and place the following into the file

^ContentPage {
     background-color: Lime;
}

Note: the CSS is case insensitive, but I’ve stuck to using the case associated with the controls/page here.

Notice the use of the ^ followed by the base type. If you read my previous post Styles in Xamarin Forms, you’ll notice that this is equivalent to an implicit style. i.e. it’s applied to anything of the type ContentPage.

To use this style we need to add the following to our ContentPage XAML

<ContentPage.Resources>
   <StyleSheet Source="Styles.css" />
</ContentPage.Resources>

Note: you do NOT need to add any namespace to use the StyleSheet (or at least I didn’t at the time of writing). if Visual Studio or Resharper suggests you need to add a namespace, just ignore it.

Now if you run your application you’ll be presented with the Lime background ContentPage.

If you’re used to CSS you’ll know that you can also declare an id (the equivalent of an explicit style) to your CSS. Let’s change our CSS to this following

#ContentStyle {
     background-color: Lime;
 }

Now we can assign this to either the StyleId or it will fallback to using x:Name (if no StyleId is set) on our control. For example

StyleId="ContentStyle"

or if you prefer you can simply use the x:Name (remember no StyleId should exist)

x:Name="ContentStyle"

We can also declare our CSS using CLASS selectors such as

.ContentStyle {
     background-color: Lime;
}

Now we would use the StyleClass attribute on our ContentPage instead of StyleId or x:Name, i.e.

StyleClass="ContentStyle"

Finally, we can also declare CSS for child elements, so for example CSS for the Label which is a child of a StackLayout would look like this

StackLayout Label {
    background-color: Lime;
}

See Selector reference for more on selector syntax, which also demonstrated setting style for direct child objects etc.

References

Styling Xamarin.Forms apps using Cascading Style Sheets (CSS)
Styling Xamarin.Forms Apps with CSS

Styles in Xamarin Forms

Like WPF and UWP, Xamarin Forms supports the ability to “style” your application controls.

We can explicitly apply styles by creating a style with a key and explicitly assigning that style to a control. Alternatively we can implicitly apply styles be declaring the type (only) that the style applies to.

Let’s just do something very simple and make our ContentPage a rather bright Lime colour.

Explicit Style

After creating a mobile application within Visual Studio (which will default to using a ContentPage) simply add the following to the App.xaml, within the Application.Resources element.

<ResourceDictionary>
   <Style x:Key="ContentStyle" TargetType="ContentPage" >
      <Setter Property="BackgroundColor" Value="Lime" />
   </Style>
</ResourceDictionary>

In this example, we’ve declared the x:Key as ContentStyle. This is an explicit style in that, to use it, we need to set the Style property on the ContentPage that we want to apply this style to.

Open the MainPage.xaml (or any other ContentPage xaml files you have) and add the following as an attribute to the ContentPage

Style="{StaticResource ContentStyle}"

If you run the application you’ll be presented with a ContentPage with a bright Lime background colour.

If you’ve come from using WPF or UWP you’ll know you can also declare styles to the resource of your page’s so they’re scoped solely to that page. The App.xaml is globally scoped.

Implicit Style

Now, if all our ContentPage objects were to use this style, we might prefer to not have to assign the style each time. Instead we can change our App.xaml Style to look like this

<Style TargetType="ContentPage" ApplyToDerivedTypes="True">
   <Setter Property="BackgroundColor" Value="Lime" />
</Style>

Notice, we’ve removed the x:Key and added the ApplyToDerivedTypes. Now remove the Style attribute from your, previously created, ContentPage and run the application again and you’ll see the Style is automatically applied to all ContentPage objects.

Note: You can use TargetType=”{x:Type ContentPage}”, this more verbose way of declaring the TargetType is not required.

Using the Xamarin Forms ListView

The ListView (as probably expected) allows us to display a list of data items, just like WPF/XAML we can alter the list item (or ViewCell) to display a custom view of our data, including images, buttons etc.

Bind to the ItemsSource property

For some unknown reason, I continually forget that the property used to bind our list of items to on a ListView is ItemsSource, not BindingContext, so just putting this note to myself Bind to the ItemsSource.

Okay back to the post…

Basic use of the ListView

In the case where we have a list of items, such as strings, then we can simply use

<ListView ItemsSource="{Binding Items}" />

assuming we have a view model which exposes an Items property which is a collection (i.e. ObservableCollection or the likes).

Displaying more complex items

As you’d probably expect, if you’re trying to display a non-primitive type, you can override the class ToString method to return a string representation of the data, for example if we’re trying to display for the type SlightlyLessBasicItemViewModel

public class SlightlyLessBasicItemViewModel
{
   public string Key { get; set; }
   public string Value { get; set; }

   public override string ToString()
   {
      return $"{Key} : {Value}";
   }
}

However, it’s also likely that we’ll want to formatting, images. buttons etc. into a list view item at which point we need to create our own item template.

If we assume we have a view model with an Items collection of SlightlyLessBasicItemViewModel we might like to display our row/cell with the key in bold and the value italic, for example we would use something like

<ListView ItemsSource="{Binding Items}">
   <ListView.ItemTemplate>
      <DataTemplate>
         <ViewCell>
            <StackLayout Orientation="Horizontal" VerticalOptions="Center">
               <Label Text="{Binding Key}" FontAttributes="Bold" />
               <Label Text="{Binding Value}" FontAttributes="Italic" />
             </StackLayout>
          </ViewCell>
       </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Grouping

The ListView supports grouping, i.e. displaying something slightly different to indicate that the items belong to a group. Let’s create the following

public class GroupViewModel : 
   ObservableCollection<SlightlyLessBasicItemViewModel>
{
   public string GroupName { get; set; }
}

Now our main view model will return an Items collection of GroupViewModel types, each GroupViewModel will act as a separate header (and bind to the GroupName for the group heading) and the items will then be displayed beneath each grouping name in the ListView.

All we need to do to our XAML is add IsGroupingEnabled=”True” and then tell the List view to display the GroupName using GroupDisplayBinding=”{Binding GroupName}”. For completeness, here’s the full XAML for this

<ListView ItemsSource="{Binding Items}" 
      IsGroupingEnabled="True"
      GroupDisplayBinding="{Binding GroupName}">
   <ListView.ItemTemplate>
      <DataTemplate>
         <ViewCell>
            <StackLayout Orientation="Horizontal" VerticalOptions="Center">
               <Label Text="{Binding Key}" FontAttributes="Bold" />
               <Label Text="{Binding Value}" FontAttributes="Italic" />
            </StackLayout>
         </ViewCell>
      </DataTemplate>
   </ListView.ItemTemplate>
</ListView>

We can also add the GroupShortNameBinding binding to add to the jump list for jumping to specific parts of our list.

Ofcourse it’s also likely we’re want to override the cell that displays the group. To do this we override the GroupHeaderTemplate (we no longer need the GroupDisplayBinding if we’re taking over the displaying of it). So for example here’s out new group header template displayed in bright green

<ListView ItemsSource="{Binding Items}" 
      IsGroupingEnabled="True">
   <ListView.ItemTemplate>
      <DataTemplate>
         <ViewCell>
            <StackLayout Orientation="Horizontal" VerticalOptions="Center">
               <Label Text="{Binding Key}" FontAttributes="Bold" />
               <Label Text="{Binding Value}" FontAttributes="Italic" />
            </StackLayout>
         </ViewCell>
      </DataTemplate>
   </ListView.ItemTemplate>
   <ListView.GroupHeaderTemplate>
      <DataTemplate>
         <ViewCell>
            <StackLayout Orientation="Horizontal" VerticalOptions="Center">
               <Label Text="{Binding GroupName}" TextColor="Chartreuse"/>
            </StackLayout>
         </ViewCell>
      </DataTemplate>
   </ListView.GroupHeaderTemplate>
</ListView>

Headers and Footers

Along with groupings we can define headers (displayed as you’d expect at the top of the list view) and footers (yes, these are displayed at the end of the list view). Again, like groupings, we can create/use the default look and feel or override it, so here’s an example with the default look and feel (as our ListView XAML’s getting rather large I’ll show an abridge version to just show the changes here, source for this post will be available on my GitHub repos).

Note: I’m not going to change the view model (the GroupingViewModel) used in this example but instead hard code the header and footer, ofcourse you can data bind to these from your view model just as we’ve done for groups etc.

<ListView ItemsSource="{Binding Items}" 
   IsGroupingEnabled="True" 
   Header="---Header---"
   Footer="---Footer---">
</ListView>

Now let’s override our templates to customise the display of our header and footer. Remove the text only from the Header and Footer attributes. We’ll need the attributes still to tell the ListView to display a header and footer. Then we added our HeaderTemplate and FooterTemplate, for example

<ListView ItemsSource="{Binding Items}" 
   IsGroupingEnabled="True" 
   Header="" Footer="">
<!-- other content -->
   <ListView.GroupHeaderTemplate>
      <DataTemplate>
         <ViewCell>
            <StackLayout Orientation="Horizontal" VerticalOptions="Center">
               <Label Text="{Binding GroupName}" TextColor="Chartreuse"/>
            </StackLayout>
         </ViewCell>
      </DataTemplate>
   </ListView.GroupHeaderTemplate>
   <ListView.HeaderTemplate>
      <DataTemplate>
         <StackLayout Orientation="Horizontal">
            <Label Text="---" TextColor="Crimson" />
            <Label Text="Header" TextColor="DarkOrange"/>
            <Label Text="---" TextColor="Crimson" />
         </StackLayout>
      </DataTemplate>
   </ListView.HeaderTemplate>
   <ListView.FooterTemplate>
      <DataTemplate>
         <StackLayout Orientation="Horizontal">
            <Label Text="---" TextColor="Orange" />
            <Label Text="Footer" TextColor="Crimson"/>
            <Label Text="---" TextColor="Orange" />
         </StackLayout>
      </DataTemplate>
   </ListView.FooterTemplate>
</ListView>

Different (or uneven) row heights

In some situations we might want the ListView to display rows with different heights. By default all rows will have the same height, we simply need to set HasUnevenRows=”True” in the ListView and then, assuming our ItemTemplate expands to fit the data it’s given, we’ll get rows of differing sizes.

This example is slightly contrived to save creating another view model, so we’ll make the changes to the ItemTemplate to support larger labels and also to expand so when the label wraps the row expands. Here’s the changes to the ListView

<ListView ItemsSource="{Binding Items}" 
     IsGroupingEnabled="True" Header="" Footer="" 
     HasUnevenRows="True">
   <ListView.ItemTemplate>
      <DataTemplate>
         <ViewCell>
            <StackLayout Orientation="Horizontal" 
               VerticalOptions="StartAndExpand">
               <Label Text="{Binding Key}" FontAttributes="Bold" FontSize="24"/>
               <Label Text="{Binding Value}" FontAttributes="Italic" FontSize="24"/>
            </StackLayout>
         </ViewCell>
      </DataTemplate>
   </ListView.ItemTemplate>
<!-- other content -->
</ListView>

Pull to refresh

A paradigm used in mobile list views is the idea of pulling the list view to refresh it, for example maybe the list view displays a list of email messages, instead of automatically updating the list the user might see an indicator which says more messages are pending, then the user pulls the list to refresh/update the view.

To add such functionality we need to add the IsPullToRefreshEnabled=”True” to the ListView itself and then we’ll need our view model to supply a RefreshCommand and also a boolean property to tell the UI when the refresh has completed.

So let’s go back to a very basic list view and view model. Here’s my view model

public class PullToRefereshViewModel : ViewModel
{
   public PullToRefereshViewModel()
   {
      RefreshCommand = new ActionCommand(() =>
      {
         Items.Add(DateTime.Now.ToString());
         IsRefreshing = false;
      }); 
   }

   [CreateInstance]
   public ExtendedObservableCollection<string> Items
      => GetProperty<ExtendedObservableCollection<string>>();

   public ICommand RefreshCommand { get; }

   public bool IsRefreshing
   {
      get => GetProperty<bool>();
      set => SetProperty(value);
   }
}

Note: I’m using my Presentations.Core view model code which hopefully is fairly obvious.

Here’s the list view

<ListView ItemsSource="{Binding Items}" 
   IsPullToRefreshEnabled="True" 
   RefreshCommand="{Binding RefreshCommand}"
   IsRefreshing="{Binding IsRefreshing}"/>

When the user pulls the ListView down, it (assuming IsPullToRefreshEnabled is true and the supplied RefreshCommand CanExecute is true) will set IsRefreshing to true and display a activity/busy indicator. It will then call the ICommand assigned to RefreshCommand. However after the command completes the IsRefreshing will need to be set to false to hide the activity/busy indicator. It sort of feels like this should happen automatically when the command finishes, but seems it’s down to the view model to reset this flag.

Note: It’s important that the IsRefreshing is set to false or you’ll be stuck the busy indicator being displayed. Therefore, it’s probably best to put the code to reset IsRefreshing into a finally block if there’s chances of exceptions in the refresh command code.

Context Menu/Actions

We can add a context menu/action to the cell of a listview, for example a Delete option when the cell is tapped the option to delete the selected cell should appear.

We’ll extend the “Pull to Refresh” example by adding an ItemTemplate and changing the view model a little. Here’s the ItemTemplate

<ListView.ItemTemplate>
   <DataTemplate>
      <ViewCell>
         <ViewCell.ContextActions>
            <MenuItem Text="Delete" 
               Command="{Binding DeleteCommand}" 
               IsDestructive="True" />
          </ViewCell.ContextActions>
          <StackLayout>
             <Label Text="{Binding Value}" VerticalOptions="Center" />
          </StackLayout>
      </ViewCell>
   </DataTemplate>
</ListView.ItemTemplate>

Note: the use of IsDestructive=”True” has significance on iOS devices, only a single action can have this set to true.

In this example we need to move away from using a collection of strings for the ItemSource and have a class with a DeleteCommand on it, hence in the example above the cell label binds to a Value property on this new class. Here’s one possible way of implementing the view model for this along with the replacement for the PullToRefreshViewModel

public class ItemViewModel : ViewModel
{
   private readonly ContextMenuViewModel _parent;
   
   public ItemViewModel(ContextMenuViewModel parent, string value)
   {
      _parent = parent;
      Value = value;
      DeleteCommand = new ActionCommand<ItemViewModel>(s =>
      {
         _parent.Items.Remove(this);
      });
   }

   public ICommand DeleteCommand { get; }

   public string Value
   {
      get => GetProperty<string>();
      set => SetProperty(value);
   }

   public class ContextMenuViewModel : ViewModel
   {
      public ContextMenuViewModel()
      {
         RefreshCommand = new ActionCommand(() =>
         {
            Items.Add(new ItemViewModel(this, DateTime.Now.ToString()));
            IsRefreshing = false;
         });
      }

      [CreateInstance]
      public ExtendedObservableCollection<ItemViewModel> Items
         => GetProperty<ExtendedObservableCollection<ItemViewModel>>();

      public ICommand RefreshCommand { get; }

      public bool IsRefreshing
      {
         get => GetProperty<bool>();
         set => SetProperty(value);
      }
}

Note: there are several ways we might want this sort of code to work, this is just one example.

Code for the samples

Code for the samples listed, can be found at GitHub https://github.com/putridparrot/blog-projects/tree/master/ListViewExamples

Upgrading Xcode and Visual Studio for Mac

This post is a note to myself – after upgrading Xcode to 9.4 I found that Visual Studio for the Mac seemed to fail to run on the iOS simulator, instead what happens when you run the VS is that it simply stops, no errors are shown, nothing.

What to do after upgrading Xcode

After upgrading/updating Xcode, always run Xcode to allow it to install any updates. Part of the upgrade might be that the Visual Studio for Mac has updated the simulator, in my case this is what had happened. Xcode 9.4 had the 11.4 version simulator whereas Visual Studio for Mac listed version 11.3.

Running Xcode installed pending updates but I also needed to go to the Xcode Preferences and in the accounts tab, ensure I was signed in (if the login has expired).

Now Visual Studio for Mac displayed the correct versions of the simulator and all worked again.

Monitoring your application using App Center

Microsoft’s App Center (https://appcenter.ms/apps) allows us to do several things, including build and distribution of our application(s), but what I’m interested in for this post, is the capabilities which allow us to monitor some usage information, tracing events and viewing exceptions.

Within App Center you need to create an application and tell App Center what OS and Platform is being used and it will respond by supplying you with information on how to “embed” App Center code into your application.

Once we’ve created an application in App Center we’ll be supplied with a key (currently you need a key per OS application).

Let’s now create a simply test application using Xamarin.Forms, although you can create a standard UWP application if you prefer.

Note: at this time WPF does not seem to be fully supported.

Creating our Xamarin.Forms application

  • In Visual Studio, select Mobile App (Xamarin.Forms) project, this will allow us to create a UWP, IOS and Android application (ensure all three platforms are selected).
  • Now add the two NuGet packages, Microsoft.AppCenter.Analytics and Microsoft.AppCenter.Crashes to each platform specific project.

Inside the shared project, edit the App.xaml.cs adding the following using clauses

using Microsoft.AppCenter;
using Microsoft.AppCenter.Analytics;

and within the OnStart, add the following code

AppCenter.Start(
   "android=ANDROID_KEY;" +
   "uwp=UWP_KEY;" +
   "ios=IOS_KEY",
   typeof(Analytics), 
   typeof(Crashes));

For each platform you need to create a new application key within App Center. If you are only intending to create a single platform version of your application, for example a UWP application, you can use the following instead

AppCenter.Start(UWP_KEY,
   typeof(Analytics), 
   typeof(Crashes));

If we now run our application, App Center will start to log each time the application is run along with information regarding the OS being used, but what if we want to start to track certain usage, for example to find out if a feature is actually being used.

Exceptions and crash reporting

Crash/Exception reporting is enabled by default but obviously if you’re running inside the Debugger in Visual Studio, this may intercept such exceptions before they get sent to the App Center, so if your using a mobile device, you’ll need to actually deploy the application to test any exception handling.

However in instances where we want to both handle an exception (probably most cases) and log/track the exception we use code like the following

try
{
   // do something
}
catch(Exception e) 
{
   Crashes.TrackError(e);
}

We can also supply a dictionary with additional information to TrackError, for example

try
{
   // do something
}
catch(Exception e) 
{
   Crashes.TrackError(e, new Dictionary<string, string>
   {
      { "WithFile", filename }
   });
}

Tracking events

To track events, simple add the following line (obviously replacing the text with whatever you want to see in App Center when an event occurs).

Analytics.TrackEvent("New Feature Used");

we can also supply more information to the event tracking, by supplying a dictionary to the TrackEvent method, for example

Analytics.TrackEvent("New Feature Used", new Dictionary<string, string>
{
   { "WithFile", filename }
});

Turning Analytics on/off

Obviously you might want to have a configuration option which allows a user to opt-in/out of analytics, simply use

Analytics.SetEnabledAsync(false);

Offline behaviour

Obviously all this is great if the application/device in connected to the internet but in situations where the application or device are offline, messages will be stored locally. The FAQ states that up to 300 logs can be stored offline and once a internet connection is restored the messages will be sent to the App Center.