Home > C#, WinRT > Dynamically choose DataTemplate in WinRT

Dynamically choose DataTemplate in WinRT

18/02/2013

Using a DataTemplateSelector, we can determine at runtime which DataTemplate to apply to show items in a control like the GridView. Fo example, suppose we have the following classes:

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 GridView, based on the actual type of the object. So, we create a class inheriting from DataTemplateSelector:

public class MyDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate TextTemplate { get; set; }
    public DataTemplate ImageTemplate { get; set; }

    protected override DataTemplate SelectTemplateCore(object item, 
                                                       DependencyObject container)
    {
        if (item is TextItem)
            return TextTemplate;
        if (item is ImageItem)
            return ImageTemplate;

        return base.SelectTemplateCore(item, container);
    }
}

Then, we add the following 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:

<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 = "Primo elemento di testo",
    Content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur..."
});

items.Add(new ImageItem
{
    Name = "Piazza dei Miracoli, Pisa",
    Url = "http://wallpaperfree.myblog.it/media/02/01/2987769223.jpg"
});

items.Add(new ImageItem
{
    Name = "Spiaggia",
    Url = "http://wallpaperfree.myblog.it/media/00/00/320939694.jpg"
});

items.Add(new TextItem
{
    Name = "Altro contenuto testuale",
    Content = "Quisque sapien urna, fermentum sollicitudin vehicula in, cursus..."
});

items.Add(new TextItem
{
    Name = "Esempio",
    Content = "Sed malesuada, mauris eu scelerisque blandit, magna erat rutrum velit... "
});

items.Add(new TextItem
{
    Name = "Titolo elemento",
    Content = "Integer blandit tempor nulla, id pretium ante egestas vel..."
});

itemGridView.ItemsSource = items;

In this way, for every element in the list, MyDataTemplateSelector.SelectTemplateCore is invoked, and so the correct template is selected according to the actual type of the item. In conclusion, running our code, we obtain a result like the following:

DataTemplateSelector example

DataTemplateSelector example

Categories: C#, WinRT
%d bloggers like this: