我有一个MyClass<MyObject>
类,并希望将其设置为HierarchicalDataTemplate的DataType。
XAML中的语法是什么? (我知道如何设置命名空间,我只需要
的语法<HierarchicalDataTemplate DataType="{X:Type .....
答案 0 :(得分:16)
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>
这里有一些关键的想法:
答案 1 :(得分:4)
WPF 3.x开箱即用不支持(我认为它可能在4.0中,但我不确定);但是使用标记扩展名很容易设置。
首先,您需要创建一个标记扩展类,它将type参数作为构造函数参数:
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}}" />
不用说,这可以推广到允许任意泛型类型的实例化;我没有表现出来,因为它增加了一点点复杂性。
答案 2 :(得分:1)
在.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;