Главная » WPF » Принципы стилизации

0

Идея создания  отдельного  определения стиля или темы витает в воздухе уже давно. Впервые со стилями  и темами я познакомился много лет назад, работая с Microsoft  Word.  В Word  есть именованные контейнеры информации о формати ровании:  Заголовок 1, Заголовок 2, Обычный  и т.д. Первая  попытка  применить стили в мире Web была встроена уже в базовую семантическую разметку, это те ги типа H1, H2 и EMPHASIS. Такие  семантические теги браузер  мог представ лять в том или ином стиле. С появлением каскадных  таблиц стилей (CSS) у ав тора документа появилась возможность определять  свой стиль для любого тега с помощью специального  языка.

В WPF мы с самого начала хотели поддержать  какой то способ стилизации, то есть возможность повторно использовать стилевую информацию для нескольких элементов. Это обеспечило бы единообразие пользовательского интерфейса и подде ржку совместной работы дизайнеров  и программистов. На долю дизайнера  выпада ло бы определение стиля, а программист занимался бы структурой интерфейса. Кри тически важным представлялось наличие единой модели, охватывающей ГИП, доку менты и мультимедиа.  При разработке  системы стилей  в WPF мы руководствова лись тремя принципами: (1) учесть композицию элементов; (2) предоставить унифи цированную модель для настройки; (3) оптимизировать инструментальные средства.

Композиция элементов

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

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

<Window …>

<Window.Styles>

<!— применить этот стиль к любой кнопке Button внутри

StackPanel… (конечно, это не настоящий синтаксис). —>

<Style ApplyTo=’StackPanel   Button’> … </Style>

</Window.Styles>

</Window>

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

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

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

<Window …>

<Window.Style>

<Style>…</Style>

</Window.Style>

<StackPanel>

<StackPanel.Style>

<Style>…</Style>

</StackPanel.Style>

</StackPanel>

</Window>

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

<Window …>

<Window.Resources>

<Style x:Key=’someStyle’>…</Style>

</Window.Resources>

<StackPanel>

<StackPanel.Resources>

<Style x:Key=’someStyle’>…</Style>

</StackPanel.Resources>

<!— Все находящееся внутри StackPanel получит стиль «someStyle» от StackPanel, а не от Window. —>

</StackPanel>

</Window>

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

Унифицированная модель настраивания

В WPF унификация понимается двояко: (1) как возможность применять стили к любому презентационному домену (ГИП,  документам  и мультимедиа); (2) как воз можность настраивать все в системе (свойства,  действия,  отображение  и т.д.). Одно из существенных преимуществ унифицированной презентационной платформы сос тоит в том, что возможность использовать стили повсеместно ничего не стоит при ус ловии, что система стилизации дает доступ ко всем платформенным средствам.

Рис. 8.1. Использование методов установки свойств для применения стилей к ГИП, документам и мультимедиа

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

В примере ниже строится набор стилей, применимых к элементам любого ти

па: абзацам, кнопкам, фигурам  и т.д. (рис. 8.1):

<FlowDocumentScrollViewer xmlns=’http://schemas.microsoft.com/winfx/2006/xaml/presentation’ xmlns:x=’http://schemas.microsoft.com/winfx/2006/xaml’

<FlowDocument>

<FlowDocument.Resources>

<Style TargetType=’{x:Type Paragraph}’>

<Setter Property=’FontFamily’ Value=’Georgia’ />

<Setter Property=’Margin’ Value=’3’ />

</Style>

<Style TargetType=’{x:Type Button}’>

<Setter Property=’FontFamily’ Value=’Tahoma’ />

<Setter Property=’Margin’ Value=’3’ />

</Style>

<Style TargetType=’{x:Type RadioButton}’>

<Setter Property=’FontFamily’ Value=’Tahoma’ />

<Setter Property=’Margin’ Value=’3’ />

</Style>

<Style TargetType=’{x:Type CheckBox}’>

<Setter Property=’FontFamily’ Value=’Tahoma’ />

<Setter Property=’Margin’ Value=’3’ />

</Style>

<Style TargetType=’{x:Type Ellipse}’>

<Setter Property=’Fill’ Value=’Red’ />

<Setter Property=’Margin’ Value=’3’ />

</Style>

<Style TargetType=’{x:Type Rectangle}’>

<Setter Property=’Fill’ Value=’Blue’ />

<Setter Property=’Margin’ Value=’3’ />

</Style>

</FlowDocument.Resources>

<Paragraph>Hello World</Paragraph>

<Paragraph>

<RadioButton>Some</RadioButton>

<Button>UI</Button>

<CheckBox>Controls</CheckBox>

</Paragraph>

<Paragraph>And some interesting shapes:

<Ellipse Width=’15’ Height=’15’ />

<Rectangle Width=’15’ Height=’15’ />

</Paragraph>

</FlowDocument>

</FlowDocumentScrollViewer>

Но ничто не бывает так просто, как хочется. Поэтому  есть несколько  мест, в которых система стилизации раскрывает  детали реализации ядра WPF. Напри мер, самый естественный  способ применения триггера к элементу  состоит в том, чтобы записать свойство Triggers элемента в объект Setter:

<Style TargetType=’{x:Type Button}’>

<!— не работает —>

<Setter Property=’Triggers’>

<Setter.Value>

<Trigger Property=’IsMouseOver’ Value=’True’>

</Trigger>

</Setter.Value>

</Setter>

</Style>

Однако  из за некоторых  деталей реализации механизма  применения тригге ров мы были вынуждены прибегнуть к более специализированной модели, осно ванной на свойстве Style.Triggers:

<Style TargetType=’{x:Type Button}’>

<Style.Triggers>

<Trigger Property=’IsMouseOver’ Value=’True’>

</Trigger>

</Style.Triggers>

</Style>

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

Источник: К. Андерсон  Основы  Windows Presentation Foundation. Пер. с англ. А. Слинкина — М.: ДМК Пресс, 2008 — 432 с.: ил.

По теме:

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