Xamarin Forms Alternating Rows for ListView

When building a new Android app with Xamarin Forms, I needed to create alternating color rows for a ListView. I quickly came across a posting that made the job easy, but there was a problem with it. It used a Grid layout, and defined the layout twice identically, except for the background color. The problem with that is that it is an anti-pattern. Such are the things that make maintainability a nightmare. You may think that it’s just a few lines of code and not a big deal–maybe it’ll never even change. But the code can grow complex over time, and it would be easy to miss having to make a change twice to cover both different places.

With a bit of effort and help from Nirmal Subedi on StackOverflow, I found the right solution for creating alternating color rows on a ListView. The StackOverflow post that discusses this is here.

Create the DataTemplateSelector

First create the DataTemplateSelector. This is straight forward and is solely for rendering the correct DataTemplate based on whether the row is an even or an odd numbered row of the ListView.

using System.Collections;
using Xamarin.Forms;

namespace MyNamespace
{
    public class AlternateColorDataTemplateSelector : DataTemplateSelector
    {
        public DataTemplate EvenTemplate { get; set; }
        public DataTemplate UnevenTemplate { get; set; }


        protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
        {

            ListView lv = container as ListView;
            if (lv != null)
            {
                IList listItem = lv.ItemsSource as IList;
                
                int idx = listItem.IndexOf(item);
                return idx % 2 == 0 ? EvenTemplate : UnevenTemplate;
            }
            else
            {
                return UnevenTemplate;
            }
        }
    }
}

Create the Grid Layout

Define the row, together with all its bindings as a standalone Grid class object. An example is below. The binding to “Data” will need to be changed to whatever you are using for each row of the ListView.

The easiest way to do this is to add a new ContentView class, then change ContentView on the XAML and on the C# code-behind to “Grid”.

<?xml version="1.0" encoding="UTF-8"?>
<Grid xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:local="clr-namespace:MyNamespace"
             mc:Ignorable="d" 
             x:Class="MyNamespace.MasterGrid">
    <Grid.RowDefinitions>
		<RowDefinition />
	</Grid.RowDefinitions>
	<Grid.ColumnDefinitions>
		<ColumnDefinition />
		<ColumnDefinition />
	</Grid.ColumnDefinitions>
	
    <Label
		Grid.Column="0" Text={Binding Name} />
	<Label
		Grid.Column="1" Text={Binding Data} />
	
</Grid>

And the example code-behind to match:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace MyNamespace
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MasterGrid : Grid
    {
        public MasterGrid()
        {
            InitializeComponent();
        }
    }
}

Putting it all together

Which now leaves putting it all together on your PageView:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MyNamespace"
             x:Class="MyNamespace.MyPage"
             Title="Sample Alternating Color ListView">
    <ContentPage.Resources>
        <DataTemplate x:Key="evenTemplate">
            <ViewCell>
                <local:MasterGrid Background="Red" />
            </ViewCell>
        </DataTemplate>
        <DataTemplate x:Key="unevenTemplate">
            <ViewCell>
                <local:MasterGrid Background="Blue" />
            </ViewCell>
        </DataTemplate>
        <local:AlternateColorDataTemplateSelector x:Key="alternateColorDataTemplateSelector"
                EvenTemplate="{StaticResource evenTemplate}"
                UnevenTemplate="{StaticResource unevenTemplate}" />
    </ContentPage.Resources>
    <ContentPage.Content>
        <StackLayout>
            <ListView 
                ItemTemplate="{StaticResource alternateColorDataTemplateSelector}"
                ItemsSource="{Binding MyList}" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

One thought on “Xamarin Forms Alternating Rows for ListView

Comments are closed.