How to: Alternate the Background Color for Rows in a ListView
This example shows three methods that you can use to alternate the Background color for rows in a ListView.
The following sections provide three methods to create a ListView with rows that alternate in Background color. The example also discusses a method for updating the view when you add or remove rows.
Method 1: Define a Style That Uses an IValueConverter to Alternate Background Color
The following example shows how to define a Style for a ListViewItem control that binds the value of the Background property to an IValueConverter.
<Style x:Key="myItemStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="Background">
<Setter.Value>
<Binding RelativeSource="{RelativeSource Self}"
Converter="{StaticResource myConverter}"/>
</Setter.Value>
</Setter>
</Style>
The following example defines a ResourceKey for the IValueConverter.
<namespc:BackgroundConverter x:Key="myConverter"/>
The following example shows the definition of the IValueConverter that sets the Background property according to the row index.
Public NotInheritable Class BackgroundConverter
Implements IValueConverter
Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As CultureInfo) As Object Implements IValueConverter.Convert
Dim item As ListViewItem = CType(value, ListViewItem)
Dim listView As ListView = TryCast(ItemsControl.ItemsControlFromItemContainer(item), ListView)
' Get the index of a ListViewItem
Dim index As Integer = listView.ItemContainerGenerator.IndexFromContainer(item)
If index Mod 2 = 0 Then
Return Brushes.LightBlue
Else
Return Brushes.Beige
End If
End Function
public sealed class BackgroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
ListViewItem item = (ListViewItem)value;
ListView listView =
ItemsControl.ItemsControlFromItemContainer(item) as ListView;
// Get the index of a ListViewItem
int index =
listView.ItemContainerGenerator.IndexFromContainer(item);
if (index % 2 == 0)
{
return Brushes.LightBlue;
}
else
{
return Brushes.Beige;
}
}
The following example shows how to define a ListView that uses Style as its ItemContainerStyle in order to provide the required layout.
<ListView Name="theListView"
ItemsSource="{Binding Source={StaticResource EmployeeData},
XPath=Employee}"
ItemContainerStyle="{StaticResource myItemStyle}" >
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding XPath=FirstName}"
Header="First Name" Width="120"/>
<GridViewColumn DisplayMemberBinding="{Binding XPath=LastName}"
Header="Last Name" Width="120"/>
<GridViewColumn DisplayMemberBinding="{Binding XPath=FavoriteCity}"
Header="Favorite City" Width="120"/>
</GridView>
</ListView.View>
</ListView>
Method 2: Derive a New Class from ListView to Alternate Background Color
The following example shows how to define a class that derives from ListView. This class overrides the PrepareContainerForItemOverride method in order to create rows that have alternating Background colors.
Public Class SubListView
Inherits ListView
Protected Overrides Sub PrepareContainerForItemOverride(ByVal element As DependencyObject, ByVal item As Object)
MyBase.PrepareContainerForItemOverride(element, item)
If TypeOf View Is GridView Then
Dim index As Integer = ItemContainerGenerator.IndexFromContainer(element)
Dim lvi As ListViewItem = TryCast(element, ListViewItem)
If index Mod 2 = 0 Then
lvi.Background = Brushes.LightBlue
Else
lvi.Background = Brushes.Beige
End If
End If
End Sub
End Class
public class SubListView : ListView
{
protected override void
PrepareContainerForItemOverride(DependencyObject element,
object item)
{
base.PrepareContainerForItemOverride(element, item);
if (View is GridView)
{
int index = ItemContainerGenerator.IndexFromContainer(element);
ListViewItem lvi = element as ListViewItem;
if (index % 2 == 0)
{
lvi.Background = Brushes.LightBlue;
}
else
{
lvi.Background = Brushes.Beige;
}
}
}
}
The following example shows how to create an instance of this class. The namespc prefix maps to a common language runtime (CLR) namespace and the corresponding assembly where the StyleSelector is defined.
<namespc:SubListView
ItemsSource="{Binding Source={StaticResource EmployeeData},
XPath=Employee}">
<namespc:SubListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding XPath=FirstName}"
Header="First Name" Width="120"/>
<GridViewColumn DisplayMemberBinding="{Binding XPath=LastName}"
Header="Last Name" Width="120"/>
<GridViewColumn DisplayMemberBinding="{Binding XPath=FavoriteCity}"
Header="Favorite City" Width="120"/>
</GridView>
</namespc:SubListView.View>
</namespc:SubListView>
Method 3: Use a StyleSelector to Alternate Background Color
The following example shows how to define a StyleSelector that defines a Style for a row. This example defines the Background color according to the row index.
Public Class ListViewItemStyleSelector
Inherits StyleSelector
Public Overrides Function SelectStyle(ByVal item As Object, ByVal container As DependencyObject) As Style
Dim st As New Style()
st.TargetType = GetType(ListViewItem)
Dim backGroundSetter As New Setter()
backGroundSetter.Property = ListViewItem.BackgroundProperty
Dim listView As ListView = TryCast(ItemsControl.ItemsControlFromItemContainer(container), ListView)
Dim index As Integer = listView.ItemContainerGenerator.IndexFromContainer(container)
If index Mod 2 = 0 Then
backGroundSetter.Value = Brushes.LightBlue
Else
backGroundSetter.Value = Brushes.Beige
End If
st.Setters.Add(backGroundSetter)
Return st
End Function
End Class
public class ListViewItemStyleSelector : StyleSelector
{
public override Style SelectStyle(object item,
DependencyObject container)
{
Style st = new Style();
st.TargetType = typeof(ListViewItem);
Setter backGroundSetter = new Setter();
backGroundSetter.Property = ListViewItem.BackgroundProperty;
ListView listView =
ItemsControl.ItemsControlFromItemContainer(container)
as ListView;
int index =
listView.ItemContainerGenerator.IndexFromContainer(container);
if (index % 2 == 0)
{
backGroundSetter.Value = Brushes.LightBlue;
}
else
{
backGroundSetter.Value = Brushes.Beige;
}
st.Setters.Add(backGroundSetter);
return st;
}
}
The following example shows how to define a ResourceKey for the StyleSelector. The namespc prefix maps to a CLR namespace and the corresponding assembly where the StyleSelector is defined. For more information, see XAML Namespaces and Namespace Mapping for WPF XAML.
<namespc:ListViewItemStyleSelector x:Key="myStyleSelector"/>
The following example shows how to set the ItemContainerStyleSelector property of a ListView to this StyleSelector resource.
<ListView
ItemsSource="{Binding Source={StaticResource EmployeeData},
XPath=Employee}"
ItemContainerStyleSelector="{DynamicResource myStyleSelector}" >
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding XPath=FirstName}"
Header="First Name" Width="120"/>
<GridViewColumn DisplayMemberBinding="{Binding XPath=LastName}"
Header="Last Name" Width="120"/>
<GridViewColumn DisplayMemberBinding="{Binding XPath=FavoriteCity}"
Header="Favorite City" Width="120"/>
</GridView>
</ListView.View>
</ListView>
Update the ListView After a Change in the ListViewItem Collection
If you add or remove a ListViewItem from a ListView control, you must update the ListViewItem controls in order to recreate the alternating Background color. The following example shows how to update the ListViewItem controls.
Dim dataView As ICollectionView = CollectionViewSource.GetDefaultView(theListView.ItemsSource)
dataView.Refresh()
ICollectionView dataView =
CollectionViewSource.GetDefaultView(theListView.ItemsSource);
dataView.Refresh();