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

4

2 回答 2

4

对您的问题的简短回答是 - 是的,它是 WPF 框架中的一个错误。错误报告在这里

更新-

Microsoft 已接受这是 XAML 编译器中的一个错误,并且他们没有修复此问题。来自微软的报价 -

这是 XAML 编译器中的一个问题 - 它生成 BAML 来描述每个资源的密钥,通常基于 x:Key(如果存在)和 DataType(如果不存在)。当 x:Key 本身是间接的(在您的情况下,使用 x:Static),编译器选择 DataType 键。虽然选择基于 x:Static 的键可能更“正确”,但更改它会引入兼容性问题。此外,由于问题发生在编译时,您必须重新编译您的应用程序才能看到修复(生成不同的 BAML 流)。您的应用程序的现有副本将包含旧的 BAML 流,并且在运行时的行为方式与现在相同。因此,我们决定不解决此问题。

x:Key 在这里不被忽略,但DataTemplateKey(WpfApplication1.TestDto)在第一种情况下设置为。您不能在没有键值的情况下在 Resources 部分下声明资源。

如您所见,该键自动设置为DataTemplateKey(WpfApplication1.TestDto)此处。

来自MSDN -

此属性与 Style 类的 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,因此 key 被设置为DataTemplateKey(WpfApplication1.TestDto).

您可以通过仅设置 DataType 将另一个 DataTemplate 添加到您的资源中来验证这一点,即

<DataTemplate DataType="{x:Type wpfApplication1:TestDto}"/>.

它会编译得很好但会抛出运行时错误

“已添加项目。字典中的键:'DataTemplateKey(WpfApplication1.TestDto)' 正在添加的键:'DataTemplateKey(WpfApplication1.TestDto)'”

于 2013-10-22T20:10:53.110 回答
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; }
}
于 2013-10-18T15:46:54.153 回答