How to reference a generic type in the DataType attribute of a DataTemplate? How to reference a generic type in the DataType attribute of a DataTemplate? wpf wpf

How to reference a generic type in the DataType attribute of a DataTemplate?


No, you cannot express a generics type in XAML. You will have to create a concrete type that extends your generic one ...

public class FooLocationTreeViewModel : LocationTreeViewModel<Foo>{}


In XAML 2006 this is not supported. You can, however, roll your own if you want to have this functionality.

This link has a nice tutorial on creating markup extensions.

Usage would be like this:

<Grid xmlns:ext="clr-namespace:CustomMarkupExtensions">  <TextBlock Text="{ext:GenericType FooLocationTreeViewModel(Of Foo)}" /></Grid>

You have to choose and implement the syntax though. I suggest the VB notation since it won't interfere like the C# notation does with < and >.


I know, that I'm a little late to the party, but I want post an answer for all those who may see this question in the future:

It is possible.

You can see the whole code in the answer to this question: DataTemplates and Generics. But since it is quite long, I will just copy the important bits. If you want more details, then look into the referenced question.

  1. You need to write a MarkupExtension which can provide a closed generic type.

    public class GenericType : MarkupExtension{    public GenericType() { }    public GenericType(Type baseType, params Type[] innerTypes)    {        BaseType = baseType;        InnerTypes = innerTypes;    }    public Type BaseType { get; set; }    public Type[] InnerTypes { get; set; }    public override object ProvideValue(IServiceProvider serviceProvider)    {        Type result = BaseType.MakeGenericType(InnerTypes);        return result;    }}
  2. Now you can define your type which closes your generic type in xaml, and then use the closed generic type as DataType of an DataTemplate.

    <Window.Resources>    <x:Array Type="{x:Type System:Type}"              x:Key="ListWithTwoStringTypes">        <x:Type TypeName="System:String" />        <x:Type TypeName="System:String" />    </x:Array>    <WpfApp1:GenericType BaseType="{x:Type TypeName=Generic:Dictionary`2}"                        InnerTypes="{StaticResource ListWithTwoStringTypes}"                       x:Key="DictionaryStringString" />    <DataTemplate DataType="{StaticResource DictionaryStringString}">        <TextBlock Text="Hi Dictionary"               FontSize="40"               Foreground="Cyan"/>    </DataTemplate></Window.Resources>
  3. Be happy that the defined DataTemplate gets automatically selected by WPF.