我遇到了DataTemplate键的奇怪行为:当通过x:Type指定DataType时,x:通过x指定Key:静态引用,x:忽略Key。我写了一个示例应用程序来说明它。
XAML资源:
<DataTemplate DataType="{x:Type wpfApplication1:TestDto}" x:Key="{x:Static wpfApplication1:DataKeys.TestDtoKey}" />
<DataTemplate x:Key="{x:Static wpfApplication1:DataKeys.TestDtoKey2}" />
<DataTemplate DataType="{x:Type wpfApplication1:TestDto}" x:Key="TestKey3" />
<DataTemplate DataType="wpfApplication1:TestDto" x:Key="{x:Static wpfApplication1:DataKeys.TestDtoKey4}" />
C#:
public class TestDto {}
public static class DataKeys
{
public static string TestDtoKey = "TestKey";
public static string TestDtoKey2 = "TestKey2";
public static string TestDtoKey4 = "TestKey4";
}
启动应用程序,请参阅this.Resources.Keys in debugger:
{DataTemplateKey(WpfApplication1.TestDto)} object {System.Windows.DataTemplateKey}
"TestKey2" object {string}
"TestKey3" object {string}
"TestKey4" object {string}
如您所见,在第一种情况下,x:Key被忽略!
有人可以解释发生了什么吗? 文档(http://msdn.microsoft.com/en-us/library/system.windows.datatemplate.datatype.aspx)清楚地表明设置x:Key会将资源键设置为您在其中指定的任何内容。
答案 0 :(得分:4)
您的问题的简短回答是 - 是的,这是WPF框架中的一个错误。 Bug报告here。
更新 -
Microsoft已经接受它是XAML编译器中的一个错误,他们并没有解决这个问题。来自微软的报价 -
这是XAML编译器中的一个问题 - 它生成BAML来描述 每个资源的密钥,通常基于x:Key(如果存在) 如果不是,则在DataType上。当x:Key本身是间接的(in 你的情况,使用x:Static),编译器选择DataType键。 选择x:基于静态的键可能更“正确”, 改变这将引入兼容性问题。还有,因为 问题发生在编译时,你必须重新编译你的应用程序才能看到 修复(生成不同的BAML流)。您的现有副本 应用程序将包含旧的BAML流,并且行为方式相同 在运行时,就像他们现在一样。出于这个原因,我们决定不会 解决了这个问题。
x:此处不会忽略键,但在第一种情况下设置为DataTemplateKey(WpfApplication1.TestDto)
。如果没有键值,则不能在Resources部分下声明资源。
正如您所看到的,此处的密钥会自动设置为DataTemplateKey(WpfApplication1.TestDto)
。
来自MSDN -
此属性与。的TargetType属性非常相似 风格课。 当您将此属性设置为不带数据类型时 指定x:Key,DataTemplate会自动应用到 该类型的数据对象。请注意,当您这样做时,设置了x:Key 隐式地。因此,如果您为此DataTemplate指定一个x:Key值, 你覆盖了隐含的x:Key,而DataTemplate却没有 自动应用。
不知何故,如果你bind x:Key with static value
而不是硬编码字符串,它会获得defined as default template for that dataType
,因此密钥设置为DataTemplateKey(WpfApplication1.TestDto)
。
您可以通过向资源添加另一个DataTemplate来验证,只设置DataType,即
<DataTemplate DataType="{x:Type wpfApplication1:TestDto}"/>
。
它将编译正常,但会抛出运行时错误
“项目已添加。键入字典: 'DataTemplateKey(WpfApplication1.TestDto)'键被添加: 'DataTemplateKey(WpfApplication1.TestDto)'“
答案 1 :(得分:1)
我不确定这会有所帮助,但请尝试将{get; set;}附加到班级中的每个属性。 WPF中的一些工作人员(即Binding)在没有它们的情况下不起作用。可能在这里是同一个故事...
public static class DataKeys
{
public static string TestDtoKey { get { return "TestKey"; } set; }
public static string TestDtoKey2 { get { return "TestKey2"; } set; }
public static string TestDtoKey4 { get { return "TestKey4"; } set; }
}