【问题标题】:How to reference a generic type in the DataType attribute of a HierarchicalDataTemplate?如何在 HierarchicalDataTemplate 的 DataType 属性中引用泛型类型?
【发布时间】:2009-11-10 07:12:25
【问题描述】:

我有一个 MyClass<MyObject> 类,想将其设置为 HierarchicalDataTemplate 的 DataType。

这在 XAML 中的语法是什么? (我知道如何设置命名空间,我只需要语法

<HierarchicalDataTemplate DataType="{X:Type .....

【问题讨论】:

    标签: .net wpf xaml hierarchicaldatatemplate


    【解决方案1】:

    itowlson 的方法很好,但这只是一个开始。以下内容适用于您的案例(以及大多数(如果不是全部)案例):

    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;
        }
    }
    

    然后,您可以在 XAML 中创建具有任何深度级别的任何类型。例如:

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

    这里有几个关键的想法:

    • 必须使用标准 ` 表示法指定泛型类型。所以,System.Collections.Generic.ListSystem.Collections.Generic.List`1。字符 ` 表示该类型是泛型的,它后面的数字表示该类型具有的泛型参数的数量。
    • x:Type 标记扩展能够非常轻松地检索这些基本泛型类型。
    • 通用参数类型作为 Type 对象数组传递。然后将该数组传递给 MakeGenericType(...) 调用。

    【讨论】:

    • 好东西 - 帮助我解决了我的通用绑定问题!
    【解决方案2】:

    开箱即用的 WPF 3.x 不支持此功能(我认为它可能在 4.0 中,但我不确定);但是使用标记扩展很容易设置。

    首先,您需要创建一个将类型参数作为构造函数参数的标记扩展类:

    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);
      }
    }
    

    现在您使用此标记扩展代替 x:Type 扩展:

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

    不用说,这可以概括为允许任意泛型类型的实例化;我没有展示这个,因为它增加了一点点复杂性。

    【讨论】:

    • 我花了很多时间来尝试让它工作。我失败了......实际上事情要复杂得多,因为我真正拥有的 DataType 是 Dictionary> 感谢您为我指明了正确的方向。当我有更多时间时,我可能会在稍后再讨论这个问题。
    【解决方案3】:

    在 .NET 4.0 中,使用以下代码。

    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

    【讨论】:

      猜你喜欢
      • 2012-04-17
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 2013-10-28
      • 1970-01-01
      • 2011-10-08
      • 1970-01-01
      相关资源
      最近更新 更多