Общие сведения о вложенных событияхAttached Events Overview

Язык XAMLExtensible Application Markup Language (XAML) определяет компонент языка и тип события, называемый присоединенным событием.defines a language component and type of event called an attached event. Концепция присоединенного события позволяет добавить обработчик для конкретного события в произвольный элемент, а не в элемент, который фактически определяет или наследует событие.The concept of an attached event enables you to add a handler for a particular event to an arbitrary element rather than to an element that actually defines or inherits the event. В этом случае ни объект, потенциально вызывающий событие, ни конечный обрабатывающий экземпляр не определяет или иным образом не "владеет" событием.In this case, neither the object potentially raising the event nor the destination handling instance defines or otherwise "owns" the event.

Предварительные требованияPrerequisites

Предполагается, что вы ознакомились с разделами Общие сведения о перенаправленных событиях и Обзор XAML (WPF).This topic assumes that you have read Routed Events Overview and XAML Overview (WPF).

Синтаксис присоединенных событийAttached Event Syntax

Присоединенные события имеют синтаксис XAMLXAML и шаблон кодирования, который должен использоваться резервным кодом для поддержки использования присоединенных событий.Attached events have a XAMLXAML syntax and a coding pattern that must be used by the backing code in order to support the attached event usage.

В синтаксисе XAMLXAML присоединенное событие указывается не только по имени события, но и по типу владельца и имени события, разделенным символом точки (.).In XAMLXAML syntax, the attached event is specified not just by its event name, but by its owning type plus the event name, separated by a dot (.). Так как имя события квалифицируется с помощью имени типа, которому оно принадлежит, синтаксис присоединенных событий позволяет подключить любое присоединенное событие к любому элементу, для которого может быть создан экземпляр.Because the event name is qualified with the name of its owning type, the attached event syntax allows any attached event to be attached to any element that can be instantiated.

Например, ниже приведен синтаксис XAMLXAML для подключения обработчика для пользовательского присоединенного события NeedsCleaning.For example, the following is the XAMLXAML syntax for attaching a handler for a custom NeedsCleaning attached event:

<aqua:Aquarium Name="theAquarium" Height="600" Width="800" aqua:AquariumFilter.NeedsCleaning="WashMe"/>

Обратите внимание на префикс aqua:. Префикс необходим в этом случае, поскольку присоединенное событие является пользовательским событием, которое поступает из пользовательского сопоставленного xmlns.Note the aqua: prefix; the prefix is necessary in this case because the attached event is a custom event that comes from a custom mapped xmlns.

Реализация присоединенных событий в WPFHow WPF Implements Attached Events

В WPFWPFприсоединенные события, обеспечиваются RoutedEvent поле и перенаправляются через дерево, после их возникновения.In WPFWPF, attached events are backed by a RoutedEvent field and are routed through the tree after they are raised. Как правило, источником присоединенного события (объектом, вызывающим событие) является система или служба, и таким образом, объект, который выполняет код, порождающий это событие, не является непосредственной частью дерева элементов.Typically, the source of the attached event (the object that raises the event) is a system or service source, and the object that runs the code that raises the event is therefore not a direct part of the element tree.

Сценарии для присоединенных событийScenarios for Attached Events

В WPFWPFприсоединенные события присутствуют в определенных функциональных областях там, где имеется абстракция уровня службы, такие как для событий, включаемых статическим Mouse класса или Validation класса.In WPFWPF, attached events are present in certain feature areas where there is service-level abstraction, such as for the events enabled by the static Mouse class or the Validation class. Классы, которые взаимодействуют со службой или используют ее, могут использовать событие в синтаксисе присоединенных событий или предоставить присоединенное событие как перенаправленное событие, которое является частью процесса интеграции возможностей службы классом.Classes that interact with or use the service can either use the event in the attached event syntax, or they can choose to surface the attached event as a routed event that is part of how the class integrates the capabilities of the service.

Хотя WPFWPF определяет количество присоединенных событий, ситуации, в которых вы будете использовать или обрабатывать присоединенное событие напрямую, очень ограничены.Although WPFWPF defines a number of attached events, the scenarios where you will either use or handle the attached event directly are very limited. Как правило, присоединенное событие служит в качестве архитектурного элемента, однако затем оно передается в неприсоединенное (поддерживаемое "оболочкой" события CLRCLR) перенаправленное событие.Generally, the attached event serves an architecture purpose, but is then forwarded to a non-attached (backed with a CLRCLR event "wrapper") routed event.

К примеру, присоединенное событие основной Mouse.MouseDown может намного легче обрабатываться на любой заданной UIElement с помощью MouseDown об этом UIElement вместо работы с синтаксисом присоединенных событий, либо в XAMLXAML или кода.For instance, the underlying attached event Mouse.MouseDown can more easily be handled on any given UIElement by using MouseDown on that UIElement rather than dealing with attached event syntax either in XAMLXAML or code. Присоединенное событие выполняет определенную роль в архитектуре, поскольку оно обеспечивает будущее расширение типов устройств ввода.The attached event serves a purpose in the architecture because it allows for future expansion of input devices. Гипотетическому устройству нужно будет только вызвать Mouse.MouseDown в чтобы имитировать ввод от мыши и не может быть производным от Mouse для этого.The hypothetical device would only need to raise Mouse.MouseDown in order to simulate mouse input, and would not need to derive from Mouse to do so. Однако этот сценарий включает обработку кода события, а обработка XAMLXAML присоединенного события не относится к этому сценарию.However, this scenario involves code handling of the events, and XAMLXAML handling of the attached event is not relevant to this scenario.

Обработка присоединенного события в WPFHandling an Attached Event in WPF

Процесс для обработки присоединенного события и код обработчика, который вы будете писать, по сути аналогичны перенаправленному событию.The process for handling an attached event, and the handler code that you will write, is basically the same as for a routed event.

Как правило, присоединенное событие WPFWPF не сильно отличается от перенаправленного события WPFWPF.In general, a WPFWPF attached event is not very different from a WPFWPF routed event. Различие заключается в выборе источника события и его представления классом в качестве члена (что также влияет на синтаксис обработчика XAMLXAML).The differences are how the event is sourced and how it is exposed by a class as a member (which also affects the XAMLXAML handler syntax).

Тем не менее, как было отмечено ранее, существующие присоединенные события WPFWPF не предназначены для обработки в WPFWPF.However, as noted earlier, the existing WPFWPF attached events are not particularly intended for handling in WPFWPF. Гораздо чаще целью событий является включение составного элемента для передачи состояния в родительский элемент при компоновке. В этом случае событие обычно вызывается в коде и зависит от обработки класса в соответствующем родительском классе.More often, the purpose of the event is to enable a composited element to report a state to a parent element in compositing, in which case the event is usually raised in code and also relies on class handling in the relevant parent class. Например, элементы в пределах Selector ожидаются для вызова присоединенного Selected обрабатываются события, который затем класс Selector класса и дальнейшим потенциальным преобразованием классом Selector класс в другое перенаправленное событие, SelectionChanged .For instance, items within a Selector are expected to raise the attached Selected event, which is then class handled by the Selector class and then potentially converted by the Selector class into a different routed event, SelectionChanged. Дополнительные сведения о перенаправленных событиях и обработке классов см. в разделе Маркировка перенаправленных событий как обработанных и обработка классов.For more information on routed events and class handling, see Marking Routed Events as Handled, and Class Handling.

Определение собственных присоединенных событий как перенаправленных событийDefining Your Own Attached Events as Routed Events

При наследовании от общих базовых классов WPFWPF можно реализовать собственные присоединенные события, включив определенные методы шаблонов в собственный класс и используя вспомогательные методы, которые уже присутствуют в базовых классах.If you are deriving from common WPFWPF base classes, you can implement your own attached events by including certain pattern methods in your class and by using utility methods that are already present on the base classes.

Шаблон выглядит следующим образом.The pattern is as follows:

  • Метод добавитьEventNameобработчик с двумя параметрами.A method AddEventNameHandler with two parameters. Первый параметр является экземпляром, к которому добавляется обработчик событий.The first parameter is the instance to which the event handler is added. Вторым параметром является добавляемый обработчик событий.The second parameter is the event handler to add. Этот метод должен быть public и static, не возвращая значения.The method must be public and static, with no return value.

  • Метод удалитьEventNameобработчик с двумя параметрами.A method RemoveEventNameHandler with two parameters. Первый параметр является экземпляр, из которого удаляется обработчик событий.The first parameter is the instance from which the event handler is removed. Второй параметр — удаляемый обработчик событий.The second parameter is the event handler to remove. Этот метод должен быть public и static, не возвращая значения.The method must be public and static, with no return value.

ДобавитьEventNameобработчик метод доступа упрощает XAMLXAML обработку в таких случаях обработчика присоединенного события атрибуты объявляются в элементе.The AddEventNameHandler accessor method facilitates the XAMLXAML processing when attached event handler attributes are declared on an element. ДобавитьEventNameобработчик и удалитьEventNameобработчик методы также обеспечивают доступ кода к хранилищу обработчика событий для вложенное событие.The AddEventNameHandler and RemoveEventNameHandler methods also enable code access to the event handler store for the attached event.

Этот общий шаблон еще недостаточно точен для практической реализации в структуре, поскольку реализация любого заданного модуля чтения XAMLXAML может иметь разные схемы для идентификации базовых событий в поддерживающем языке и архитектуре.This general pattern is not yet precise enough for practical implementation in a framework, because any given XAMLXAML reader implementation might have different schemes for identifying underlying events in the supporting language and architecture. Это одна из причин, WPFWPF реализует присоединенные события как перенаправленные события; идентификатор, используемый для события (RoutedEvent) уже определен WPFWPF системой событий.This is one of the reasons that WPFWPF implements attached events as routed events; the identifier to use for an event (RoutedEvent) is already defined by the WPFWPF event system. Кроме того, перенаправление события является естественным расширением реализации для концепции уровня языка XAMLXAML присоединенного события.Also, routing an event is a natural implementation extension on the XAMLXAML language-level concept of an attached event.

ДобавитьEventNameобработчик внедрению WPFWPF присоединенное событие состоит из вызова метода AddHandler с перенаправленным событием и обработчиком в качестве аргументов.The AddEventNameHandler implementation for a WPFWPF attached event consists of calling the AddHandler with the routed event and handler as arguments.

Эта стратегия реализации и система перенаправленных событий в общем ограничивают обработку присоединенных событий либо UIElement производные классы или ContentElement производные классы, поскольку только эти классы имеют AddHandler реализаций.This implementation strategy and the routed event system in general restrict handling for attached events to either UIElement derived classes or ContentElement derived classes, because only those classes have AddHandler implementations.

Например, следующий код определяет присоединенное событие NeedsCleaning в классе владельцаAquarium, используя стратегию присоединенных событий WPFWPF для объявления присоединенного события как перенаправленного события.For example, the following code defines the NeedsCleaning attached event on the owner class Aquarium, using the WPFWPF attached event strategy of declaring the attached event as a routed event.

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);
    }
}
Public Shared ReadOnly NeedsCleaningEvent As RoutedEvent = EventManager.RegisterRoutedEvent("NeedsCleaning", RoutingStrategy.Bubble, GetType(RoutedEventHandler), GetType(AquariumFilter))
Public Shared Sub AddNeedsCleaningHandler(ByVal d As DependencyObject, ByVal handler As RoutedEventHandler)
    Dim uie As UIElement = TryCast(d, UIElement)
    If uie IsNot Nothing Then
        uie.AddHandler(AquariumFilter.NeedsCleaningEvent, handler)
    End If
End Sub
Public Shared Sub RemoveNeedsCleaningHandler(ByVal d As DependencyObject, ByVal handler As RoutedEventHandler)
    Dim uie As UIElement = TryCast(d, UIElement)
    If uie IsNot Nothing Then
        uie.RemoveHandler(AquariumFilter.NeedsCleaningEvent, handler)
    End If
End Sub

Обратите внимание, что метод, используемый для установления поля идентификатора присоединенного события, RegisterRoutedEvent, является фактически тот же метод, который используется для регистрации неприсоединенных перенаправленных событий.Note that the method used to establish the attached event identifier field, RegisterRoutedEvent, is actually the same method that is used to register a non-attached routed event. Все присоединенные события и перенаправленные события регистрируются в централизованном внутреннем хранилище.Attached events and routed events all are registered to a centralized internal store. Эта реализация хранилища событий обеспечивает поддержку режима "события в качестве интерфейса", который рассматривается в разделе Общие сведения о перенаправленных событиях.This event store implementation enables the "events as an interface" conceptual consideration that is discussed in Routed Events Overview.

Вызов присоединенного события WPFRaising a WPF Attached Event

Как правило, вам не требуется вызывать существующие определенные присоединенные события WPFWPF в коде.You do not typically need to raise existing WPFWPF defined attached events from your code. Эти события выполните общей концептуальной модели «служба» и классы служб, таких как InputManager несут ответственность за вызов событий.These events follow the general "service" conceptual model, and service classes such as InputManager are responsible for raising the events.

Тем не менее при определении пользовательского присоединенного события на основе WPFWPF модель создания вложенных событий на RoutedEvent, можно использовать RaiseEvent для вызова присоединенного события из любого UIElement или ContentElement.However, if you are defining a custom attached event based on the WPFWPF model of basing attached events on RoutedEvent, you can use RaiseEvent to raise an attached event from any UIElement or ContentElement. Вызов перенаправленного события (присоединенного или нет) требует объявления конкретного элемента в дереве элементов в качестве источника события; Этот источник указывается как RaiseEvent вызывающего объекта.Raising a routed event (attached or not) requires that you declare a particular element in the element tree as the event source; that source is reported as the RaiseEvent caller. За определение того, какой элемент передается как источник в дереве, отвечает служба.Determining which element is reported as the source in the tree is your service's responsibility

См. такжеSee also