Автор работы: Пользователь скрыл имя, 19 Октября 2012 в 19:18, реферат
Что собой представляют пользовательские элементы в WPF
Хотя пользовательский элемент можно построить в любом проекте WPF, обычно такие элементы размещаются в специально выделенной сборке — библиотеке классов (DLL). Это позволяет разделять работу с множеством приложений WPF.
Надежные команды
Описанный выше прием представляет
собой совершенно законный способ подключения
команд к элементам управления, но
элементы WPF и профессиональные элементы
управления его не используют. Они
применяют более надежный подход,
присоединяя статические обработчики
команд с помощью метода CommandManager.
Основная проблема, связанная с реализацией, продемонстрированной в предыдущем разделе, заключается в том, что она использует общедоступную коллекцию CommandBindings. Это делает ее несколько хрупкой, поскольку клиент может легко модифицировать коллекцию CommandBindings.
Подобное невозможно в
случае применения метода RegisterClassCommandBinding().
И именно такой подход используют
элементы управления WPF. Например, если
посмотреть на коллекцию CommandBindings из TextBox,
то в ней не будет никаких привязок
для жестко закодированных команд Undo,
Redo, Cut, Сору и Paste, поскольку они зарегистрированы
как привязки классов. Техника довольно
проста. Вместо создания привязок команд
в конструкторе экземпляра, их понадобится
создавать в статическом
CommandManager.
new CommandBinding(
UndoCommand_Executed, UndoCommand_CanExecute));
Хотя этот код изменен незначительно, все же он демонстрирует существенный сдвиг. Поскольку ссылки на методы UndoCommand_Executed() и UndoCommand_CanExecute() присутствуют в конструкторе, оба они должны быть статическими. Чтобы извлечь данные экземпляра (такие как информацию о текущем и предшествующем цветах), нужно привести отправителя события к объекту ColorPicker и использовать его.
Ниже приведен пересмотренный код обработки команд:
private static void UndoCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
ColorPickerUserControl colorPicker = (ColorPickerUserControl)
e.CanExecute = colorPicker.previousColor.
}
private static void UndoCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
ColorPickerUserControl colorPicker = (ColorPickerUserControl)
colorPicker.Color = (Color)colorPicker.
}
Кстати, этот подход не ограничивается
командами. Если хотите привязать логику
обработки событий к элементу
управления, можете воспользоваться
обработчиком событий класса с методом
EventManager.
UserControl
Пользовательские элементы
предлагают довольно-таки безболезненный,
но в некотором отношении
"За кулисами" класс
UserControl работает во многом подобно
классу ContentControl, от которого он
унаследован. В
Например, при обработке
события UIElement.MouseLeftButtonDown в контейнере
компоновки, содержащем в себе созданный
ранее указатель цвета, будет
получено событие, когда выполняется
щелчок кнопкой мыши внутри Rectangle. Однако
источником этого события будет
не Rectangle, а объект ColorPicker, содержащий
этот Rectangle. Если создать тот же самый
указатель цвета как обычный
элемент с содержимым, то этого
не будет — в данном случае на
вас возлагается обязанность
перехватывать событие в
Наиболее существенное отличие пользовательских элементов от других типов специальных элементов управления заключается в способе их проектирования. Как и все элементы управления, пользовательские элементы имеют шаблон. Однако этот шаблон изменяется редко. Вместо этого создается код разметки как часть класса специального пользовательского элемента управления, и этот код разметки обрабатывается с применением метода InitializeComponent() при создании элемента. С другой стороны, элемент управления, не имеющий внешнего вида, не имеет и разметки. Все, что ему нужно — это шаблон.
Обычный ContentControl имеет следующий упрощенный шаблон:
<ControlTemplate TargetType="ContentControl">
<ContentPresenter
ContentTemplate="{
Content="{TemplateBinding ContentControl.Content} " />
</ControlTemplate>
Этот шаблон всего лишь наполняет полученным содержимым и применяет необязательный шаблон содержимого. Свойства вроде Padding, Background, HorizontalAlignment и VerticalAlignment не дают никакого эффекта, если только явно не привязать их.
UserControl имеет похожий шаблон,
но с несколькими
Формально шаблон пользовательского
элемента управления может быть изменен.
В действительности можно переместить
весь код разметки в шаблон, лишь
слегка видоизменив ее. Но на самом
деле делать это незачем: если необходим
более гибкий элемент управления,
в котором внешний вид отделен
от интерфейса, предоставляемого классом
этого элемента, то лучше создать
собственный элемент
Создание элемента управления, лишенного внешнего вида
Цель пользовательских элементов
управления заключается в предоставлении
поверхности визуального
Некоторые аспекты пользовательского
элемента управления удастся изменить
через стили, но часть из них заблокирована
внутри, будучи жестко закодированной
в разметке. Например, нет никакой
возможности переместить
Решение этой проблемы состоит
в создании элемента управления без
внешнего вида, т.е. элемента управления
на основе одного из базовых классов,
не имеющих поверхности
Рефакторинг кода указателя цвета
Превратить рассмотренный указатель цвета в элемент управления без внешнего вида не так трудно. Первый шаг прост — нужно всего лишь изменить объявление класса, как показано ниже:
public class ColorPicker : System.Windows.Controls.
{ ... }
В этом примере класс ColorPicker наследуется от Control. Класс FrameworkElement не подходит, поскольку указатель цвета требует взаимодействия с пользователем, а другие высокоуровневые классы не могут точно описать его поведение. Например, указатель цвета не позволяет вставлять в него другое содержимое, а потому ContentControl тоже не годится.
Код внутри класса ColorPicker точно такой же, как код пользовательского элемента управления (за исключением того факта, что из конструктора понадобится удалить вызов InitializeComponent()). Вы следуете тому же подходу для определения свойств зависимости и маршрутизируемых событий. Единственное отличие связано с необходимостью сообщения WPF о том, что для класса элемента управления будет предоставлен новый стиль. Этот стиль будет обеспечен новым шаблоном элемента. (Если пропустить этот шаг, будет использован шаблон, определенный в базовом классе.)
Чтобы сообщить WPF о том, что
предоставляется новый стиль, следует
вызвать метод OverrideMetadata
DefaultStyleKeyProperty.
new FrameworkPropertyMetadata(
Можно предоставить другой
тип, если нужно использовать шаблон
другого класса элемента управления,
но почти всегда для каждого из
собственных пользовательских элементов
управления будет создаваться
Рефакторинг кода разметки указателя цвета
После добавления вызова OverrideMetadata понадобится просто подключить правильный стиль. Этот стиль должен быть помещен в словарь ресурсов по имени generic.xaml, который следует сохранить в папке Themes проекта. Таким образом, этот стиль будет распознан как стиль по умолчанию для элемента управления. Для добавления файла generic.xaml выполните следующие шаги:
Часто библиотека пользовательских элементов управления содержит несколько таких элементов. Чтобы держать их стили отдельно для облегчения редактирования, файл generic.xaml часто использует слияние словарей ресурсов. В следующей разметке показано содержимое файла generic.xaml, который извлекает ресурсы из ресурсного словаря ColorPicker.xaml в той же папке Themes библиотеки элементов управления по имени CustomControls:
<ResourceDictionary xmlns="http://schemas.
xmlns:x="http://schemas.
<ResourceDictionary.
<ResourceDictionary
Source="/ColorPicker;
</ResourceDictionary.
</ResourceDictionary>
Стиль пользовательского элемента управления должен использовать атрибут TargetType для автоматического присоединения себя к указателю цвета.
Стиль можно использовать для установки любых свойств в классе элемента управления (независимо от того, наследуются они от базового класса или добавлены вами). Однако наиболее полезная задача, которую выполняет стиль — это применение нового шаблона, определяющего визуальное представление по умолчанию для элемента управления.
Преобразовать обычный код разметки (подобный тому, что используется для нашего указателя цвета) в шаблон элемента управления очень легко. Необходимо принять во внимание описанные ниже соображения:
Принимая во внимание перечисленные соображения, можно создать следующий шаблон для указателя цвета: