Создание и использование шаблонов

Последнее обновление: 15.02.2016

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

К примеру создадим округлый элемент Button:

<Window x:Class="ControlsTemplateApp.MainWindow"
        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:ControlsTemplateApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="300">
    <Window.Resources>
        <ControlTemplate TargetType="Button" x:Key="btTemplate">
            <Border CornerRadius="25" BorderBrush="CadetBlue" BorderThickness="2" 
                    Background="LightBlue" Height="40" Width="100" >
                <ContentControl Margin="5" HorizontalAlignment="Center" VerticalAlignment="Center" Content="Hello" />
            </Border>
        </ControlTemplate>
    </Window.Resources>
    <Grid>
        <Button x:Name="myButton" Template="{StaticResource btTemplate}" Height="40" Width="100">Hello</Button>
    </Grid>
</Window>
ControlTemplate в WPF

Мы можем определять шаблоны с через стили, а можем в виде отдельных ресурсов. Так, в данном случае с помощью элемента ControlTemplate определяется ресурс с ключом "btTemplate".

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

TemplateBinding

Вышеопределенный шаблон устанавливал цвет, ряд других параметров, которые мы не могли бы изменить. Например, если мы установим в кнопке цвет фона, то этот цвет никак не повлияет, так как в реальности будет работать только цвет, определенный в элементе Border:

<Button x:Name="myButton" Template="{StaticResource btTemplate}" Background="Red">Привет</Button>

Чтобы мы могли из элемента, к которому применяется шаблон, влиять на свойства, определенные в этом шаблоне, нам надо использовать элемент TemplateBinding. Он служит для установки в шаблоне привязки к свойствам элемента. Так, изменим шаблон следующим образом:

<Window x:Class="ControlsTemplateApp.MainWindow"
        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:ControlsTemplateApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="300">
    <Window.Resources>
        <ControlTemplate TargetType="Button" x:Key="btTemplate">
            <Border CornerRadius="25" 
                    BorderBrush="{TemplateBinding BorderBrush}" 
                    BorderThickness="{TemplateBinding BorderThickness}" 
                    Background="{TemplateBinding Background}" 
                    Height="{TemplateBinding Height}" 
                    Width="{TemplateBinding Width}" >
                <ContentControl Margin="{TemplateBinding Padding}" 
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                                Content="{TemplateBinding Content}" />
            </Border>
        </ControlTemplate>
    </Window.Resources>
    <Grid>
        <Button x:Name="myButton" Template="{StaticResource btTemplate}" Height="40" Width="100" Background="LightPink">Привет</Button>
    </Grid>
</Window>

Выражение типа Background="{TemplateBinding Background}" в элементе Border указывает, что фон элемента Border будет привязан к свойству Background элемента Button. Таким образом, здесь практически все свойства Border и ContentControl (кроме свойства CornerRadius) устанавливаются из разметки элемента Button

Свойство Template

Используя свойство Template, можно определить шаблон напрямую в самом элементе:

<Button x:Name="myButton" Content="Привет" Height="40" Width="100" Background="LightPink">
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Border CornerRadius="25" 
                BorderBrush="{TemplateBinding BorderBrush}" 
                BorderThickness="{TemplateBinding BorderThickness}" 
                Background="{TemplateBinding Background}" 
                Height="{TemplateBinding Height}" 
                Width="{TemplateBinding Width}" >
				<ContentControl Margin="{TemplateBinding Padding}" 
                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                        Content="{TemplateBinding Content}" />
            </Border>
        </ControlTemplate>
    </Button.Template>
</Button>

Триггеры в шаблонах

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

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

<Button x:Name="myButton" Content="Привет" Height="40" Width="100" Background="LightPink">
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Border x:Name="buttonBorder" CornerRadius="25" 
                BorderBrush="{TemplateBinding BorderBrush}" 
                BorderThickness="{TemplateBinding BorderThickness}" 
                Background="{TemplateBinding Background}" 
                Height="{TemplateBinding Height}" 
                Width="{TemplateBinding Width}" >
                <ContentControl Margin="{TemplateBinding Padding}" 
                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                    Content="{TemplateBinding Content}" />
            </Border>
			<ControlTemplate.Triggers>
				<Trigger Property="IsMouseOver" Value="true">
                    <Setter Property="FontWeight" Value="Bold" />
                </Trigger>
                <Trigger Property="IsPressed" Value="true">
                    <Setter TargetName="buttonBorder" Property="Background" Value="Azure" />
                    <Setter TargetName="buttonBorder" Property="BorderBrush" Value="DarkBlue" />
                </Trigger>
                <Trigger Property="IsEnabled" Value="false">
                    <Setter Property="Foreground" Value="Gray"/>
                    <Setter TargetName="buttonBorder" Property="Background" Value="LightGray"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Button.Template>
</Button>

Здесь для элемента Border определено свойство x:Name="buttonBorder", благодаря чему мы можем ссылаться на этот элемент в триггерах.

В коллекции триггеров шаблона определено три триггера. Первый срабатывает, когда свойство IsMouseOver элемена Button будет равно true. То есть при наведении указателя мыши на кнопку. В этом случае триггер делает жирным шрифт кнопки:

<Trigger Property="IsMouseOver" Value="true">
    <Setter Property="FontWeight" Value="Bold" />
</Trigger>

Второй триггер срабатывает при нажатии на кнопку, а третий - когда свойство IsEnabled равно false. Причем в этих триггерах свойство TargetName, что позволяет установить свойства не самой кнопки, а элемента Border в шаблоне.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850