Шаблоны на Silverlight API

25

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

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

По сушеству, в данном примере будет воссоздан рассмотренный ранее шаблон круглой кнопки, но на этот раз с помощью диспетчера VSM, а не триггеров, доступных на платформе WPF. Прежде всего создайте новый проект приложения Silverlight. Затем нарисуйте произвольную форму на монтажном столе инструментом Pen или Pencil либо выберите готовую форму из категории Shapes в библиотеке ресурсов. И в этом случае можете выбрать простую форму эллипса, заполнив ее зеленым цветом. Щелкните правой кнопкой мыши на этой геометрической форме и выберите, как и прежде, команду Make Into Control из контекстного меню:

Создание шаблона в проекте Silverlight

Определите новый ресурс, именуемый SilverlightRoundButtonTemplate. доступный на уровне приложения и предназначенный для стилевого оформления элементов управления типа Button, в открывшемся диалоговом окне. Как только вы щелкнете на кнопке ОК, появится окно визуального конструктора круглой кнопки, оформляемой по новому шаблону. Этот шаблон можно, как и прежде, поправить и видоизменить на панели Properties, Objects and Timeline и в редакторе, выбираемом по навигационной цепочке.

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

Работа с диспетчером VSM на панели States

Подобно панели Triggers в проектах, разрабатываемых на платформе WPF, панель States служит для внесения изменений визуального состояния в выбранный шаблон, но делается это совершенно по-другому. Если окно с монтажным столом активизировано для выбранного шаблона, разрабатываемого на платформе Silverlight, перейдите к панели States, обратив внимание на исходные установки:

Панель States

По умолчанию в пустом шаблоне вообще отсутствуют визуальные состояния. Но как только вы перейдете к панели States, то обнаружите на ней ряд общедоступных визуальных состояний (Normal, MouseOver, Pressed, Disabled, Unfocused и Focused), разделенных на две группы: CommonStates (Общие состояния) и FocusStates (Состояния фокуса). Как будет показано далее, к этим двум группам можно также добавить группы специальных состояний.

Эти группы стандартных состояний удобны тем, что в элементах управления на платформах WPF и Silverlight автоматически реализуются переходы в эти состояния, когда происходит соответствующее действие. Иными словами, если пользователь щелкнет кнопкой мыши на элементе управления, последний автоматически перейдет в состояние Pressed (Нажато). Если же элемент окажется вне логического фокуса и каких-либо действий мышью, то он автоматически перейдет в состояние Normal (Обычное) и т.д.

Для большей наглядности переход элемента управления в состояние Mouseover (Наведен курсор мыши) можно дополнить соответствующей анимацией, описываемой в разметке. С этой целью выберите состояние Mouseover на панели States. В итоге произойдет автоматический переход в режим регистрации. Как и при создании обычной анимации, в данном случае вы сможете внести любые изменения в свойства выбранного элемента управления на панели Properties. Что же касается состояния Mouseover, то выберите более темный оттенок цвета заполнения формы эллипса в свойстве Fill:

Регистрация изменений, с помощью визуальных состояний

А теперь выберите состояние Pressed на панели States. Выполните графическое преобразование формы эллипса таким образом, чтобы размеры соответствующею элемента управления немного сокращались при переходе в данное состояние. С этой целью перейдите к области Transform на панели Properties (напомним, что на вкладке Scale в этой области доступны преобразования масштабированием).

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

Если вы откроете файл разметки приложения App.xaml в редакторе XAML, то заметите, что в элементе разметки <style> появился целый ряд новых инструкций определяющих изменения, внесенные вами в различные визуальные состояния:

<VisualStateManager.VisualStateGroups>
			<VisualStateGroup x:Name="CommonStates">
									<VisualState x:Name="Disabled"/>
									<VisualState x:Name="Normal"/>
									<VisualState x:Name="MouseOver">
										<Storyboard>
											<ColorAnimation Duration="0" To="#FF177A0F" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="ellipse" d:IsOptimized="True"/>
										</Storyboard>
									</VisualState>
									<VisualState x:Name="Pressed">
										<Storyboard>
											<DoubleAnimation Duration="0" To="0.8" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="ellipse" d:IsOptimized="True"/>
											<DoubleAnimation Duration="0" To="0.8" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" Storyboard.TargetName="ellipse" d:IsOptimized="True"/>
										</Storyboard>
									</VisualState>
			</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

Когда происходит переход в определенное состояние по умолчанию выполняется код элементе разметки <Storyboard>, связанном с этим состоянием. По желанию можете определить новое время перехода для всех состояний из отдельной группы, откорректировав устанавливаемое по умолчанию нулевое значение этого параметра:

Изменение времени перехода для состояния

Настройка отдельных переходов

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

Добавление эффектов инерционности движения в анимацию смены состояний

В качестве примера выберите состояние Focused (В фокусе) из группы FocusedStates (Состояния в фокусе). Обратите внимание на кнопку справа от наименования этого и других состоянии из данной группы. (Она обозначена стрелкой, направленной вправо и мелким знаком +). Если щелкнуть на этой кнопке, которая официально называется Add Transition (Добавить переход), отобразится ряд редакторов переходов в состояния.

С помощью этих редакторов можно задавать эффекты перехода из текущего состояния в состояние Focused, из состояния Focused - в состояние Unfocused (Вне фокуса) и обратно в состояние Focused, но не спешите задавать какие-либо переходы.

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

Краткий обзор специальных состояний

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

Допустим, шаблон должен обеспечивать особый внешний вид элемента управления, когда пользователь нажимает клавишу <Shift> и щелкает кнопкой мыши на этом элементе. Такого результата можно добиться с помощью групп специально настраиваемых состояний. Для того чтобы показать, каким образом подобная задача решается с помощью диспетчера VSM, перейдем к рассмотрению вопроса, касающегося создания специальных объектов типа UserControl.

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