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

前端 未结 3 990
花落未央
花落未央 2020-12-05 05:48

I have a class of MyClass and want to set it as the DataType for a HierarchicalDataTemplate.

What is the syntax for this in XAML? (I kno

相关标签:
3条回答
  • 2020-12-05 06:28

    This is not supported in WPF 3.x out of the box (I think it may be in 4.0, but I'm not sure); but it's easy to set up with a markup extension.

    First, you need to create a markup extension class that takes the type parameter as a constructor argument:

    public class MyClassOf : MarkupExtension
    {
      private readonly Type _of;
    
      public MyClassOf(Type of)
      {
        _of = of;
      }
    
      public override object ProvideValue(IServiceProvider serviceProvider)
      {
        return typeof(MyClass<>).MakeGenericType(_of);
      }
    }
    

    Now you use this markup extension in place of the x:Type extension:

    <HierarchicalDataTemplate DataType="{local:MyClassOf {x:Type MyObject}}" />
    

    Needless to say, this can be generalised to allow instantiation of arbitrary generic types; I haven't shown this because it adds a wee bit more complexity.

    0 讨论(0)
  • 2020-12-05 06:38

    itowlson's approach is a good one but it is just a start. Here's something that will work for your case (and most, if not all, cases):

    public class GenericType : MarkupExtension
    {
        public Type BaseType { get; set; }
        public Type[] InnerTypes { get; set; }
    
        public GenericType() { }
        public GenericType(Type baseType, params Type[] innerTypes)
        {
            BaseType = baseType;
            InnerTypes = innerTypes;
        }
    
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            Type result = BaseType.MakeGenericType(InnerTypes);
            return result;
        }
    }
    

    Then, you are able to create any type with any level of depth in your XAML. For example:

        <Grid.Resources>
            <x:Array Type="{x:Type sys:Type}" 
                     x:Key="TypeParams">
                <x:Type TypeName="sys:Int32" />
            </x:Array>
    
            <local:GenericType BaseType="{x:Type TypeName=coll:List`1}" 
                               InnerTypes="{StaticResource TypeParams}"
                               x:Key="ListOfInts" />
    
            <x:Array Type="{x:Type sys:Type}" 
                     x:Key="DictionaryParams">
                <x:Type TypeName="sys:Int32" />
                <local:GenericType BaseType="{x:Type TypeName=coll:List`1}" 
                                   InnerTypes="{StaticResource TypeParams}" />
            </x:Array>
    
            <local:GenericType BaseType="{x:Type TypeName=coll:Dictionary`2}"
                               InnerTypes="{StaticResource DictionaryParams}"
                               x:Key="DictionaryOfIntsToListOfInts" />
        </Grid.Resources>
    

    There's a few key ideas here:

    • A generic type has to be specified using the standard ` notation. So, System.Collections.Generic.List<> is System.Collections.Generic.List`1. The character ` indicates that the type is generic and the number after it indicates the number of generic parameters the type has.
    • The x:Type markup extension is able to retrieve these base generic types quite easily.
    • The generic parameter types are passed as an array of Type objects. This array is then passed into the MakeGenericType(...) call.
    0 讨论(0)
  • 2020-12-05 06:45

    In .NET 4.0, use below code.

    XamlNamespaceResolver nameResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlNamespaceResolver;
    IXamlSchemaContextProvider schemeContextProvider = serviceProvider.GetService(typeof(IXamlSchemaContextProvider)) as IXamlSchemaContextProvider;
    XamlTypeName xamlTypeName = new XamlTypeName(nameResolver.GetNamespace("generic"), "List`1");
    Type genericType = schemeContextProvider.SchemaContext.GetXamlType(xamlTypeName).UnderlyingType;
    

    http://illef.tistory.com/115

    0 讨论(0)
提交回复
热议问题