Главная » Разработка для Windows Phone 7 » Совместное и повторное использование стилей шаблонов Windows Phone 7

0

Как известно, можно наследовать один Style от другого, при этом наследуются все объекты Setter. Новый Style может добавлять новые Setter или переопределять имеющиеся.

А вот от ControlTemplate наследоваться нельзя. Нельзя сослаться на существующий ControlTemplate и заменить часть его дерева визуальных элементов или задать что-то дополнительно. (Довольно сложно представить механизм или синтаксис такого процесса.)

Как правило, если требуется внести какие-либо изменения в существующий ControlTemplate, необходимо получить копию всего шаблона и редактировать ее. Шаблоны по умолчанию обычно включены в документацию Silverlight. (Но как я уже упоминал в этой главе, документация Silverlight включает только шаблоны для Веб-версии Silverlight, в ней нет шаблонов для Silverlight for Windows Phone.) Expression Blend также имеет доступ к стандартным шаблонам по умолчанию.

Если требуется использовать совместно Style или ControlTemplate (или Style, включающий ControlTemplate) для нескольких элементов страницы, просто поместите его в коллекцию Resources этой страницы. Если требуется использовать Style или ControlTemplate для нескольких страниц, поместите его в коллекцию Resources файла App.xaml.

Также ресурсы могут использоваться совместно несколькими приложениями. Для этого ресурсы описываются в XAML-файле, корневым элементом которого является ResourceDictionary. Рассмотрим такой файл, который называется SharedResources.xaml:

<ResourceDictionary

xmlns="http://schemas.microsoft.com/winfx/2 0 0 6/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2 0 0 6/xaml">

<SolidColorBrush x:Key="brush" Color="Blue" /> </ResourceDictionary>

Файл может иметь не только SolidColorBrush, а намного больше ресурсов. У каждого ресурса, конечно же, должен быть атрибут x:Key. Этот файл можно создавать как часть проекта или добавлять в проект уже существующий файл. В любом случае для Build Action в окне свойств должно быть задано Page.

Теперь мы можем сослаться на этот файл в коллекции Resources в App.xaml:

<Application.Resources> <ResourceDictionary>

<ResourceDictionary.MergedDictionaries>

<ResourceDictionary Source="SharedResources.xaml" />

</ResourceDictionary.MergedDictionaries>

</ResourceDictionary> </Application.Resources>

Обратите внимание, что свойство-элемент ResourceDictionary.MergedDictionary (Объединенный словарь) используется для ссылки на внешние объекты ResourceDictionary.

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

Рассмотрим приложение FlipToggleDemo (Демонстрация переключателя с переворачиванием), включающее пользовательский класс FlipToggleButton (Переключатель с переворачиванием), наследуемый от ToggleButton. Но FlipToggleButton не вносит никакого нового кода в ToggleButton, добавляются только Style и ControlTemplate.

В проекте FlipToggleDemo я добавил новый элемент типа Windows Phone User Control (Пользовательский элемент управления для Windows Phone) и назвал его FlipToggleButton.xaml. В результате этого были созданы файл FlipToggleButton.xaml и файл FlipToggleButton.xaml.cs для класса, который наследуется от UserControl. После этого в обоих файлах я изменил UserControl на ToggleButton, так чтобы FlipToggleButton наследовался от ToggleButton.

Чтобы не усложнять, я решил не реализовывать никакие смены состояний для неактивной кнопки, но переворачивать ее для состояния Unchecked. Рассмотрим полный XAML-файл для пользовательской кнопки. (Отступы уменьшены на два пробела, чтобы строки не превышали ширины страницы книги.):

Проект Silverlight: FlipToggleDemo Файл: FlipToggleButton.xaml <ToggleButton x:Class="FlipToggleDemo.FlipToggleButton"

xmlns="http://schemas.microsoft.com/winfx/2 0 0 6/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2 0 0 6/xaml"> <ToggleButton.Style>

<Style TargetType="ToggleButton"> <Setter Property="Template"> <Setter.Value>

<ControlTemplate TargetType="ToggleButton">

<Border BorderBrush="{StaticResource PhoneForegroundBrush}"

BorderThickness="{StaticResource PhoneBorderThickness}" Background="{TemplateBinding Background}" RenderTransform0rigin="0.5 0.5"> <Border.RenderTransform>

<RotateTransform x:Name="rotate" /> </Border.RenderTransform>

<VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CheckStates"> <VisualState x:Name="Checked"> <Storyboard>

<DoubleAnimation Storyboard.TargetName="rotate"

Storyboard.TargetProperty="Angle" To="18 0" Duration="0:0:0.5" />

</Storyboard> </VisualState>

<VisualState x:Name="Unchecked"> <Storyboard>

<DoubleAnimation Storyboard.TargetName="rotate"

Storyboard.TargetProperty="Angle" Duration="0:0:0.5" />

</Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups>

<ContentPresenter Content="{TemplateBinding Content}"

ContentTemplate="{TemplateBinding ContentTemplate}" Margin="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding

HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding

VerticalContentAlignment}" />

</Border> </ControlTemplate> </Setter.Value> </Setter> </Style> </ToggleButton.Style> </ToggleButton>

Обычно основную часть XAML-файла занимает свойство Content корневого элемента. В данном случае это свойство Style корневого элемента. Обратите внимание, что и для объекта Style, и для объекта ControlTemplate в качестве значения свойства TargetType задан ToggleButton, а не FlipToggleButton. В этом нет никакой ошибки, потому что ни один из них не использует никаких свойств, специально определенных FlipToggleButton, потому что FlipToggleButton не определяет никаких новых свойств FlipToggleButton.

Сам шаблон довольно прост и включает только Border и ContentPresenter со всеми привязками, определенными в стандартном шаблоне. Но Border также описывает свойство RenderTransformOrigin, и значением его свойства RenderTransform задан объект RotateTransform.

Для двух анимаций, обеспечивающих переворот кнопки (для состояния Checked) и возвращение ее в нормальное положение (для состояния Unchecked), задана отличная от нуля продолжительность. Для DoubleAnimation, реализующего состояние Checked, не задано значение From; используется базовое значение этого свойства, которое равно нулю. Для DoubleAnimation, реализующего состояние Unchecked, не задано ни To, ни From! Анимация начинается со значения свойства Angle объекта RotateTransform – вероятнее всего это будет 180 градусов, но может быть и меньше, если предыдущая анимация не была полностью завершена к моменту перехода кнопки в состояние Unchecked – и завершается в базовом значении, которым является нуль.

Рассмотрим файл выделенного кода для пользовательского элемента управления полностью: Проект Silverlight: FlipToggleDemo Файл: FlipToggleButton.xaml.cs

using System.Windows.Controls.Primitives;

namespace FlipToggleDemo {

public partial class FlipToggleButton : ToggleButton {

public FlipToggleButton() {

InitializeComponent();

}

}

}

Экземпляр пользовательской кнопки создается в файле MainPage.xaml проекта: Проект Silverlight: FlipToggleDemo Файл: MainPage.xaml (фрагмент)

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <local:FlipToggleButton Content="Flip Toggle"

HorizontalAlignment="Center" VerticalAlignment="Center" />

</Grid>

Источник: Чарльз Петзольд, Программируем Windows Phone 7, Microsoft Press, © 2011.

По теме:

  • Комментарии