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

84

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

Иногда возникает потребность создать стиль, который не только изменяет ряд уставок общих свойств целевого элемента управления, но и переопределяет форму самого элемента управления. Так, в конкретном проекте может потребоваться круглая форма кнопки или произвольная многоугольная форма, нарисованная инструментом Pen или Pencil.

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

Несмотря на то что шаблон является наиболее часто используемой составляющей более крупного стиля, имеется все же возможность определить автономный ресурс объекта в элементе разметки <ControlTemplate>. Настраивая свойство Template (Шаблон) элементов управления, можно назначать для них заданные шаблоны. В следующем примере проекта будет показано, как это делается.

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

Используемые по умолчанию шаблоны входят в состав библиотек на платформах WPF и Silverlight в качестве встраиваемых XAML-ресурсов, и поэтому не могут быть изменены непосредственно. Но, как будет показано далее, в среде Expression Blend предоставляется ряд механизмов для извлечения копии используемого по умолчанию шаблона с целью его последующей правки.

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

Для определения нового шаблона (или видоизменения уже имеющегося), как правило, требуется предоставлять специальные элементы разметки XAML, описывающие реакцию элемента управления на те же самые изменения состояния. Как будет показано далее, в шаблоне на платформе WPF можно определить визуальные подсказки используя два следующих средства: триггеры или диспетчер визуальных состояний (VSM — Visual State Manager), тогда как на платформе Silverlight это можно сделать только с помощью диспетчера VSM. Далее будет также показано, что в среду Ехpression Blend интегрированы специальные редакторы, предназначенные для работы с каждым из этих двух средств.

Диспетчер VSM был впервые введен в состав прикладного интерфейса Silverlight API и служит для внедрения визуальных подсказок в шаблон на платформе Silverlight. Исторически сложилось так, что программирующие на платформе WPF применяли аналогичный подход посредством триггеров. Но после выпуска версии .NET 4.0 платформа WPF была обновлена, чтобы поддерживать диспетчер VSM, а, следовательно, программирующие на этой платформе получили возможность пользоваться двумя разными средствами (триггерами и диспетчером VSM) для реализации визуальных подсказок. Применение обоих этих средств демонстрируется в рассматриваемых далее примерах.

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

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

Итак, создайте новый проект приложения WPF, присвоив ему имя WpfTemplatesByHand. После этого добавьте одну кнопку (объект типа Button) на монтажном столе в исходном окне типа Window. В настоящий момент кнопка визуализируется с помощью связанного с ней шаблона, используемого по умолчанию. Как упоминалось ранее, этот шаблон является ресурсом, встраиваемым в соответствующую библиотеку на платформе WPF или Silverlight. Определяя свой шаблон, вы по существу, заменяете набор инструкций из используемого по умолчанию шаблона собственным набором инструкций.

Для примера используйте следующий шаблон для кнопки в разметке XAML:

<Button Height="100" Width="100" Margin="80,73,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
			<Button.Template>
				<ControlTemplate>
					<Grid x:Name="controlLayout">
						<Ellipse x:Name="buttonSurface" Fill="LightBlue"></Ellipse>
						<Label x:Name="buttonCaption" VerticalAlignment="Center"
						       HorizontalAlignment="Center"
							   FontWeight="Bold" FontSize="20" Content="OK!"></Label>
					</Grid>
				</ControlTemplate>
			</Button.Template>
		</Button>

В приведенной выше разметке определен шаблон, состоящий из именованного элемента управления типа Grid, содержащего, в свою очередь, элементы управления типа Ellipse и Label. А поскольку строки или столбцы сетки не определены, то каждый последующий потомок объекта типа Grid располагается над предыдущим, что даёт возможность без труда отцентровать содержимое данного объекта с помощью его свойств VerticalAligment (Выравнивание по вертикали) и HorizontalAligment (Выравнивание по горизонтали). Обратите также внимание на то, что все содержимое злемента разметки <ControlTemplate> присваивается свойству Template элемента управления типа Button в элементе разметки <Button.Template>.

Для последующей проверки своего шаблона организуйте на панели Properties обработку события Click, наступающего после щелчка на кнопке, представленной объектом типа Button.

Сохранение шаблонов в виде ресурсов

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

Итак, переместите ресурс локального обыкта типа Button на уровень приложения. Для этого найдите сначала свойство Template данного объекта на панели Properties. Затем откройте меню дополнительных параметров, щелкнув на белом квадратике справа от текстового поля данного свойства. Выберите из этого меню команду Convert to New Resource:

Извлечение шаблона  в ресурс

Определите в открывшемся диалоговом окне новый шаблон, сохраняемый под именем RoundButtonTemplate (Шаблон круглой кнопки) в качестве ресурса приложения.

Обратите также внимание на то, что разметка, описывающая исходный объект типа Button, видоизменена. Как показано ниже, в свойстве Template этого объекта ваш шаблон установлен в качестве специального именованного ресурса:

<Button Height="100" Width="100" Margin="80,73,0,0" 
		VerticalAlignment="Top" HorizontalAlignment="Left" Click="Button_Click" 
		Template="{DynamicResource RoundButtonTemplate}"/>

Этот ресурс теперь доступен для всего приложения, а следовательно, в данном приложении можно определить сколько угодно круглых кнопок. Итак, добавьте еще два элемента управления типа Button на монтажном столе исходного окна типа Window. Затем перейдите к панели Properties и установите в свойстве Template каждого из этих элементов управления ресурс RoundButtonTemplate:

Установка специального шаблона Template
Три круглые кнопки, оформленные по единому шаблону

Внедрение визуальных подсказок с помощью триггеров на платформе WPF

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

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

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

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

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

<ControlTemplate x:Key="RoundButtonTemplate" TargetType="{x:Type Button}">
			<Grid x:Name="controlLayout">
				<Ellipse x:Name="buttonSurface" Fill="LightBlue"/>
				<Label x:Name="buttonCaption" VerticalAlignment="Center"
					HorizontalAlignment="Center"
					FontWeight="Bold" FontSize="20" Content="OK!"/>
			</Grid>
		
		<ControlTemplate.Triggers>
			<Trigger Property="IsMouseOver" Value="True">
				<Setter TargetName="buttonSurface" Property="Fill" Value="Blue"></Setter>
				<Setter TargetName="buttonCaption" Property="Foreground" Value="Yellow"></Setter>
			</Trigger>
		</ControlTemplate.Triggers>
</ControlTemplate>

Если вы еще раз запустите свое приложение на выполнение, то обнаружите изменение цвета кнопки, когда курсор мыши оказывается в пределах ее границ. Обратите также внимание на то, что данный конкретный элемент <Trigger> определен таким образом, что при установке логического значения true в свойстве IsMouseOver (Курсор мыши наведен) два целевых элемента (buttonSurface и buttonCaption), указываемых в свойстве TargetName (Имя целевого объекта), соответственно изменяют свое состояние.

Приведенная выше разметка не должна вас особенно смущать. Ведь большинство программирующих на платформе WPF согласны с тем, что устанавливать триггеры вручную — занятие малопривлекательное. Поэтому далее будет показано, каким образом панель Triggers используется в Expression Blend для автоматического формирования логики работы триггеров.

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

Пройди тесты
Лучший чат для C# программистов