Почему x: ключ требуется на ControlTemplate в ResourceDictionary

рассмотрим следующий файл 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, должны иметь ключевой атрибут или некоторые другой тип ключа, связанный с ними. Линия 10 Позиция 10.

Если я добавлю x:key атрибут ControlTemplate, он компилируется. Однако мне не придется этого делать. ControlTemplate украшен атрибутом DictionaryKeyProperty, который задает TargetType в качестве ключевого свойства. Поэтому, пока я указываю TargetType для моего ControlTemplate, я должен не необходимо указать явный ключ (аналогично тому, как мне не нужно указывать его на DataTemplate, который я определил).

у меня есть второй и тангенциально связанный с этим вопрос. Если я определяю ControlTemplate таким образом (либо указывая ключ, либо нет) в XAML, он автоматически применяется ко всем элементам управления типа ContentControl, которые не указывают другой шаблон,или мне придется встроить ControlTemplate внутри стиля для этого?

4 ответов


из MSDN ControlTemplate:

если у вас есть автономный ControlTemplate в разделе ресурсов с свойство TargetType имеет тип, ControlTemplate не имеет автоматически применитесь к этому типу. Вместо этого необходимо указать х:ключ и применить шаблон явно.

также обратите внимание, что свойство TargetType требуется на ControlTemplate, если шаблон
определение содержит объект ContentPresenter.

так ControlTemplate не применяется автоматически, и вы должны всегда указывать x:Key. Так что DictionaryKeyProperty не относится.

Я сделал некоторые исследования:

хотя DictionaryKeyPropertyAttribute состояние страницы MSDN:

примечания по использованию WPF

следующий список ссылается на примеры API WPF, где это атрибут применяется:

ControlTemplate.TargetType

DataTemplate.DataTemplateKey

Style.TargetType

но на Обзор Ресурсов страница они упоминают только Styles, DataTemplates, and Implicit Keys, который имеет скрытые ключи. Это также означает, что вам нужно всегда указывать x:Key на ControlTemplate несмотря на DictionaryKeyProperty.

кстати, кажется, что-то не так с DictionaryKeyPropertyAttirubte посмотреть этот подключиться вопрос.


Я не знаю ответа на ваш первый вопрос, но по поводу второго:

у меня есть второй и тангенциально связанный с этим вопрос. Если я определяю ControlTemplate таким образом (либо указав ключ, либо нет) в XAML, он автоматически применяется ко всем элементам управления типа ContentControl, который не указывает другой шаблон, или мне придется внедрить ControlTemplate внутри стиля для этого?

нет, это не будет автоматически применять. Стили применяются автоматически, если их ключ соответствует DefaultStyleKey элемента управления; шаблоны данных автоматически выбираются ContentControl Если тип Content соответствует DataType шаблона. Но это не относится к шаблонам управления ; во всяком случае, шаблоны управления обычно определяются как часть стиля элемента управления, они редко применяются непосредственно к элементу управления.


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

ключ используется для применения шаблонов на элементе управления, как кнопка as, textbox, textblock и т.д. Если вы не используете его, то шаблонов не работает.


Если вы хотите, чтобы шаблон элемента управления был применен ко всем указанным типам, вы можете определить стиль и установить свойство шаблона и этот стиль с 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>

Я проверил это с помощью кнопки формат, но я думаю, что это должно работать таким образом.