Customizing ListView Cells with Xamarin.Forms’ DataTemplateSelector

Nish Anil

            Many mobile apps have to display a list of data to users, so it's no surprise that the list view is a fundamental control seen in almost every app. Xamarin.Forms' <code>ListView</code> allows you to display a list of data using cells and a <code>DataTemplate</code> to bind between a data source and the cell. Using this approach, you could easily customize an existing cell or create a completely new look and feel by extending the <code>ViewCell</code>. However, this type of customization has one key limitation: the inability to render different types of cells in the same <code>ListView</code> at runtime.

Xamarin.Forms 2.1 introduces DataTemplateSelector, which is a powerful mechanism to customize the presentation of a cell at runtime. While DataTemplate is used to specify the visualization of your data objects, a DataTemplateSelector is used to choose a DataTemplate at runtime based on the value of a data-bound property.

In this blog post, we’ll be using the DataTemplateSelector to create a simple chat user interface (seen below), which will customize the look of the cell with different colors and alignment based on an incoming and outgoing message.

Getting Started with Xamarin.Forms DataTemplateSelector

Selecting a DataTemplate at runtime can be implemented in just two easy steps:

  1. Create a class that inherits from DataTemplateSelector and override the OnSelectTemplate method to select a particular DataTemplate.
  2. Wire the DataTemplateSelector to the ListView by setting the ItemTemplate property.

Create a DataTemplateSelector

To customize cells, create a custom class that inherits from DataTemplateSelector and override the OnSelectTemplate method. The parameter item provides you the bound data of the cell, which in turn can be used to write logic to generate a custom template. In this example, the binding context is a MessageViewModel, which is then used to determine which type of data template should be displayed. We have defined two DataTemplates—incomingDataTemplate and outgoingDataTemplate. The OnSelectTemplate method returns appropriate template based on if the message is incoming or outgoing. To ensure that we avoid potential memory leaks, it’s always important to keep a reference to each data template in memory.

class MyDataTemplateSelector : Xamarin.Forms.DataTemplateSelector
{
    public MyDataTemplateSelector()
    {
        // Retain instances!
        this.incomingDataTemplate = new DataTemplate(typeof(IncomingViewCell));
        this.outgoingDataTemplate = new DataTemplate(typeof(OutgoingViewCell));
    }

    protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
    {
        var messageVm = item as MessageViewModel;
        if (messageVm == null)
            return null;
        return messageVm.IsIncoming ? this.incomingDataTemplate : this.outgoingDataTemplate;
    }

    private readonly DataTemplate incomingDataTemplate;
    private readonly DataTemplate outgoingDataTemplate;
}

Applying the DataTemplateSelector in XAML

There are multiple ways you can reference the DataTemplateSelector in XAML. Either you can create an instance of the selector in your ViewModel and bind them to the ListView‘s ItemTemplate property or create a static resource within ResourceDictionary and directly reference them in ListView, as seen below:

    
  
    
      
    
  

  
    

When using DataTemplateSelectors, it’s important to keep in mind the following limitations:

  • No more than 20 templates per ListView on Android.
  • The DataTemplateSelector subclass MUST return the same template for the same data if queried multiple times.
  • The DataTemplateSelector must not return another DataTemplateSelector.
  • The DataTemplateSelector must not return new instances of a DataTemplate on each call, instead the same instance must be returned. Failure to do so will effectively disable virtualization and lead to a memory leak.

Wrapping Up

DataTemplateSelectors are a useful approach for customizing a ListView at the runtime based on a custom defined logic. In addition, since the UI code is logically separated from the code that takes care of template selections, it results in massively increased code maintainability and testability. Download the chat user interface sample shown today to get started with Xamarin.Forms 2.1’s DataTemplateSelector.

1 comment

Discussion is closed. Login to edit/delete existing comments.

  • Jonathan 0

    A very helpful idea. I look forward to implementing it.
    At this time, in your article the code sample of referencing a DataTemplateSelector in a static resource within a ResourceDictionary is empty.
    Without that example, I have to consider your first option of creating an instance of the selector in the ViewModel and then binding it to the ListView ItemTemplate property. My concern with this option is that the DataTemplate ViewCell objects would be View items. My understanding in MVVM design is that the Model should not be aware of the ViewModel and the ViewModel should not be aware of the View. If the ViewModel is creating an instance of the selector, does this violate that principle?

Feedback usabilla icon