ListView data binding with mutiple data templates in Xamarin Forms

This article describes the ListView data binding with multiple data/item templates in Xamarin Forms. Since this feature is being implemented in Xamarin forms, it works in all the platforms windows, android & ios.

To use multiple data templates for a ListView, use DataTemplateSelector for selecting the appropriate data template based on a type or a condition at runtime.

Note: To make use of DataTemplateSelector, ensure to update the Xamarin forms package to latest stable version (should be >=2.1).

Let’s create a simple chat user interface and distinguish the messages as incoming and outgoing as in below screenshot.


Create a Xamarin Forms project and update the Xamarin.forms package to latest stable version.
Since ListView allows you to display a list of data using cells, create a custom incoming message cell and outgoing message cell.

Incoming Message XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
            
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            
x:Class="ListViewBinding.UserControls.InBoundViewCell">
  <StackLayout>
    <Grid Margin="5">
      <Grid.RowDefinitions>
         <RowDefinition Height="*"></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>
      </Grid.RowDefinitions>
       <Grid.ColumnDefinitions>
         <ColumnDefinition Width="0.15*"></ColumnDefinition>
        <ColumnDefinition Width="0.85*"></ColumnDefinition>
      </Grid.ColumnDefinitions>
      <Grid Grid.Row="0" Grid.Column="1" BackgroundColor="#ffffff" Padding="5">
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"></RowDefinition>
          <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Label Grid.Row="0" Text="{Binding MessageText}" Margin="10,10,10,0" FontSize="22" TextColor="#7799CC"></Label>
      </Grid>
    </Grid>
  </StackLayout>
</ViewCell>

Outgoing Message XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
            
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            
x:Class="ListViewBinding.UserControls.OutBoundViewCell">
  <StackLayout>
    <Grid Margin="5">
      <Grid.RowDefinitions>
         <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
      </Grid.RowDefinitions>
       <Grid.ColumnDefinitions>
         <ColumnDefinition Width="0.85*"></ColumnDefinition>
        <ColumnDefinition Width="0.15*"></ColumnDefinition>
      </Grid.ColumnDefinitions>
      <Grid Grid.Row="1" Grid.Column="0" BackgroundColor="#7799CC">
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Label Grid.Row="0" Margin="10,10,10,0" Text="{Binding MessageText}" FontSize="22">
         </Label>
      </Grid>
    </Grid>
  </StackLayout>
</ViewCell>

Create a class that inherits from DataTemplateSelector and override the OnSelectTemplate method to select a particular DataTemplate
public class MessageTemplateSelector : DataTemplateSelector
    {
        private readonly DataTemplate inBoundDataTemplate;

         private readonly DataTemplate outBoundDataTemplate;

         public MessageTemplateSelector()
        {
            this.inBoundDataTemplate = new DataTemplate(typeof(InBoundViewCell));
             this.outBoundDataTemplate = new DataTemplate(typeof(OutBoundViewCell));
         }

        protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
        {
            var messageModel = item as Message;
             return messageModel != null && messageModel.MessageType == "INBOUND" ? this.inBoundDataTemplate : this.outBoundDataTemplate;
        }
    }

Create a ListView and apply the DataTemplateSelector by creating a static resource with in the ResourceDictionary.
<ContentPage.Resources>
     <ResourceDictionary>
      <userControls:MessageTemplateSelector x:Key="MessageTemplateSelector"></userControls:MessageTemplateSelector>
    </ResourceDictionary>
  </ContentPage.Resources>
<ListView
      
x:Name="lstMessages"  
      
HorizontalOptions="Fill"
      
VerticalOptions="Fill"
      
SeparatorVisibility="None"
      
ItemTemplate="{StaticResource MessageTemplateSelector}">
    </ListView>

Finally, bind the ItemsSource to ListView as below.
var messages = new List<Message>();
             messages.Add(new Message { MessageId = 1, MessageText = "Hello! First InBound Message, right side data item", MessageType = "INBOUND" });
            messages.Add(new Message { MessageId = 2, MessageText = "Hello! First Outbound Message, left side data item", MessageType = "OUTBOUND" });

             this.Messages = new ObservableCollection<Message>(messages);

            lstMessages.ItemsSource = Messages;

Download the working sample


By Siva Jagan Dhulipalla   Popularity  (1148 Views)