当使用x:Static指定时,DataTemplate关键字会被忽略。

12

我在使用DataTemplate键时遇到了奇怪的行为:当通过x:Type指定DataType,且通过x:Static引用指定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:

{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将把资源键设置为您在其中指定的任何内容。


非常类似于一个漏洞。也许你应该尝试为connect.microsoft.com编写反馈? - Anatoliy Nikolaev
2个回答

4
你的问题的简短回答是——是的,这是WPF框架中的一个错误。错误报告在这里更新-
微软已经承认这是XAML编译器中的一个bug,他们不会修复这个问题。来自微软的引用-
这是XAML编译器中的一个问题-它生成BAML来描述每个资源的关键字,通常基于x:Key(如果存在)和DataType(如果不存在)。当x:Key本身是间接的时(在您的情况下,使用x:Static),编译器选择DataType键。虽然选择基于x:Static的键可能更“正确”,但改变这一点会引入兼容性问题。此外,因为该问题发生在编译时,您必须重新编译应用程序才能看到修复(生成不同的BAML流)。现有副本的应用程序将包含旧的BAML流,并且在运行时的行为与现在相同。出于这个原因,我们决定不修复这个问题。

在第一种情况下,x:Key不会被忽略,而是设置为DataTemplateKey(WpfApplication1.TestDto)。在资源部分声明资源时,必须有一个键值。

如您所见,在此处键值会自动设置为DataTemplateKey(WpfApplication1.TestDto)

来自MSDN -

此属性与Style类的TargetType属性非常相似。当您将此属性设置为数据类型而不指定x:Key时,DataTemplate将自动应用于该类型的数据对象。请注意,这样做会隐式设置x:Key。因此,如果您给此DataTemplate分配了一个x:Key值,则会覆盖隐式的x:Key,并且DataTemplate将不会自动应用。

以某种方式,如果您将x:Key绑定到静态值而不是硬编码字符串,则它将被定义为该数据类型的默认模板,因此键值将设置为DataTemplateKey(WpfApplication1.TestDto)

您可以通过向资源中添加另一个DataTemplate并仅设置DataType来验证此内容,例如:<DataTemplate DataType="{x:Type wpfApplication1:TestDto}"/>。它将编译成功,但会抛出运行时错误:“Item has already been added. Key in dictionary: 'DataTemplateKey(WpfApplication1.TestDto)' Key being added: 'DataTemplateKey(WpfApplication1.TestDto)”。

谢谢你的回答,但是你只是用不同的话重复了我说过的话。 - Pavel Tupitsyn
是的,对你的问题的简短回答就是那是一个bug。 :) - Rohit Vats
1
更新了微软的回复。他们已经接受了这个缺陷,但由于兼容性问题不会修复它。 - Rohit Vats

1

我不确定这是否有帮助,但尝试在您的类中的每个属性后附加{get;set;}。WPF中的某些组件(如绑定)可能无法正常工作。也许这里是同样的情况...

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

我尝试了一下,不足为奇,它没有帮助。x:Static适用于任何静态属性或字段。 - Pavel Tupitsyn
2
【离题】很棒的昵称 :) 【/离题】 - Anatoliy Nikolaev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接