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>
I think you should make a video about this on YouTube…