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

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

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

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

        <Button VerticalAlignment="Top" Height="30" Template="{x:Null}">
            <StackPanel Background="Red">
                <TextBlock Text="Кнопка" FontSize="12" TextAlignment="Center" Margin="0 6 0 0" />
            </StackPanel>
        </Button>

Свойство Template элемента как раз и указывает на используемый шаблон. Чтобы шаблон исключить применение стандартного шаблона мы указали выражение {x:Null}

Шаблон элемента - это своего рода визуальный скелет элемента управления. В предыдущем примере мы по сути не использовали шаблоны, однако нередко возникают ситуации, когда надо изменить визуальный облик элемента коренным образом, например, сделать его округлым или другой формы и т.д.

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

<UserControl.Resources>
        <ControlTemplate TargetType="Button" x:Key="btTemplate">
            <Border Name="RootElement" CornerRadius="25" Background="{TemplateBinding Background}">
                <Grid Margin="0" Background="Transparent">
                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
										VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>                 
                </Grid>
            </Border>
        </ControlTemplate>
        <ControlTemplate x:Key="tbTemplate">
            <Border Name="Border" CornerRadius="25" Padding="2"
                BorderThickness="2" BorderBrush="Blue" Background="White">
            </Border>
        </ControlTemplate>
    </UserControl.Resources>
    <Grid Background="Black">
       <Button Width="80" Height="30" Template="{StaticResource btTemplate}" Margin="0 50 0 0" Content="Нажми" Background="Red" Click="Button_Click" />
        <TextBox x:Name="textBox1"  Width="210" Height="25" Template="{StaticResource tbTemplate}" Margin="0 0 0 90"  />
    </Grid>
</UserControl>

Что в данном случае мы делаем? Сначала объявляется шаблон - создаем объект ControlTemplate. Подобно стилям он объявляется в ресурсах. Как и всякому ресурсу присваиваем ему ключ. Сначала определяем корневой элемент - Border. Так как элемент начинается с границ, то и объект Border является корневым, в который вложены остальные элементы. Объект Grid является дочерним по отношению к корневому элементу и содержит объект ContentPresenter. У объекта Border определяем свойство CornerRadius, отвечающее за закругление границ объекта. Затем определяем цвет фона элемента. Это делается с помощью привязки и ключевого слова TemplateBinding. Оно привязывает данное свойство к свойству объекта, для которого определен шаблон. В данном случае фон элемента Border привязывается к фону кнопки, что обеспечивает шаблонам гибкость в использовании. У элемента Grid определяем фон как Transparent. Если бы мы задали какой-то конкретный цвет, то кнопка приобрела бы квадратный вид. Затем определяем элемент ContentPresenter. Он задает параметры содержимого. Для него также определяем привязку к свойствам кнопки, в частности задаем выравнивание по горизонтали и вертикали.

Таким же образом поступаем для элемента TextBox.

Подключение к шаблону происходит с помощью свойства Template элемента с указанием ресурса.

Есть еще два способа задания шаблонов. Один - непосредственно в разметке контрола:

       <TextBox x:Name="textBox1"  Width="210" Height="25" Margin="0 0 0 90" >
            <TextBox.Template>
                <ControlTemplate>
                    <Border Name="Border" CornerRadius="25" Padding="2"
                BorderThickness="2" BorderBrush="Blue" Background="White">
                    </Border>
                </ControlTemplate>
            </TextBox.Template>
        </TextBox>

А второй - создание шаблона в стиле:

 <UserControl.Resources>
        <Style x:Key="buttonStyle" TargetType="Button">
            <Setter Property="Template">
                <Setter.Value>
					<ControlTemplate TargetType="Button">
						<Border Name="RootElement" CornerRadius="25" Background="{TemplateBinding Background}" >
							<Grid Margin="0" Background="Transparent">
								<ContentPresenter 
								HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
								VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>  
							</Grid>
						</Border>
					</ControlTemplate>
				</Setter.Value>
			</Setter>
		</Style>
	</Window.Resources>
		.....
	<UserControl Width="80" Height="30" Style="{StaticResource buttonStyle}" Margin="0 50 0 0" Content="Нажми" Background="Blue" />

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

Элемент управления обладает определенными состояниями, которые могут влиять на визуальное отображение. Например, для кнопки это может быть состояние MouseOver, когда указатель мыши наведен на кнопку, или Pressed, когда кнопка нажата. Чтобы изменить внешний вид в зависимости от состояния элемента используется объект ViewState. Объект ViewState через другой объект - Storyboard позволяет определить анимацию, изменяющую внешний вид элемента.

      <ControlTemplate TargetType="Button" x:Key="btTemplate">
            <Border Name="RootElement" BorderThickness="3" BorderBrush="Black" CornerRadius="25" >
                <Border.Background>
                    <SolidColorBrush x:Name="BorderColor" Color="Blue" />
                </Border.Background>
                <Grid>
                    <ContentPresenter 
                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Grid>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup Name="CommonStates">
                        <VisualState Name="MouseOver">
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="BorderColor"
                            Storyboard.TargetProperty="Color" 
                            To="Red" />
                            </Storyboard>
                        </VisualState>
                        <VisualState Name="Normal">
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="BorderColor" 
                            Storyboard.TargetProperty="Color" 
                            To="Blue" />
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
            </Border>
        </ControlTemplate>

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

За счет чего это происходит? Корневой элемент Border имеет объект VisualStateManager, у которого, в свою очередь, есть коллекция объектов VisualStateGroup. В данном случае у нас используется только один объект VisualStateGroup - CommonStates. Данная группа содержит такие состояния как MouseOver, Pressed, Normal. А объекты VisualState как раз и задают состояния и применяемую к ним анимацию. Анимацией управляет объект Storyboard. Его свойство TargetName указывает на имя объекта, который анимируется, а TargetProperty - свойство объекта, которое анимируется.

Если объект VisualState используется для визуализации элемента в определенном состоянии, то объект VisualTransition визуализирует элемент в момент перехода от одного состояния в другое. Так если мы задали два визуальных состояния, то мы можем определить визуальный переход из одного состояния в другое:

<ControlTemplate TargetType="Button" x:Key="btTemplate">
            <Border Name="RootElement" BorderThickness="3" BorderBrush="Black" CornerRadius="25" >
                <Border.Background>
                    <SolidColorBrush x:Name="BorderColor" Color="Blue" />
                </Border.Background>
                <Grid>
                    <ContentPresenter 
                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Grid>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup Name="CommonStates">
                        <VisualState Name="MouseOver">
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="BorderColor"
                            Storyboard.TargetProperty="Color" 
                            To="Red" />
                            </Storyboard>
                        </VisualState>
                        <VisualState Name="Normal">
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="BorderColor" 
                            Storyboard.TargetProperty="Color" 
                            To="Blue" />
                            </Storyboard>
                        </VisualState>
                        <VisualStateGroup.Transitions>
                            <VisualTransition From="MouseOver" To="Normal" 
                                    GeneratedDuration="0:0:1.5">
                                <Storyboard>
                                    <ColorAnimationUsingKeyFrames Storyboard.TargetName="BorderColor" 
                                                                  Storyboard.TargetProperty="Color" FillBehavior="HoldEnd">
                                        <ColorAnimationUsingKeyFrames.KeyFrames>
                                            <LinearColorKeyFrame Value="Yellow" KeyTime="0:0:0.5" />
                                            <LinearColorKeyFrame Value="Red" KeyTime="0:0:0.5" />
                                            <LinearColorKeyFrame Value="Green" KeyTime="0:0:0.5" />
                                        </ColorAnimationUsingKeyFrames.KeyFrames>
                                    </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualTransition>
                        </VisualStateGroup.Transitions>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
            </Border>
        </ControlTemplate>

Дополнительную информацию о том, как формируются шаблоны у тех или иных элементов управления, посетив страницу на сайте msdn Control Styles and Template.

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