UserControl
64WPF --- Шаблоны и пользовательские элементы управления WPF --- UserControl
Пользовательские элементы предлагают довольно-таки безболезненный, но в некотором отношении ограниченный способ создания специальных элементов управления. Чтобы понять — почему, давайте присмотримся к тому, как функционирует UserControl.
"За кулисами" класс UserControl работает во многом подобно классу ContentControl, от которого он унаследован. В действительности ключевых отличий немного:
Класс UserControl изменяет некоторые значения по умолчанию. А именно: устанавливает IsTabStop и Focusable в false (так что он не занимает отдельного места в последовательности обхода по клавише <Tab>), а также устанавливает HorizontalAlignment и VerticalAlignment в Stretch (вместо Left и Тор), в результате заполняя все доступное пространство.
Класс UserControl применяет новый шаблон элемента управления, состоящий из элемента Border, который упаковывает ContentPresenter. Элемент ContentPresenter хранит в себе содержимое, которое добавляется посредством кода разметки.
Класс UserControl изменяет источник маршрутизированных событий. Когда событие распространяется пузырьком или туннелируется от элемента управления, находящегося внутри пользовательского элемента, к элементу, находящемуся вне его, источник изменяется и указывает на пользовательский элемент управления вместо первоначального элемента. Это немного повышает степень инкапсуляции.
Например, при обработке события UIElement.MouseLeftButtonDown в контейнере компоновки, содержащем в себе созданный ранее указатель цвета, будет получено событие, когда выполняется щелчок кнопкой мыши внутри Rectangle. Однако источником этого события будет не Rectangle, а объект ColorPicker, содержащий этот Rectangle. Если создать тот же самый указатель цвета как обычный элемент с содержимым, то этого не будет — в данном случае на вас возлагается обязанность перехватывать событие в элементе управления, обрабатывать его и возбуждать повторно.
Наиболее существенное отличие пользовательских элементов от других типов специальных элементов управления заключается в способе их проектирования. Как и все элементы управления, пользовательские элементы имеют шаблон. Однако этот шаблон изменяется редко. Вместо этого создается код разметки как часть класса специального пользовательского элемента управления, и этот код разметки обрабатывается с применением метода InitializeComponent() при создании элемента. С другой стороны, элемент управления, не имеющий внешнего вида, не имеет и разметки. Все, что ему нужно — это шаблон.
Обычный ContentControl имеет следующий упрощенный шаблон:
<ControlTemplate TargetType="ContentControl">
<ContentPresenter
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
Content="{TemplateBinding ContentControl.Content} " />
</ControlTemplate>
Этот шаблон всего лишь наполняет полученным содержимым и применяет необязательный шаблон содержимого. Свойства вроде Padding, Background, HorizontalAlignment и VerticalAlignment не дают никакого эффекта, если только явно не привязать их.
UserControl имеет похожий шаблон, но с несколькими дополнительными тонкостями. Наиболее очевидно то, что он добавляет элемент Border и привязывает его свойства к свойствам BorderBrush, BorderThickness, Background и Padding пользовательского элемента управления, чтобы они что-нибудь делали. Вдобавок ContentPresenter внутри привязывается к свойствам выравнивания.
Формально шаблон пользовательского элемента управления может быть изменен. В действительности можно переместить весь код разметки в шаблон, лишь слегка видоизменив ее. Но на самом деле делать это незачем: если необходим более гибкий элемент управления, в котором внешний вид отделен от интерфейса, предоставляемого классом этого элемента, то лучше создать собственный элемент управления, лишенный внешнего вида, как описано в следующей статье.