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:
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:
<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.