【问题标题】:Why is x:key required on ControlTemplate in the ResourceDictionary为什么 ResourceDictionary 中的 ControlTemplate 需要 x:key
【发布时间】:2012-03-21 21:56:30
【问题描述】:

考虑以下 XAML 文件:

<Window x:Class="ExpressionVisualizer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sle="clr-namespace:System.Linq.Expressions;assembly=System.Core"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <DataTemplate DataType="{x:Type sle:BinaryExpression}"/>
        <ControlTemplate TargetType="{x:Type ContentControl}"/>
    </Window.Resources>
</Window>

这给出了以下编译错误:

添加到 IDictionary 的所有对象都必须具有 Key 属性或一些 与它们关联的其他类型的密钥。第 10 行位置 10。

如果我将 x:key 属性添加到 ControlTemplate,它会编译。但是,我不应该这样做。 ControlTemplate 使用 DictionaryKeyProperty 属性进行修饰,该属性将 TargetType 指定为关键属性。因此,只要我为我的 ControlTemplate 指定一个 TargetType,我就应该不必必须指定一个显式键(类似于我不必在我定义的 DataTemplate 上指定一个键)。

我有第二个与切线相关的问题。如果我在 XAML 中以这种方式定义 ControlTemplate(无论是否指定键),它是否会自动应用于未指定另一个模板的 ContentControl 类型的所有控件,或者我是否必须将 ControlTemplate 嵌入到样式中发生这种情况?

【问题讨论】:

    标签: wpf xaml controltemplate resourcedictionary


    【解决方案1】:

    我不知道你的第一个问题的答案,但关于第二个问题:

    我有第二个与切线相关的问题。如果我定义一个 ControlTemplate 以这种方式(指定或不指定键)在 XAML,它是否会自动应用于所有类型的控件 ContentControl 不指定另一个模板,或者我必须 将 ControlTemplate 嵌入到 Style 中以使其发生?

    不,它不会自动应用。如果样式的键与控件的DefaultStyleKey 匹配,则样式会自动应用;如果Content 的类型与模板的DataType 匹配,则ContentControl 会自动获取数据模板。但控制模板并非如此;无论如何,控件模板通常被定义为控件样式的一部分,它们很少直接应用于控件。

    【讨论】:

      【解决方案2】:

      来自 MSDN ControlTemplate:

      如果您在资源部分有一个独立的 ControlTemplate TargetType 属性设置为一个类型,ControlTemplate 没有 自动应用于该类型。相反,您需要指定 一个 x:Key 并显式应用模板。

      另请注意,如果模板是 ControlTemplate,则 TargetType 属性是必需的
      定义包含一个 ContentPresenter。

      因此ControlTemplate 不会自动应用,您必须始终指定x:Key。所以DictionaryKeyProperty 不适用。

      我做了一些研究:

      虽然DictionaryKeyPropertyAttribute MSDN 页面声明:

      WPF 使用说明

      以下列表引用了 WPF API 的示例,其中 属性已应用:

      ControlTemplate.TargetType
      
      DataTemplate.DataTemplateKey
      
      Style.TargetType
      

      但是在Resources Overview 页面上,他们只提到了Styles, DataTemplates, and Implicit Keys,它具有隐式键。这也意味着您需要始终为ControlTemplate 指定x:Key,尽管DictionaryKeyProperty

      顺便说一句,DictionaryKeyPropertyAttirubte 似乎有问题,请参阅此connect issue

      【讨论】:

      • 这回答了我问题的第二部分。我知道如果我想在文档的其他地方引用模板,我需要指定一个 x:Key,但省略它不会导致编译错误。
      • 我已经更新了我的答案。它接缝DictionaryKeyProperty 没有做它应该做的......
      • DictionaryKeyProperty 的问题似乎不会影响所有类型,因为该属性按 DataTemplate 中指定的方式工作。 Connect 问题是从 2009 年开始的。我想我会把它写成 WPF 中的另一件事,它不起作用并且从未经过彻底测试。每次我尝试在 WPF 中开发某些东西时,我都会遇到这些类型的问题。 Windows 窗体永远不会发生这种情况,一切正常。我真的认为(也许是一厢情愿)他们会让 WPF 在 4.0 版本中更加可预测/可用。
      • @nemesv,Microsoft connect 已“停用”--该链接现已失效
      【解决方案3】:
      <Window x:Class="ExpressionVisualizer.MainWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:sle="clr-namespace:System.Linq.Expressions;assembly=System.Core"
          Title="MainWindow" Height="350" Width="525">
      <Window.Resources>
          <DataTemplate x:Key="DT" DataType="{x:Type sle:BinaryExpression}"/>
          <ControlTemplate x:Key="CT" TargetType="{x:Type ContentControl}"/>
      </Window.Resources>
      

      键用于在按钮、文本框、文本块等控件上应用模板。如果您不使用它,则模板不起作用。

      【讨论】:

        【解决方案4】:

        如果您希望将控件模板应用于所有指定的类型,您可以定义一个样式并将模板属性和带有 TargetType 的样式设置为您指定的控件:

        <Window x:Class="ExpressionVisualizer.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:sle="clr-namespace:System.Linq.Expressions;assembly=System.Core"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <DataTemplate x:Key="DT" DataType="{x:Type sle:BinaryExpression}"/>
            <ControlTemplate x:Key="CT" TargetType="{x:Type ContentControl}"/>
            <Style TargetType="ContentControl">
                <Setter Property="Template" Value="{StaticResource  CT}"></Setter>
            </Style>
        </Window.Resources>
        

        我已经使用按钮目标类型对此进行了测试,但我认为它应该以这种方式工作。

        【讨论】:

          猜你喜欢
          • 2011-10-26
          • 1970-01-01
          • 2020-05-03
          • 2019-06-09
          • 1970-01-01
          • 2011-09-12
          • 1970-01-01
          • 1970-01-01
          • 2020-03-22
          相关资源
          最近更新 更多