Общие сведения о вложенных событиях
XAML определяет компонент языка и тип события, называемый присоединенным событием. Концепция присоединенного события позволяет добавить обработчик для конкретного события в произвольный элемент, а не в элемент, который фактически определяет или наследует событие. В этом случае ни объект, потенциально вызывающий событие, ни конечный обрабатывающий экземпляр не определяет или иным образом не "владеет" событием.
Предварительные требования
Предполагается, что вы ознакомились с разделами Общие сведения о перенаправленных событиях и Обзор XAML (WPF).
Синтаксис присоединенных событий
Присоединенные события имеют синтаксис XAML и шаблон кодирования, который должен использоваться резервным кодом для поддержки использования присоединенных событий.
В синтаксисе XAML присоединенное событие указывается не только по имени события, но и по типу владельца и имени события, разделенным символом точки (.). Так как имя события квалифицируется с помощью имени типа, которому оно принадлежит, синтаксис присоединенных событий позволяет подключить любое присоединенное событие к любому элементу, для которого может быть создан экземпляр.
Например, ниже приведен синтаксис XAML для подключения обработчика для пользовательского присоединенного события NeedsCleaning
.
<aqua:Aquarium Name="theAquarium" Height="600" Width="800" aqua:AquariumFilter.NeedsCleaning="WashMe"/>
Обратите внимание на префикс aqua:
. Префикс необходим в этом случае, поскольку присоединенное событие является пользовательским событием, которое поступает из пользовательского сопоставленного xmlns.
Реализация присоединенных событий в WPF
В WPFприсоединенные события, обеспечиваются RoutedEvent поле и перенаправляются через дерево, после их возникновения. Как правило, источником присоединенного события (объектом, вызывающим событие) является система или служба, и таким образом, объект, который выполняет код, порождающий это событие, не является непосредственной частью дерева элементов.
Сценарии для присоединенных событий
В WPFприсоединенные события присутствуют в определенных функциональных областях там, где имеется абстракция уровня службы, такие как для событий, включаемых статическим Mouse класса или Validation класса. Классы, которые взаимодействуют со службой или используют ее, могут использовать событие в синтаксисе присоединенных событий или предоставить присоединенное событие как перенаправленное событие, которое является частью процесса интеграции возможностей службы классом.
Хотя WPF определяет количество присоединенных событий, ситуации, в которых вы будете использовать или обрабатывать присоединенное событие напрямую, очень ограничены. Как правило, присоединенное событие служит в качестве архитектурного элемента, однако затем оно передается в неприсоединенное (поддерживаемое "оболочкой" события CLR) перенаправленное событие.
К примеру, присоединенное событие основной Mouse.MouseDown может намного легче обрабатываться на любой заданной UIElement с помощью MouseDown об этом UIElement вместо работы с синтаксисом присоединенных событий, либо в XAML или кода. Присоединенное событие выполняет определенную роль в архитектуре, поскольку оно обеспечивает будущее расширение типов устройств ввода. Гипотетическому устройству нужно будет только вызвать Mouse.MouseDown в чтобы имитировать ввод от мыши и не может быть производным от Mouse для этого. Однако этот сценарий включает обработку кода события, а обработка XAML присоединенного события не относится к этому сценарию.
Обработка присоединенного события в WPF
Процесс для обработки присоединенного события и код обработчика, который вы будете писать, по сути аналогичны перенаправленному событию.
Как правило, присоединенное событие WPF не сильно отличается от перенаправленного события WPF. Различие заключается в выборе источника события и его представления классом в качестве члена (что также влияет на синтаксис обработчика XAML).
Тем не менее, как было отмечено ранее, существующие присоединенные события WPF не предназначены для обработки в WPF. Гораздо чаще целью событий является включение составного элемента для передачи состояния в родительский элемент при компоновке. В этом случае событие обычно вызывается в коде и зависит от обработки класса в соответствующем родительском классе. Например, элементы в пределах Selector ожидаются для вызова присоединенного Selected обрабатываются события, который затем класс Selector класса и дальнейшим потенциальным преобразованием классом Selector класс в другое перенаправленное событие, SelectionChanged . Дополнительные сведения о перенаправленных событиях и обработке классов см. в разделе Маркировка перенаправленных событий как обработанных и обработка классов.
Определение собственных присоединенных событий как перенаправленных событий
При наследовании от общих базовых классов WPF можно реализовать собственные присоединенные события, включив определенные методы шаблонов в собственный класс и используя вспомогательные методы, которые уже присутствуют в базовых классах.
Шаблон выглядит следующим образом.
Метод добавитьEventNameобработчик с двумя параметрами. Первый параметр является экземпляром, к которому добавляется обработчик событий. Вторым параметром является добавляемый обработчик событий. Этот метод должен быть
public
иstatic
, не возвращая значения.Метод удалитьEventNameобработчик с двумя параметрами. Первый параметр является экземпляр, из которого удаляется обработчик событий. Второй параметр — удаляемый обработчик событий. Этот метод должен быть
public
иstatic
, не возвращая значения.
ДобавитьEventNameобработчик метод доступа упрощает XAML обработку в таких случаях обработчика присоединенного события атрибуты объявляются в элементе. ДобавитьEventNameобработчик и удалитьEventNameобработчик методы также обеспечивают доступ кода к хранилищу обработчика событий для вложенное событие.
Этот общий шаблон еще недостаточно точен для практической реализации в структуре, поскольку реализация любого заданного модуля чтения XAML может иметь разные схемы для идентификации базовых событий в поддерживающем языке и архитектуре. Это одна из причин, WPF реализует присоединенные события как перенаправленные события; идентификатор, используемый для события (RoutedEvent) уже определен WPF системой событий. Кроме того, перенаправление события является естественным расширением реализации для концепции уровня языка XAML присоединенного события.
ДобавитьEventNameобработчик внедрению WPF присоединенное событие состоит из вызова метода AddHandler с перенаправленным событием и обработчиком в качестве аргументов.
Эта стратегия реализации и система перенаправленных событий в общем ограничивают обработку присоединенных событий либо UIElement производные классы или ContentElement производные классы, поскольку только эти классы имеют AddHandler реализаций.
Например, следующий код определяет присоединенное событие NeedsCleaning
в классе владельцаAquarium
, используя стратегию присоединенных событий WPF для объявления присоединенного события как перенаправленного события.
public static readonly RoutedEvent NeedsCleaningEvent = EventManager.RegisterRoutedEvent("NeedsCleaning", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AquariumFilter));
public static void AddNeedsCleaningHandler(DependencyObject d, RoutedEventHandler handler)
{
UIElement uie = d as UIElement;
if (uie != null)
{
uie.AddHandler(AquariumFilter.NeedsCleaningEvent, handler);
}
}
public static void RemoveNeedsCleaningHandler(DependencyObject d, RoutedEventHandler handler)
{
UIElement uie = d as UIElement;
if (uie != null)
{
uie.RemoveHandler(AquariumFilter.NeedsCleaningEvent, handler);
}
}
Обратите внимание, что метод, используемый для установления поля идентификатора присоединенного события, RegisterRoutedEvent, является фактически тот же метод, который используется для регистрации неприсоединенных перенаправленных событий. Все присоединенные события и перенаправленные события регистрируются в централизованном внутреннем хранилище. Эта реализация хранилища событий обеспечивает поддержку режима "события в качестве интерфейса", который рассматривается в разделе Общие сведения о перенаправленных событиях.
Вызов присоединенного события WPF
Как правило, вам не требуется вызывать существующие определенные присоединенные события WPF в коде. Эти события выполните общей концептуальной модели «служба» и классы служб, таких как InputManager несут ответственность за вызов событий.
Тем не менее при определении пользовательского присоединенного события на основе WPF модель создания вложенных событий на RoutedEvent, можно использовать RaiseEvent для вызова присоединенного события из любого UIElement или ContentElement. Вызов перенаправленного события (присоединенного или нет) требует объявления конкретного элемента в дереве элементов в качестве источника события; Этот источник указывается как RaiseEvent вызывающего объекта. За определение того, какой элемент передается как источник в дереве, отвечает служба.