C# – How to dinamically select a DataTemplate for each item in a list

Using a DataTemplateSelector, we can determine at runtime which DataTemplate to apply to show items in a ItemsControl derivated control like the GridView, ListView, ListBox, etc.

For example, suppose we have a list of items of the below type:

public class Item
{
    public string Name { get; set; }
}
 
public class TextItem  : Item
{
    public string Content { get; set; }
}
 
public class ImageItem : Item
{
    public string Url { get; set; }
}

And we want to show either text or image content in the same list, based on the actual type of the object. The solution is to create a class inheriting from DataTemplateSelector and override two methods, SelectTemplateCore(object item) and SelectTemplateCore(object item, DependencyObject container)

create a class inheriting from DataTemplateSelector and override two methods, SelectTemplateCore(object item) and SelectTemplateCore(object item, DependencyObject container)

public class MyDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate TextTemplate { get; set; }
    public DataTemplate ImageTemplate { get; set; }
 
    protected override DataTemplate SelectTemplateCore(object item)
    {
        if (item is TextItem)
            return TextTemplate;
        if (item is ImageItem)
            return ImageTemplate;
 
        return base.SelectTemplateCore(item);
    }

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        return SelectTemplateCore(item);
    }

}

Then, add the DataTemplates and create a MyDataTemplateSelector instance as page resources in XAML:

<Page.Resources>
    <DataTemplate x:Key="TextDataTemplate">
        <Border BorderBrush="LightGray" BorderThickness="1">
            <Grid HorizontalAlignment="Left" Width="400" Height="280">
                <StackPanel>
                    <TextBlock Text="{Binding Name}" Margin="15,0,15,20"
                               Style="{StaticResource TitleTextStyle}"
                        TextWrapping="Wrap" TextTrimming="WordEllipsis" MaxHeight="40"/>
                    <TextBlock Text="{Binding Content}" Margin="15,0,15,0" Height="200"
                        TextWrapping="Wrap" TextTrimming="WordEllipsis"/>
                </StackPanel>
            </Grid>
        </Border>
    </DataTemplate>
 
    <DataTemplate x:Key="ImageDataTemplate">
        <Grid HorizontalAlignment="Left" Width="400" Height="280">
            <Border Background=
                    "{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
                <Image Source="{Binding Url}" Stretch="UniformToFill"/>
            </Border>
            <StackPanel VerticalAlignment="Bottom"
                        Background=
                        "{StaticResource ListViewItemOverlayBackgroundThemeBrush}">
                <TextBlock Text="{Binding Name}"
                           Foreground=
                           "{StaticResource ListViewItemOverlayForegroundThemeBrush}"
                           Style="{StaticResource TitleTextStyle}"
                           Height="40" Margin="15,0,15,0"/>
            </StackPanel>
        </Grid>
    </DataTemplate>
 
    <local:MyDataTemplateSelector x:Key="MyDataTemplateSelector"
        TextTemplate="{StaticResource TextDataTemplate}"
        ImageTemplate="{StaticResource ImageDataTemplate}">
    </local:MyDataTemplateSelector>
</Page.Resources>

The two data templates define the layout of an item if it contains text (TextDataTemplate) or image (ImageDataTemplate). After that, we declare our DataTemplateSelector, assigning its TextTemplate and ImageTemplate properties to the data templates defined before. Finally, we use this DataTemplateSelector in the GridView declaration:

Assign your DataTemplateSelector derived instance to the ItemTemplateSelector property of your list control

<GridView
    x:Name="itemGridView"
    Padding="116,137,40,46"      
    ItemTemplateSelector="{StaticResource MyDataTemplateSelector}" 
/>

Now, we can create a list of Item elements and assign it to the ItemsSource property of GridView:

var items = new List<Item>();
 
items.Add(new TextItem
{
    Name = "First text",
    Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur..."
});
 
items.Add(new ImageItem
{
    Name = "My image 1",
    Url = "http://teixeira-soft.com/wp/wp-content/uploads/2016/01/CarresqueiraPortugal_Portugal_1920x1080.jpg"
});
 
items.Add(new ImageItem
{
    Name = "My image 2",
    Url = "http://teixeira-soft.com/wp/wp-content/uploads/2016/01/CathedralQuarry_UK.jpg"
});
 
...

// And finally assign items to the ItemsSource property of the list 
itemGridView.ItemsSource = items;
 
DataTemplateSelector
DataTemplateSelector example.
Share            
X
                                                                                                        

Leave a Reply

Your email address will not be published. Required fields are marked *