如何在DataTemplate的DataType属性中引用泛型类型的特定实现?
这个问题是强连接到这个答案为“How to reference a generic type in the DataType attribute of a HierarchicalDataTemplate?”如何在DataTemplate的DataType属性中引用泛型类型的特定实现?
我跟着这个问题的答案的基本思路,并创造了这个数据结构:
<!-- for DictItemVM<string, Remote.Address> which is a viewmodel for a KeyValuePair<...> -->
<x:Array Type="{x:Type sys:Type}"
x:Key="KVParamsStringToRemoteAddress"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:remote="clr-namespace:Remote"
xmlns:mvvm="clr-namespace:MVVM">
<x:Type TypeName="sys:String" />
<mvvm:GenericType BaseType="{x:Type TypeName=remote:Address}"/>
</x:Array>
<mvvm:GenericType xmlns:mvvm="clr-namespace:MVVM"
BaseType="{x:Type TypeName=mvvm:DictItemVM`2}"
InnerTypes="{StaticResource KVParamsStringToRemoteAddress}"
x:Key="DictItemVMOfStringToRemoteAddress"/>
DictItemVM<T,U>
是一个视图模型为KeyValuePair<...>
和源自BaseVM。 BaseVM有一个DataTemplate视图,但我努力为DictItemVM<string, Remote.Address>
创建一个。
Remote.Address是一个复杂的值类型(存储路径和访问信息)。 Remote.Address具有自己的DataTemplate视图。
所以,现在我有静态资源“DictItemVMOfStringToRemoteAddress”,我想用它来指定一个DataTemplate:
<DataTemplate x:Key="TestKey" DataType="{StaticResource DictItemVMOfStringToRemoteAddress}">
<StackPanel>
<Label Content="UniqueName" />
<TextBox Text="{Binding UniqueName}" />
<Label Content="Key"/>
<TextBox Text="{Binding Key, Mode=OneWay}" IsEnabled="False" />
<Label Content="Value"/>
<ContentControl Content="{Binding Value, Mode=OneWay}" />
</StackPanel>
</DataTemplate>
现在这个DataTemplate中应该作为一个视图,而是用于BaseVM的观点正在被显示。
有人给我这个提示吗?
[编辑:2010-08-09]
有些事情我想:
在X:数组定义我更换<mvvm:GenericType BaseType="{x:Type TypeName=remote:Address}"/>
与<x:Type TypeName="remote:Address"/>
,
因为这是它基本上是- 没有不同。
也试过在标签之间建立数据类型(而不是链接到一个静态资源)是这样的:
<DataTemplate x:Key="TestKey">
<DataTemplate.DataType>
<Binding>
<Binding.Source>
<mvvm:GenericType
BaseType="{x:Type TypeName=mvvm:DictItemVM`2}">
<mvvm:GenericType.InnerTypes>
<x:Type TypeName="sys:String" />
<x:Type TypeName="remote:Address"/>
</mvvm:GenericType.InnerTypes>
</mvvm:GenericType>
</Binding.Source>
</Binding>
</DataTemplate.DataType>
使用和不使用X试了一下:在GenericType.InnerTypes内阵列,都让我this错误。
试图从一个静态属性传递的类型是这样的:DataType="{x:Static mvvm:StaticTypes.DictItemVMOfStringToRemoteAddress}"
像这样:DataType="{Binding Path={x:Static mvvm:StaticTypes.DictItemVMOfStringToRemoteAddress}}"
没有区别。
奇怪的是,这个特定的DataTemplate需要有一些x:Key
值,与xaml资源文件中所有指向常规类型的其他值相比,例如:DataType="{x:Type mvvm:EffectVM}"
。如果我删除了x:Key,则会出现this错误。
我找到了一个解决方案,但该解决方案并不令人满意。
在XAML中,营造一个DataTemplate你要显示的给它一些独特的X每种类型的KeyValuePair<T,U>
:关键:
<DataTemplate x:Key="DictItemOfStringAndAddressVM">
<!-- ... -->
</DataTemplate>
然后在代码隐藏,创建一个DataTemplateSelector并覆盖SelectTemplate:
public class GenericDataTemplateSelector : System.Windows.Controls.DataTemplateSelector
{
public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
{
FrameworkElement element = container as FrameworkElement;
if ((element != null) && (item != null))
{
if (item is DictItemVM<string, Remote.Address>)
{
return element.FindResource("DictItemOfStringAndAddressVM") as DataTemplate;
}
else if(item is SomeOtherComplexType)
{
// ...
}
else return base.SelectTemplate(item, container);
}
return null;
}
}
在XAML
此外,声明这个类作为一种资源:
<mvvm:GenericDataTemplateSelector x:Key="GenDataTempSelect"/>
最后,(对我来说)在ContentControl中,添加属性:
ContentTemplateSelector="{StaticResource GenDataTempSelect}"
-
缺点:
- 当创建你必须在两个位置更改代码的新的DataTemplate 。
- 每个ContentControl,ListView,...都必须设置它的适当属性。
- 没有真正回答如何在WPF中引用泛型类型的问题!
优点:
- 容易增加新类型的任何结构或复杂的(享受的所有好处C#有超过WPF ...)
- 在WPF没有复杂的嵌套类型描述,上述解决方案将需要。