Шаблоны элементов управления

Вы можете настроить визуальную структуру элемента управления и визуальное поведение, создав шаблон элемента управления в платформе XAML. Элементы управления имеют множество свойств, таких как Background, Foreground и FontFamily, которые можно задать для указания различных аспектов внешнего вида элемента управления. Но изменения, которые можно внести, задав эти свойства, ограничены. Дополнительные настройки можно указать, создав шаблон с помощью класса ControlTemplate. Здесь мы покажем, как создать controlTemplate для настройки внешнего вида элемента управления CheckBox.

Важные API: класс ControlTemplate, свойство Control.Template

Пример шаблона пользовательского элемента управления

По умолчанию элемент управления CheckBox помещает его содержимое (строка или объект рядом с флажком) справа от поля выбора, а флажок указывает, что пользователь выбрал флажок. Эти характеристики представляют визуальную структуру и визуальное поведение CheckBox.

Вот флажок с помощью элемента ControlTemplate по умолчанию, показанного в CheckedUncheckedи Indeterminate состояниях.

Шаблон флажка по умолчанию

Эти характеристики можно изменить, создав элемент ControlTemplate для CheckBox. Например, если вы хотите, чтобы содержимое флажка было ниже поля выбора, и вы хотите использовать X , чтобы указать, что пользователь выбрал флажок. Эти характеристики указываются в элементе ControlTemplate checkBox.

Чтобы использовать пользовательский шаблон с элементом управления, назначьте ControlTemplate свойству Template элемента управления. Вот флажок с именем CheckBoxTemplate1ControlTemplate. Мы показываем язык разметки расширяемых приложений (XAML) для controlTemplate в следующем разделе.

<CheckBox Content="CheckBox" Template="{StaticResource CheckBoxTemplate1}" IsThreeState="True" Margin="20"/>

Вот как этот флажок выглядит в Unchecked, Checkedи Indeterminate состояния после применения шаблона.

Пользовательский шаблон флажка

Указание визуальной структуры элемента управления

При создании controlTemplate вы объединяете объекты FrameworkElement для создания единого элемента управления. Элемент ControlTemplate должен иметь только один элемент FrameworkElement в качестве корневого элемента. Корневой элемент обычно содержит другие объекты FrameworkElement . Комбинация объектов составляет визуальную структуру элемента управления.

Этот XAML создает элемент ControlTemplate для checkBox, указывающий, что содержимое элемента управления находится под полем выбора. Корневой элемент — Border. В примере указывается путь для создания X , указывающего, что пользователь выбрал флажок и эллипс , указывающий неопределенное состояние. Обратите внимание, что для непрозрачности задано значение 0 для пути и эллипса , чтобы по умолчанию ни отображалось.

TemplateBinding связывает значение свойства в шаблоне элемента управления и значение какого-либо другого предоставленного свойства элемента управления-шаблона. TemplateBinding можно использовать только в определении ControlTemplate в XAML. См. подробнее в разделе Расширение разметки TemplateBinding.

Примечание.

Начиная с Windows 10, версия 1809 (SDK 17763), вы можете использовать расширения разметки x:Bind вместе с TemplateBinding. См. подробнее в разделе Расширение разметки TemplateBinding.

<ControlTemplate x:Key="CheckBoxTemplate1" TargetType="CheckBox">
    <Border BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            Background="{TemplateBinding Background}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="25"/>
            </Grid.RowDefinitions>
            <Rectangle x:Name="NormalRectangle" Fill="Transparent" Height="20" Width="20"
                       Stroke="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
                       StrokeThickness="{ThemeResource CheckBoxBorderThemeThickness}"
                       UseLayoutRounding="False"/>
            <!-- Create an X to indicate that the CheckBox is selected. -->
            <Path x:Name="CheckGlyph"
                  Data="M103,240 L111,240 119,248 127,240 135,240 123,252 135,264 127,264 119,257 111,264 103,264 114,252 z"
                  Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                  FlowDirection="LeftToRight"
                  Height="14" Width="16" Opacity="0" Stretch="Fill"/>
            <Ellipse x:Name="IndeterminateGlyph"
                     Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                     Height="8" Width="8" Opacity="0" UseLayoutRounding="False" />
            <ContentPresenter x:Name="ContentPresenter"
                              ContentTemplate="{TemplateBinding ContentTemplate}"
                              Content="{TemplateBinding Content}"
                              Margin="{TemplateBinding Padding}" Grid.Row="1"
                              HorizontalAlignment="Center"
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Grid>
    </Border>
</ControlTemplate>

Указание визуального поведения элемента управления

Визуальное поведение указывает внешний вид элемента управления, когда он находится в определенном состоянии. Элемент управления CheckBox содержит 3 состояния проверки: Checked, Uncheckedи Indeterminate. Значение свойства IsChecked определяет состояние CheckBox, а его состояние определяет, что отображается в поле.

В этой таблице перечислены возможные значения IsChecked, соответствующие состояния CheckBox и внешний вид CheckBox.

Значение IsChecked Состояние CheckBox Внешний вид CheckBox
true Checked Содержит значение "X".
false Unchecked Пусто
NULL Indeterminate Содержит круг.

Вы указываете внешний вид элемента управления, если он находится в определенном состоянии с помощью объектов VisualState. VisualState содержит элемент Setter или Storyboard, который изменяет внешний вид элементов в ControlTemplate. Когда элемент управления вводит состояние, указанное свойством VisualState.Name, применяется свойство Setter или Storyboard. Когда элемент управления выходит из состояния, изменения удаляются. Объекты VisualState добавляются в объекты VisualStateGroup. Объекты VisualStateGroup добавляются в присоединенное свойство VisualStateManager.VisualStateGroups, которое устанавливается в корневом объекте FrameworkElement элемента ControlTemplate.

В этом XAML показаны объекты VisualState для состояний Uncheckedи Indeterminate состоянийChecked. В примере задается присоединенное свойство VisualStateManager.VisualStateGroups на границе, которое является корневым элементом ControlTemplate. VisualState Checked указывает, что значение Opacity для Path с именем CheckGlyph (см. предыдущий пример) равно 1. VisualState Indeterminate указывает, что значение Opacity для Ellipse с именем IndeterminateGlyph равно 1. VisualState Unchecked нет имеет Setter или Storyboard, поэтому CheckBox возвращается к своему внешнему виду по умолчанию.

<ControlTemplate x:Key="CheckBoxTemplate1" TargetType="CheckBox">
    <Border BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            Background="{TemplateBinding Background}">

        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CheckStates">
                <VisualState x:Name="Checked">
                    <VisualState.Setters>
                        <Setter Target="CheckGlyph.Opacity" Value="1"/>
                    </VisualState.Setters>
                    <!-- This Storyboard is equivalent to the Setter. -->
                    <!--<Storyboard>
                        <DoubleAnimation Duration="0" To="1"
                         Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Opacity"/>
                    </Storyboard>-->
                </VisualState>
                <VisualState x:Name="Unchecked"/>
                <VisualState x:Name="Indeterminate">
                    <VisualState.Setters>
                        <Setter Target="IndeterminateGlyph.Opacity" Value="1"/>
                    </VisualState.Setters>
                    <!-- This Storyboard is equivalent to the Setter. -->
                    <!--<Storyboard>
                        <DoubleAnimation Duration="0" To="1"
                         Storyboard.TargetName="IndeterminateGlyph" Storyboard.TargetProperty="Opacity"/>
                    </Storyboard>-->
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="25"/>
            </Grid.RowDefinitions>
            <Rectangle x:Name="NormalRectangle" Fill="Transparent" Height="20" Width="20"
                       Stroke="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
                       StrokeThickness="{ThemeResource CheckBoxBorderThemeThickness}"
                       UseLayoutRounding="False"/>
            <!-- Create an X to indicate that the CheckBox is selected. -->
            <Path x:Name="CheckGlyph"
                  Data="M103,240 L111,240 119,248 127,240 135,240 123,252 135,264 127,264 119,257 111,264 103,264 114,252 z"
                  Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                  FlowDirection="LeftToRight"
                  Height="14" Width="16" Opacity="0" Stretch="Fill"/>
            <Ellipse x:Name="IndeterminateGlyph"
                     Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                     Height="8" Width="8" Opacity="0" UseLayoutRounding="False" />
            <ContentPresenter x:Name="ContentPresenter"
                              ContentTemplate="{TemplateBinding ContentTemplate}"
                              Content="{TemplateBinding Content}"
                              Margin="{TemplateBinding Padding}" Grid.Row="1"
                              HorizontalAlignment="Center"
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Grid>
    </Border>
</ControlTemplate>

Чтобы лучше понять, как работают объекты VisualState, рассмотрим, что происходит, когда checkBox переходит от Unchecked состояния к состояниюChecked, а затем Indeterminate к состоянию, а затем обратно в Unchecked состояние. Ниже приведены переходы.

Смена состояния Что происходит Внешний вид CheckBox при завершении перехода
С Unchecked на Checked. Применяется значение Setter VisualState Checked, поэтому значение Opacity для CheckGlyph равно 1. Отображается X.
С Checked на Indeterminate. Применяется значение Setter VisualState Indeterminate, поэтому значение Opacity для IndeterminateGlyph равно 1. Значение Setter VisualState Checked удаляется, поэтому значение Opacity для CheckGlyph равно 0. Отображается круг.
С Indeterminate на Unchecked. Значение Setter VisualState Indeterminate удаляется, поэтому значение Opacity для IndeterminateGlyph равно 0. Отображается ничего.

  Дополнительные сведения о создании визуальных состояний для элементов управления, а также о том, как использовать класс Раскадровки и типы анимации, см. в разделе "Раскадровки анимации" для визуальных состояний.

Использование средств для работы с темами легко

Быстрый способ применить темы к элементам управления — щелкнуть правой кнопкой мыши элемент управления в структуре документа Microsoft Visual Studio и выбрать пункт "Изменить тему" или "Изменить стиль" (в зависимости от элемента управления, который вы щелкаете правой кнопкой мыши). Затем можно применить существующую тему, выбрав "Применить ресурс " или определив новую, выбрав "Создать пустое".

Элементы управления и специальные возможности

При создании нового шаблона для элемента управления, помимо возможного изменения поведения элемента управления и внешнего вида элемента управления, вы также можете изменить способ представления элемента управления в платформы специальных возможностей. Приложения для Windows поддерживают инфраструктуру автоматизации пользовательского интерфейса Майкрософт для включения специальных возможностей. Все элементы управления по умолчанию и их шаблоны поддерживают распространенные типы и шаблоны элементов управления модель автоматизации пользовательского интерфейса, подходящие для назначения и функции элемента управления. Эти типы элементов управления и шаблоны интерпретируются модель автоматизации пользовательского интерфейса клиентами, такими как вспомогательные технологии, и это позволяет управлять доступом как часть более крупного пользовательского интерфейса приложения.

Чтобы разделить базовую логику управления, а также удовлетворить некоторые архитектурные требования модель автоматизации пользовательского интерфейса, классы элементов управления включают поддержку специальных возможностей в отдельном классе, одноранговом узле автоматизации. Пиринги автоматизации иногда взаимодействуют с шаблонами элементов управления, так как одноранговые узлы ожидают, что определенные именованные части существуют в шаблонах, поэтому такие функции, как включение вспомогательных технологий для вызова действий кнопок.

При создании совершенно нового пользовательского элемента управления иногда требуется создать новый одноранговый узел автоматизации, который будет выполняться вместе с ним. Дополнительные сведения см. в разделе "Пользовательские одноранговые узлы автоматизации".

Дополнительные сведения о шаблоне элемента управления по умолчанию

В разделах, которые документируют стили и шаблоны для элементов управления XAML, отображаются фрагменты одного и того же начального XAML, который вы увидите, если вы использовали методы редактирования темы или стиля редактирования ранее. Каждый раздел содержит имена визуальных состояний, используемых ресурсов темы и полный XAML для стиля, содержащего шаблон. Разделы могут быть полезными, если вы уже начали изменять шаблон и хотите увидеть, как выглядит исходный шаблон, или убедиться, что новый шаблон имеет все необходимые именованные визуальные состояния.

Ресурсы темы в шаблонах элементов управления

Некоторые атрибуты в примерах XAML, возможно, заметили ссылки на ресурсы, использующие расширение разметки {ThemeResource}. Это метод, позволяющий одному шаблону элемента управления использовать ресурсы, которые могут быть разными значениями в зависимости от того, какая тема в настоящее время активна. Это особенно важно для кистей и цветов, так как основная цель темы заключается в том, чтобы пользователи могли выбирать, хотят ли они темной, светлой или высокой контрастности темы, примененной к системе в целом. Приложения, использующие систему ресурсов XAML, могут использовать набор ресурсов, подходящий для этой темы, чтобы выбор темы в пользовательском интерфейсе приложения отражает выбор системной темы пользователя.

Получение кода примера