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:
- Create a class that inherits from
DataTemplateSelector
and override theOnSelectTemplate
method to select a particularDataTemplate
. - Wire the
DataTemplateSelector
to theListView
by setting theItemTemplate
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 anotherDataTemplateSelector.
- 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
DataTemplateSelector
s 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
.
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...