Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
С помощью Windows Presentation Foundation (WPF) можно настроить визуальную структуру и поведение существующего элемента управления с помощью собственного повторно используемого шаблона. Шаблоны можно применять глобально к приложению, окнам и страницам или напрямую к элементам управления. Большинство сценариев, требующих создания нового элемента управления, можно охватывать путем создания нового шаблона для существующего элемента управления.
В этой статье, вы узнаете о создании нового элемента управления ControlTemplate для Button.
Когда необходимо создать ControlTemplate
Элементы управления имеют множество свойств, таких как Background, Foregroundи FontFamily. Эти свойства управляют различными аспектами внешнего вида элемента управления, но изменения, которые можно внести, задав эти свойства, ограничены. Например, можно задать для свойства Foreground значение синий и свойству FontStyle установить курсив на CheckBox. Если вы хотите настроить внешний вид элемента управления за пределами настройки других свойств элемента управления, создайте ControlTemplate.
В большинстве пользовательских интерфейсов кнопка имеет тот же общий вид: прямоугольник с некоторым текстом. Если вы хотите создать округленную кнопку, можно создать новый элемент управления, наследуемый от кнопки или повторно создающий функциональные возможности кнопки. Кроме того, новый пользовательский элемент управления предоставляет круглую визуализацию.
Вы можете избежать создания новых элементов управления, настраивая визуальный макет существующего элемента управления. Для округленной кнопки вы создаёте ControlTemplate с нужным визуальным макетом.
С другой стороны, если вам нужен элемент управления с новыми функциями, различными свойствами и новыми параметрами, вы создадите новый UserControlэлемент управления.
Предпосылки
Создайте новое приложение WPF. В файле MainWindow.xaml (или другом окне по вашему выбору) задайте следующие свойства в элементе <Window>:
| Недвижимость | Ценность |
|---|---|
| Title | Template Intro Sample |
| SizeToContent | WidthAndHeight |
| MinWidth | 250 |
Задайте для содержимого элемента <Window> следующий код XAML:
<StackPanel Margin="10">
<Label>Unstyled Button</Label>
<Button>Button 1</Button>
<Label>Rounded Button</Label>
<Button>Button 2</Button>
</StackPanel>
В конце файл MainWindow.xaml должен выглядеть следующим образом:
<Window x:Class="IntroToStylingAndTemplating.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:IntroToStylingAndTemplating"
mc:Ignorable="d"
Title="Template Intro Sample" SizeToContent="WidthAndHeight" MinWidth="250">
<StackPanel Margin="10">
<Label>Unstyled Button</Label>
<Button>Button 1</Button>
<Label>Rounded Button</Label>
<Button>Button 2</Button>
</StackPanel>
</Window>
Если вы запускаете приложение, он выглядит следующим образом:
Создайте ControlTemplate
Наиболее распространенный способ объявить ControlTemplate – это указать его как ресурс в разделе Resources в XAML-файле. Так как шаблоны являются ресурсами, они следуют тем же правилам области, что и все ресурсы. Где вы объявляете шаблон, влияет на то, где его можно применить. Например, если вы объявляете шаблон в корневом элементе XAML-файла определения приложения, можно использовать шаблон в любом месте приложения. Если вы определяете шаблон в окне, то только элементы управления в этом окне могут использовать шаблон.
Чтобы начать, добавьте Window.Resources элемент в файл MainWindow.xaml :
<Window x:Class="IntroToStylingAndTemplating.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:IntroToStylingAndTemplating"
mc:Ignorable="d"
Title="Template Intro Sample" SizeToContent="WidthAndHeight" MinWidth="250">
<Window.Resources>
</Window.Resources>
<StackPanel Margin="10">
<Label>Unstyled Button</Label>
<Button>Button 1</Button>
<Label>Rounded Button</Label>
<Button>Button 2</Button>
</StackPanel>
</Window>
Создайте элемент <ControlTemplate> и задайте следующие свойства:
| Недвижимость | Ценность |
|---|---|
| x:Key | roundbutton |
| TargetType | Button |
Этот шаблон элемента управления прост:
- корневой элемент элемента управления, Grid
- ан Ellipse для создания округленного внешнего вида кнопки
- ContentPresenter для отображения содержимого указанной пользователем кнопки
<ControlTemplate x:Key="roundbutton" TargetType="Button">
<Grid>
<Ellipse Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
Привязка шаблона
При создании нового ControlTemplate вы всё ещё можете использовать общедоступные свойства для изменения внешнего вида элемента управления. Расширение разметки TemplateBinding привязывает свойство элемента, который находится в ControlTemplate общедоступном свойстве, определяемом элементом управления. При использовании TemplateBindingможно использовать свойства элемента управления в роли параметров для шаблона. При установке свойства в элементе управления значение передается элементу, который имеет TemplateBinding.
Эллипс
Контентный презентер
Шаблон также включает <элемент ContentPresenter> . Так как этот шаблон предназначен для кнопки, помните, что кнопка наследуется от ContentControl. Кнопка отображает содержимое элемента. Вы можете задать все, что находится внутри кнопки, например обычный текст или даже другой элемент управления. Оба следующих примера являются допустимыми кнопками:
<Button>My Text</Button>
<!-- and -->
<Button>
<CheckBox>Checkbox in a button</CheckBox>
</Button>
В обоих предыдущих примерах текст и флажок задаются как свойство Button.Content. Все, что задано в качестве содержимого, можно представить с помощью <ContentPresenter>, и именно это делает шаблон.
При применении ControlTemplate к типу ContentControl, например Button, шаблон ищет ContentPresenter в дереве элементов. Шаблон автоматически связывает свойство Content элемента управления с ContentPresenter, если обнаруживается ContentPresenter.
Использование шаблона
Найдите кнопки, объявленные в начале этой статьи.
<StackPanel Margin="10">
<Label>Unstyled Button</Label>
<Button>Button 1</Button>
<Label>Rounded Button</Label>
<Button>Button 2</Button>
</StackPanel>
Установите свойство Template второй кнопки на ресурс roundbutton.
<StackPanel Margin="10">
<Label>Unstyled Button</Label>
<Button>Button 1</Button>
<Label>Rounded Button</Label>
<Button Template="{StaticResource roundbutton}">Button 2</Button>
</StackPanel>
Если вы запускаете проект и посмотрите на результат, вы увидите, что кнопка имеет округленный фон.
Вы можете заметить, что кнопка не круглая, а искривлена. Из-за того, как работает элемент <Ellipse>, он всегда расширяется, чтобы заполнить доступное пространство. Сделайте круг однородным, изменив свойства width и height кнопки на одинаковое значение.
<StackPanel Margin="10">
<Label>Unstyled Button</Label>
<Button>Button 1</Button>
<Label>Rounded Button</Label>
<Button Template="{StaticResource roundbutton}" Width="65" Height="65">Button 2</Button>
</StackPanel>
Добавление триггера
Несмотря на то, что кнопка с примененным шаблоном выглядит иначе, она ведет себя так же, как и любая другая кнопка. Если нажать кнопку, событие Click запускается. Однако вы можете заметить, что при перемещении мыши на кнопку визуальные элементы кнопки не изменяются. Шаблон определяет эти визуальные взаимодействия.
Используя динамические системы событий и свойств, предоставляемые WPF, можно отслеживать определенное свойство на предмет изменения значения и затем изменить стиль шаблона при необходимости. В этом примере вы просматриваете свойство кнопки IsMouseOver . При наведении мыши на элемент управления, примените новый цвет к стильному эллипсу <>. Этот тип триггера называется PropertyTrigger.
Чтобы эта функция работала, необходимо добавить имя в <эллипс> , на который можно ссылаться. Присвойте ему имя backgroundElement.
<Ellipse x:Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
Затем добавьте новый Trigger в коллекцию ControlTemplate.Triggers. Триггер проверяет IsMouseOver событие для значения true.
<ControlTemplate x:Key="roundbutton" TargetType="Button">
<Grid>
<Ellipse x:Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Затем добавьте <Setter> к <Trigger>, который изменяет свойство Fill у <Эллипс> на новый цвет.
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Fill" TargetName="backgroundElement" Value="AliceBlue"/>
</Trigger>
Запустите проект. При перемещении мыши на кнопку цвет <эллипса> изменяется.
Использование VisualState
Визуальные состояния определяются и активируются элементом управления. Например, при перемещении мыши над элементом управления элемент управления запускает CommonStates.MouseOver состояние. Вы можете анимировать изменения свойств в зависимости от текущего состояния элемента управления. В предыдущем разделе вы использовали <PropertyTrigger> для изменения фона кнопки на AliceBlue, когда свойство IsMouseOver имело значение true. Вместо этого создайте визуальное состояние, которое анимирует изменение этого цвета, обеспечивая плавный переход. Дополнительные сведения о VisualStatesсм. в разделе Стили и шаблоны в WPF.
Чтобы преобразовать <PropertyTrigger> в анимированное визуальное состояние, удалите <элемент ControlTemplate.Triggers> из шаблона.
<ControlTemplate x:Key="roundbutton" TargetType="Button">
<Grid>
<Ellipse x:Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
В сетке <в корне шаблона элемента управления> добавьте элемент <VisualStateManager.VisualStateGroups> с <VisualStateGroup> для CommonStates. Определите два состояния, Normal и MouseOver.
<ControlTemplate x:Key="roundbutton" TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal">
</VisualState>
<VisualState Name="MouseOver">
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Ellipse x:Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
При активации этого состояния примените любые анимации, определенные в <VisualState> . Создайте анимации для каждого состояния. Поместите анимацию внутри <элемента Storyboard> . Дополнительные сведения о раскадровках см. в разделе Storyboards Overview.
Нормальный
Это состояние анимирует заливку эллипса, восстанавливая его цвет до
Backgroundуправляющего элемента.<Storyboard> <ColorAnimation Storyboard.TargetName="backgroundElement" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" To="{TemplateBinding Background}" Duration="0:0:0.3"/> </Storyboard>Наведение курсора
Это состояние анимирует многоточие
Backgroundцвет на новый цвет:Yellow.<Storyboard> <ColorAnimation Storyboard.TargetName="backgroundElement" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" To="Yellow" Duration="0:0:0.3"/> </Storyboard>
Элемент< ControlTemplate> теперь должен быть представлен следующим кодом.
<ControlTemplate x:Key="roundbutton" TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal">
<Storyboard>
<ColorAnimation Storyboard.TargetName="backgroundElement"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
To="{TemplateBinding Background}"
Duration="0:0:0.3"/>
</Storyboard>
</VisualState>
<VisualState Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="backgroundElement"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
To="Yellow"
Duration="0:0:0.3"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Ellipse Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
<ContentPresenter x:Name="contentPresenter" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
Запустите проект. При наведении курсора на кнопку цвет <эллипса> анимируется.
Дальнейшие шаги
.NET Desktop feedback