Enhancing Xamarin.Forms ListView with Grouping Headers

Sometimes a plain ListView just isn’t good enough. You can easily spice it up with images or custom cells, but what about organizing the data. With C# and LINQ it is easy to sort your list, but how about giving it some visuals? How about some headers? With Xamarin.Forms it is extremely simple to add in headers and to create a custom view as well.

I am working out of my Xamarin.Forms-Monkeys project that I have blogged about before, which consists of a nice list of Monkeys with Images. You can browse this code on my GitHub.

Bindable Group Structure

There are a few examples of using headers with Xamarin.Forms, but I wanted to create an ultimate “Group” that would allow me to sort, organize any data, and that is when I came up with Grouping:

Grouping seems simple, but is very extensible, especially if using data binding. Notice that a Grouping is really just an ObservableCollection of type T. However, each Grouping also has a Key. Now this key is of type K, which means it could be anything including a complex data structure. This means you could in theory bind your header to a data structure of K and then bind multiple controls to multiple properties, which is very cool. For this example though we will just make K a string for sorting.

Sorting Our Monkeys

Before we get to our Monkeys we will create a new new public ObservableCollection<Grouping<string,Monkey> > MonkeysGrouped{get;set;} in our ViewModel. The reason for this is that we actually have multiple lists, which is a list of a list of grouped monkeys. Then we will add a new property to our monkey that we can use for sorting, which will be a name sort property:

And now we can sort our list of Monkeys in our view model, which we will set as the ItemsSource on our list view:

Enabling Headers

Enabling headers is very simple. There are a few properties to set on the ListView itself to get things going. First is to enable grouping, and then to set the property that the headers will bind to:
list.ItemsSource = viewModel.MonkeysGrouped;
list.IsGroupingEnabled = true;
list.GroupDisplayBinding = new Binding("Key"); //this is our key property on grouping.

Jump List

Of course, we could stop there, but what fun would that be, as we can add a jump list with just a single line of code:
list.GroupShortNameBinding = new Binding("Key");

This results in a nice jump list:

Custom Headers

Let’s take it one step further and implement our own custom header cell with a nice background color. Right now our Key, K, is only a string, but we could pass in a full data structure if we wanted to make the custom view more complex and bind to multiple pieces of information.

My HeaderCell is very simple and just contains a Label, which binds to Key and I am placing it inside of a StackLayout with a bit of custom padding and a background color. It should be noted that I am setting a fixed Height of 25 here as the Xamarin.Forms ListView needs to know what to render.

The last thing to do is to update the the ListView with this new template:

if(Device.OS != TargetPlatform.WinPhone)
  list.GroupHeaderTemplate = new DataTemplate(typeof(HeaderCell));

list.HasUnevenRows = true; //you might want to enable if using custom cells.

We don’t set it on Windows Phone because the default styling is standard on Windows Phone with accent colors. However, you can customize it here as well. Here is our outcome on all three platforms:

XAML?

As Charles Petzold would say… Show me the XAML! Of course it is just as easy, as all we need to do is bring over our updated ViewModel and Grouping and create the rest all in XAML:

Conclusion

It is extremely easy to not only customize your cells in your ListView, but also add rich functionality like list sorting with group headers with just a few lines of shared C# code with Xamarin.Forms!