Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / operating-systems / Windows / WinRT

DataTemplates in WinRT

4.33/5 (4 votes)
15 May 2014CPOL 11K  
DataTemplates in WinRT

While I enjoy the simpler interfaces in WinRT, I’ve been spoiled by the power of WPF. One thing I missed recently was the automatic selection of a DataTemplate based on the DataType property; this property isn’t there in WinRT.

The solutions I’ve seen use a custom DataTemplateSelector with various properties for each type. This certainly works but it felt a bit repetitive. Instead, the solution I came up with searches the resources for an item with the same key as the type name and returns that. Here’s the class:

C#
namespace AutoDataTemplate
{
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Media;

    public sealed class AutoDataTemplateSelector : DataTemplateSelector
    {
        protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
        {
            if (item == null)
            {
                return null;
            }

            object key = item.GetType().Name;
            return FindResource(key, container as FrameworkElement) as DataTemplate;
        }

        private static object FindResource(object key, FrameworkElement element)
        {
            if (element == null)
            {
                return null;
            }

            object value;
            if (element.Resources.TryGetValue(key, out value))
            {
                return value;
            }

            return FindResource(key, VisualTreeHelper.GetParent(element) as FrameworkElement);
        }
    }
}

Using this class would be something like this:

XML
<Page x:Class="AutoDataTemplate.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:adt="using:AutoDataTemplate">

    <Page.Resources>
        <adt:AutoDataTemplateSelector x:Key="AutoSelector" />
        
        <DataTemplate x:Key="ClassType1">
            <TextBlock Foreground="CornflowerBlue"
                       Text="{Binding Value}" />
        </DataTemplate>

        <DataTemplate x:Key="ClassType2">
            <TextBlock Foreground="Firebrick"
                       Text="{Binding DifferentValue}" />
        </DataTemplate>
    </Page.Resources>

    <ListView ItemsSource="{Binding}"
              ItemTemplateSelector="{StaticResource AutoSelector}"
              Padding="40" />
</Page>

Of course, there are limitations with this approach, mainly that namespaces cannot be used (i.e., you can’t have the key as local:MyType). This means it is not possible to auto select the template if two types have the same name but live in different namespaces – for my scenario, this wasn’t a problem.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)