使用x:Static指定时,将忽略DataTemplate键

时间:2013-10-18 14:59:00

标签: c# wpf xaml

我遇到了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会将资源键设置为您在其中指定的任何内容。

2 个答案:

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