Почему ключ x: требуется для ControlTemplate в ResourceDictionary - PullRequest
8 голосов
/ 04 марта 2012

Рассмотрим следующий 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 в качестве ключевого свойства.Поэтому, пока я указываю TargetType для моего ControlTemplate, я должен , а не указывать явный ключ (аналогично тому, как мне не нужно указывать его в DataTemplate, который я определил).

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

Ответы [ 4 ]

5 голосов
/ 04 марта 2012

Из MSDN ControlTemplate :

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

Также обратите внимание, что свойство 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 что-то не так, смотрите эту проблему connect.

1 голос
/ 04 марта 2012

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

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

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

0 голосов
/ 14 августа 2017

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

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

0 голосов
/ 13 мая 2014
<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>

Клавиша используется для применения шаблонов к элементу управления, например кнопки, текстового поля, текстового блока и т. Д. Если вы не используете их, шаблонирование не работает.

...