Máme kolekci dat a chceme např. barevně vyznačit zda-li se jedná o první či poslední řádek, nebo sudý či lichý.
Někoho by mohlo napadnout zkusit použít Trigger (+ nějaký Converter), ale podle mě je vhodnější použít tzv. DataTemplateSelector.
public class ListDataTemplateSelector : DataTemplateSelector
{
public ObservableCollection<Item> Items { get; set; }
public override DataTemplate SelectTemplate(object obj, DependencyObject container)
{
var el = container as FrameworkElement;
if ( el != null && obj != null && obj is Item )
{
Item item = obj as Item;
if ( Items.IndexOf(item)%2 == 0 )
{
return el.FindResource("even") as DataTemplate;
}
else
{
return el.FindResource("odd") as DataTemplate;
}
}
return base.SelectTemplate(obj, container);
}
}
Vytvoříme si vlastní třídu ListDataTemplateSelector , která dědí právě ze třídy DataTemplateSelector. Tato třída nabízí jednu metodu k přepsání SelectTemplate. Tato metoda se volá pro každý prvek v naší kolekci, kde si zjistíme zda-li se jedná o sudý či lichý prvek a vrátíme konkrétní šablonu (DataTemplate). Tyto šablony si můžeme např. definovat ve Window.Resources. Pro ukázku jsou mými prvky objekty třídy Item, která poskytuje jednu vlastnost Text a implementuje rozhraní IEquatable<Item>. Toto rozhraní tam je z důvodu, že využíváme metodu IndexOf objektu Collection<T>. V případě, že neimplementujeme toto rozhraní tak máme ještě možnost přepsat object metody Equals a GetHashCode. Jestliže neuděláme ani toto, tak nám bude metoda IndexOf vracet pořád –1.
public class Item : IEquatable<Item>
{
public string Text { get; set; }
public bool Equals(Item other)
{
return string.Compare(Text, other.Text, StringComparison.OrdinalIgnoreCase) == 0;
}
}
V hlavním okně MainWindow.xaml si definujeme jednotlivé šablony. Pro lichý prvek to bude elipsa a pro sudý rámeček.
<Window x:Class="DataTemplateSelectorSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:template="clr-namespace:DataTemplateSelectorSample"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="even">
<Grid>
<Ellipse Fill="LightGreen" Width="50" Height="50"/>
<TextBlock Text="{Binding Text}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="odd">
<Border Background="IndianRed" Width="50" Height="50">
<TextBlock Text="{Binding Text}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</DataTemplate>
<template:ListDataTemplateSelector x:Key="templateSelector"/>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding}"
ItemTemplateSelector="{StaticResource templateSelector}"/>
</Grid>
</Window>
Dále si nainicializujeme ListDataTemplateSelector, na který se potom odkážeme z ListBoxu pomocí StaticResource (při nastavování ItemTemplateSelector)
Na závěr si vygenerujeme testovací data aby jsme si ověřili, že vše funguje tak jak má.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var data = Enumerable.Range(0, 10).Select(x => new Item { Text = x.ToString() });
this.DataContext = data;
ListDataTemplateSelector templateSelector =
this.FindResource("templateSelector") as ListDataTemplateSelector;
templateSelector.Items = new ObservableCollection<Item>();
foreach ( var item in data )
{
templateSelector.Items.Add(item);
}
}
}
Kromě nastavení DataContextu ze kterého si ListBox získá příslušnou kolekci je ještě nutné naplnit kolekci Items našeho templateSelectoru (získáme z Resources).
Výsledná aplikace vypadá následovně:
Působí jako Microsoft Student Partner na VŠB-TU Ostrava a zároveň pracuje jako software developer.
Mezi jeho portfolio patří platforma Microsoft .NET především WPF, WCF, Silverlight, ASP.NET MVC, ale i oblast týmového vývoje a Design Patterns.
Rovněž publikuje na MSTV.cz a je držitelem ocenění Microsoft Most Valuable Professional (MVP)
Máte-li zájem o školení, konzultaci či zakázkový vývoj pak mě neváhejte kontaktovat!
email: me(at)lukaskubis.net
web: http://web.lukaskubis.net
blog: http://lukaskubis.net