Рекомендации по разработке элементов управления с возможностью использования стилей

Обновлен: Ноябрь 2007

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

В этом разделе содержатся следующие подразделы.

  • Терминология
  • Перед началом разработки. Представление об элементе управления
  • Общие рекомендации
  • Темы
  • Связанные разделы

Терминология

«Использование стилей и шаблонов» относятся к набору технологий, позволяющих разработчику элементов управления отложить разработку визуальных аспектов элемента управления на этап разработки стилей и шаблонов элемента управления. Этот набор технологий включает:

  • Стили (включая методы задания свойств, триггеры и способы раскадровки).

  • Ресурсы.

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

  • Шаблоны данных.

Введение в методы использования стилей и шаблонов см. в разделе Стилизация и использование шаблонов.

Перед началом разработки. Представление об элементе управления

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

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

Общие рекомендации

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

    • Минимизируйте контракты, насколько возможно.

    • При разработке основывайтесь на факте, что во время проектирования (то есть при использовании средства разработки) для элемента управления естественным является состояние незавершенности. WPF не поддерживает инфраструктуру состояния «составления», поэтому элементы управления нужно создавать, предполагая, что такое состояние может допускаться.

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

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

    • Изолированные вспомогательные элементы — это повторно используемые публичные элементы управления или примитивы, используемые в шаблоне «анонимно», в том смысле, что ни вспомогательный элемент, ни элемент управления с примененным стилем не знают друг о друге. С технической точки зрения любой элемент может быть анонимного типа, но в данном контексте этот термин описывает типы, которые инкапсулируют специализированные функции для выполнения целевых сценариев.

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

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

    Следующая таблица иллюстрирует современное использование вспомогательных элементов в стилях элементов управления (данный список не является полным):

    Элемент

    Тип

    Использующие элементы

    ContentPresenter

    Основанные на типе

    Button, CheckBox, RadioButton, Frame и т.д. (все типы ContentControl)

    ItemsPresenter

    Основанные на типе

    ListBox, ComboBox, Menu и т.д. (все типы ItemsControl)

    ToolBarOverflowPanel

    Именованные

    ToolBar

    Popup

    Изолированные

    ComboBox, ToolBar, Menu, ToolTip и т.д.

    RepeatButton

    Именованные

    Slider, ScrollBar и т.д.

    ScrollBar

    Именованные

    ScrollViewer

    ScrollViewer

    Изолированные

    ListBox, ComboBox, Menu, Frame и т.д.

    TabPanel

    Изолированные

    TabControl

    TextBox

    Именованные

    ComboBox

    TickBar

    Основанные на типе

    Slider

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

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

    • Основанные на типах вспомогательные элементы должны непосредственно устанавливать себе все необходимые параметры. Это может потребовать запроса вспомогательным элементом информационного контекста, в котором он используется, включая его TemplatedParent (тип элемента управления для шаблона, в котором он используется). Например, ContentPresenter автоматически привязывает свойство Content его TemplatedParent к его свойству Content при использовании в производном типе ContentControl.

    • Изолированные вспомогательные элементы не могут быть оптимизированы таким образом, так как, по определению, ни вспомогательный элемент, ни родительский элемент не знают друг о друге.

  • Чтобы пометить элементы внутри шаблона используйте свойство «Имя». Элемент управления, которому необходимо найти элемент в его стиле для программного доступа к нему, должен для этого использовать свойство Name и парадигму FindName. Элемент управления не должен вызывать исключение, когда элемент не найден, он должен без вмешательства пользователя корректно отключить функциональные возможности, которым требуется этот элемент.

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

    1. Привязка свойства. Пример: привязка ComboBox.IsDropDownOpen и ToggleButton.IsChecked.

    2. Вызванные изменения свойств или анимация свойств. Пример: состояние наведения мыши на Button.

    3. Команда. Пример: LineUpCommand / LineDownCommand в ScrollBar.

    4. Изолированные вспомогательные элементы. Пример: TabPanel в TabControl.

    5. Вспомогательные типы, основанные на типах. Пример: ContentPresenter в Button, TickBar in Slider.

    6. Именованные вспомогательные элементы. Пример: TextBox в ComboBox.

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

    8. Пользовательское поведение OnRender. Пример: ButtonChrome в Button.

  • Как можно реже используйте триггеры стиля (в отличие от триггеров шаблона). Триггеры, которые влияют на свойства элементов в шаблоне, должны быть объявлены в шаблоне. Триггеры, которые влияют на свойства элемента управления (не TargetName), могут быть объявлены в стиле, если только не известно, что при изменении шаблона триггер уничтожится.

  • Поддерживайте согласованность с существующими шаблонами стилей. Зачастую существуют различные способы решения проблемы. Будьте осведомленными о шаблонах стилей элементов управления и, если возможно, обеспечивайте согласованность с существующими шаблонами стилей элементов управления. Это особенно важно для элементов управления, производных от одного базового типа (например, ContentControl, ItemsControl, RangeBase и т.д.).

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

    • Самые общие настройки должны быть предоставлены как свойства элемента управления и использоваться шаблоном.

    • Менее общие (хотя не редкие) настройки должны быть предоставлены как вложенные свойства зависимостей и использоваться шаблоном.

    • Для известных, но редких настроек допустимо создание новых шаблонов.

Темы

  • Стили тем должны стремиться к согласованной семантике свойств во всех темах, но ничего не гарантировать. Элемент управления должен содержать в своей документации документ, описывающий семантику свойства элемента управления, то есть «значение» свойства для элемента управления. Например, элемент управления ComboBox должен определять значение свойства Background в ComboBox. Во всех темах стили по умолчанию для элемента управления должны стремиться следовать семантике, определенной в этом документе. С другой стороны, пользователи элемента управления должны знать, что семантика свойств может меняться от темы к теме. В некоторых случаях заданное свойство может оказаться неэффективным с учетом визуальных ограничений, накладываемых конкретной темой. (Например, для многих элементов управления в классической теме нет одинарной границы, к которой можно применить Thickness.)

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

  • Для стилей тем не требуется согласованной для всех тем семантики «макета». Например, стиль по умолчанию не должен гарантировать, что элемент управления будет иметь тот же размер во всех темах или что у него во всех темах будут те же границы/поля содержимого.

См. также

Основные понятия

Стилизация и использование шаблонов

Общие сведения о разработке управления