Маркировка перенаправленных событий как обработанных и обработка классовMarking Routed Events as Handled, and Class Handling

Обработчики для перенаправленных событий могут помечать событие как обработанное в данных этого события.Handlers for a routed event can mark the event handled within the event data. Обработка событий эффективно сокращает маршрут.Handling the event will effectively shorten the route. Обработка класса — это концепция программирования, поддерживаемая перенаправленными событиями.Class handling is a programming concept that is supported by routed events. Обработчик класса может обрабатывать отдельное перенаправленное событие на уровне класса с помощью обработчика, который вызывается перед любым обработчиком экземпляра в любом экземпляре класса.A class handler has the opportunity to handle a particular routed event at a class level with a handler that is invoked before any instance handler on any instance of the class.

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

В этом разделе описываются основные понятия, представленные в разделе Общие сведения о перенаправленных событиях.This topic elaborates on concepts introduced in the Routed Events Overview.

Когда следует помечать события как обработанныеWhen to Mark Events as Handled

Если для Handled true свойства задано значение в данных события для перенаправленного события, это называется пометкой обработанного события.When you set the value of the Handled property to true in the event data for a routed event, this is referred to as "marking the event handled". Нет абсолютного правила, кто должен помечать перенаправленные события как обработанные — разработчик приложения или разработчик элемента управления, который реагирует на существующие или реализует новые перенаправленные события.There is no absolute rule for when you should mark routed events as handled, either as an application author, or as a control author who responds to existing routed events or implements new routed events. В большинстве случаев понятие «обработанного», переданное в данные события перенаправленного события, должно использоваться как ограниченный протокол для ответов вашего приложения на различные перенаправленные события, предоставляемые в WPFWPF интерфейсах API, а также для любых пользовательских перенаправленных событий.For the most part, the concept of "handled" as carried in the routed event's event data should be used as a limited protocol for your own application's responses to the various routed events exposed in WPFWPF APIs as well as for any custom routed events. С другой стороны, главным образом следует помечать перенаправленное событие как обработанное, если код отвечал на перенаправленное событие значительным и относительно законченным образом.Another way to consider the "handled" issue is that you should generally mark a routed event handled if your code responded to the routed event in a significant and relatively complete way. Как правило, не должно быть более одного значительного ответа, которому требуется реализация отдельных обработчиков для каждого отдельного перенаправленного события.Typically, there should not be more than one significant response that requires separate handler implementations for any single routed event occurrence. Если требуются дополнительные ответы, необходимый код должен быть реализован посредством логики приложения, связанной с простым обработчиком, а не с помощью системы перенаправленных событий для переадресации.If more responses are needed, then the necessary code should be implemented through application logic that is chained within a single handler rather than by using the routed event system for forwarding. Понятие того, что является «значительным», также субъективно и зависит от приложения или кода.The concept of what is "significant" is also subjective, and depends on your application or code. В качестве общих рекомендаций можно привести следующие примеры «значительного ответа»: установка фокуса, изменение общедоступного состояния, установка свойств, влияющих на визуальное представление, и создание других новых событий.As general guidance, some "significant response" examples include: setting focus, modifying public state, setting properties that affect the visual representation, and raising other new events. Примеры незначительных ответов: изменение закрытого состояния (без визуального воздействия или программного представления), ведение журнала событий, просмотр аргументов события и выбор не отвечать на него.Examples of nonsignificant responses include: modifying private state (with no visual impact, or programmatic representation), logging of events, or looking at arguments of an event and choosing not to respond to it.

Поведение системы перенаправленных событий усиливает эту модель "значительный ответ" для использования обработанного состояния перенаправленного события, так как обработчики, XAMLXAML добавленные в или в AddHandler общую сигнатуру, не вызываются в ответ на перенаправленное событие, где событие данные уже помечены как обработанные.The routed event system behavior reinforces this "significant response" model for using handled state of a routed event, because handlers added in XAMLXAML or the common signature of AddHandler are not invoked in response to a routed event where the event data is already marked handled. Необходимо выполнить дополнительные усилия по добавлению обработчика с handledEventsToo параметром version (AddHandler(RoutedEvent, Delegate, Boolean)) для обработки перенаправленных событий, которые помечены как обработанные предыдущими участниками в маршруте события.You must go through the extra effort of adding a handler with the handledEventsToo parameter version (AddHandler(RoutedEvent, Delegate, Boolean)) in order to handle routed events that are marked handled by earlier participants in the event route.

В некоторых случаях элементы управления сами помечают некоторые перенаправленные события как обработанные.In some circumstances, controls themselves mark certain routed events as handled. Обработанное перенаправленное событие представляет решение разработчиков элемента управления WPFWPF, что действия этого элемента управления в ответ на перенаправленное событие являются значительными или завершенными в рамках реализации элемента управления, и событие не требует дальнейшей обработки.A handled routed event represents a decision by WPFWPF control authors that the control's actions in response to the routed event are significant or complete as part of the control implementation, and the event needs no further handling. Обычно это делается путем добавления обработчика класса для события или путем переопределения одного из виртуальных методов обработчика класса, который существует в базовом классе.Usually this is done by adding a class handler for an event, or by overriding one of the class handler virtuals that exist on a base class. При необходимости вы по-прежнему можете обойти обработку этого события; см. раздел Обход подавления событий элементами управления далее в этой статье.You can still work around this event handling if necessary; see Working Around Event Suppression by Controls later in this topic.

События предварительного просмотра по сравнению с событиями восходящей маршрутизации и обработка событий"Preview" (Tunneling) Events vs. Bubbling Events, and Event Handling

Перенаправленные события предварительного просмотра — это события нисходящей маршрутизации через дерево элементов.Preview routed events are events that follow a tunneling route through the element tree. Выражение «Предварительный просмотр» в соглашении об именовании указывает на общий принцип для событий ввода, согласно которому перенаправленные события предварительного просмотра (нисходящей маршрутизации) вызываются до эквивалентных перенаправленных событий восходящей маршрутизации.The "Preview" expressed in the naming convention is indicative of the general principle for input events that preview (tunneling) routed events are raised prior to the equivalent bubbling routed event. Кроме того, перенаправленные события, имеющие пару нисходящей и восходящей маршрутизации, имеют другую логику обработки.Also, input routed events that have a tunneling and bubbling pair have a distinct handling logic. Если перенаправленное событие нисходящей маршрутизации (событие предварительного просмотра) помечается прослушивателем событий как обработанное, то перенаправленное событие восходящей маршрутизации будет помечено как обработанное даже до того, как это событие будет получено каким-либо прослушивателем событий восходящей маршрутизации.If the tunneling/preview routed event is marked as handled by an event listener, then the bubbling routed event will be marked handled even before any listeners of the bubbling routed event receive it. Перенаправленные события нисходящей и восходящей маршрутизации технически являются отдельными событиями, но они специально совместно используют один и тот же экземпляр данных события, чтобы такое поведение стало возможным.The tunneling and bubbling routed events are technically separate events, but they deliberately share the same instance of event data to enable this behavior.

Связь между перенаправленными событиями нисходящей и восходящей маршрутизации обеспечивается внутренней реализацией того, как любой конкретный класс WPFWPF вызывает свои собственные объявленные перенаправленные события, и это справедливо для пары перенаправленных событий ввода.The connection between the tunneling and bubbling routed events is accomplished by the internal implementation of how any given WPFWPF class raises its own declared routed events, and this is true of the paired input routed events. Но если данная реализация на уровне класса отсутствует, то между перенаправленными событиями нисходящей и восходящей маршрутизации, совместно использующими эту схему именования, нет связи: без такой реализации это будут два абсолютно раздельных перенаправленных события, которые не будут вызываться в последовательности и не будут совместно использовать данные события.But unless this class-level implementation exists, there is no connection between a tunneling routed event and a bubbling routed event that share the naming scheme: without such implementation they would be two entirely separate routed events and would not be raised in sequence or share event data.

Дополнительные сведения о реализации пары перенаправленных событий нисходящей и восходящей маршрутизации в пользовательском классе см. в разделе Создание пользовательских перенаправленных событий.For more information about how to implement tunnel/bubble input routed event pairs in a custom class, see Create a Custom Routed Event.

Обработчики классов и обработчики экземпляровClass Handlers and Instance Handlers

Перенаправленные события поддерживают два разных типа прослушивателей события: прослушиватели классов и прослушиватели экземпляров.Routed events consider two different types of listeners to the event: class listeners and instance listeners. Прослушиватели классов существуют, так как типы вызвали EventManager определенныйRegisterClassHandlerAPI,, в статическом конструкторе или переопределили виртуальный метод обработчика класса из базового класса элемента.Class listeners exist because types have called a particular EventManager API ,RegisterClassHandler, in their static constructor, or have overridden a class handler virtual method from an element base class. Прослушиватели экземпляров — это конкретные экземпляры или элементы класса, в которых один или несколько обработчиков были присоединены к перенаправленному AddHandlerсобытию посредством вызова.Instance listeners are particular class instances/elements where one or more handlers have been attached for that routed event by a call to AddHandler. Существующие WPFWPF перенаправленные события выполняют вызовы AddHandler в рамках оболочки событий среды CLR для добавления{} и удаления{} реализаций события, что также является простым XAMLXAML механизмом разрешено присоединение обработчиков событий с помощью синтаксиса атрибутов.Existing WPFWPF routed events make calls to AddHandler as part of the common language runtime (CLR) event wrapper add{} and remove{} implementations of the event, which is also how the simple XAMLXAML mechanism of attaching event handlers via an attribute syntax is enabled. Поэтому даже простое XAMLXAML использование в конечном итоге равнозначно AddHandler вызову.Therefore even the simple XAMLXAML usage ultimately equates to an AddHandler call.

Элементы в пределах визуального дерева проверяются на наличие реализаций зарегистрированных обработчиков.Elements within the visual tree are checked for registered handler implementations. Обработчики потенциально вызываются на всем маршруте в порядке, соответствующем типу стратегии маршрутизации для этого перенаправленного события.Handlers are potentially invoked throughout the route, in the order that is inherent in the type of the routing strategy for that routed event. Например, перенаправленные события восходящей маршрутизации сначала будут вызывать обработчики, присоединенные к элементу, который вызвал это перенаправленное событие.For instance, bubbling routed events will first invoke those handlers that are attached to the same element that raised the routed event. Затем перенаправленное событие «поднимается» к следующему родительскому элементу и так далее, пока не будет достигнут корневой элемент приложения.Then the routed event "bubbles" to the next parent element and so on until the application root element is reached.

С точки зрения корневого элемента в восходящем маршруте, если обработка класса или любой элемент, ближайший к источнику перенаправленного события, вызывает обработчики, которые помечают аргументы события как обработанные, то обработчики в корневых элементах не вызываются и маршрут события эффективно укорачивается до достижения этого корневого элемента.From the perspective of the root element in a bubbling route, if class handling or any element closer to the source of the routed event invoke handlers that mark the event arguments as being handled, then handlers on the root elements are not invoked, and the event route is effectively shortened before reaching that root element. Однако маршрут не полностью останавливается, так как обработчики могут быть добавлены с использованием специального условия, что они должны по-прежнему вызываться, даже если обработчик класса или обработчик экземпляра пометил перенаправленное событие как обработанное.However, the route is not completely halted, because handlers can be added using a special conditional that they should still be invoked, even if a class handler or instance handler has marked the routed event as handled. Это объясняется в разделе Добавление обработчиков экземпляра, которые вызываются, даже когда события помечены как обработанные далее в этой статье.This is explained in Adding Instance Handlers That Are Raised Even When Events Are Marked Handled, later in this topic.

На более глубоком уровне, чем маршрут события, также потенциально имеется несколько обработчиков класса, действующих в любом экземпляре класса.At a deeper level than the event route, there are also potentially multiple class handlers acting on any given instance of a class. Это связано с тем, что модель обработки класса для перенаправленных событий позволяет каждому из возможных классов в иерархии классов зарегистрировать свой собственный обработчик класса для каждого перенаправленного события.This is because the class handling model for routed events enables all possible classes in a class hierarchy to each register its own class handler for each routed event. Каждый обработчик класса добавляется во внутреннее хранилище, и, когда формируется маршрут события для приложения, все обработчики классов добавляются в этот маршрут события.Each class handler is added to an internal store, and when the event route for an application is constructed, the class handlers are all added to the event route. Обработчики классов добавляются в маршрут таким образом, что сначала вызывается обработчик класса, находящегося на самом низком уровне иерархии, а затем вызываются обработчики классов из каждого последующего базового класса.Class handlers are added to the route such that the most-derived class handler is invoked first, and class handlers from each successive base class are invoked next. Как правило, обработчики классов не регистрируются, так что они также отвечают на перенаправленные события, которые уже были помечены как обработанные.Generally, class handlers are not registered such that they also respond to routed events that were already marked handled. Таким образом, этот механизм обработки класса позволяет выбрать один из двух следующих вариантов.Therefore, this class handling mechanism enables one of two choices:

  • Производные классы могут дополнять обработку класса, наследуемую от базового класса, путем добавления обработчика, который не помечает перенаправленное событие как обработанное, поскольку обработчик базового класса будет иногда вызываться после обработчика производного класса.Derived classes can supplement the class handling that is inherited from the base class by adding a handler that does not mark the routed event handled, because the base class handler will be invoked sometime after the derived class handler.

  • Производные классы могут заменять обработку класса из базового класса путем добавления обработчика класса, который помечает перенаправленное событие как обработанное.Derived classes can replace the class handling from the base class by adding a class handler that marks the routed event handled. Следует соблюдать осторожность при таком подходе, потому что в результате возможно изменение планируемой конструкции базового элемента управления в таких областях, как внешний вид, логика состояний, обработки ввода и обработка команд.You should be cautious with this approach, because it will potentially change the intended base control design in areas such as visual appearance, state logic, input handling, and command handling.

Обработка перенаправленных событий базовыми классами элементов управленияClass Handling of Routed Events by Control Base Classes

В каждом узле элементов в маршруте события прослушиватели классов имеют возможность ответить на перенаправленное событие прежде, чем это сможет сделать любой прослушиватель экземпляра в элементе.On each given element node in an event route, class listeners have the opportunity to respond to the routed event before any instance listener on the element can. По этой причине обработчики классов иногда используются для подавления перенаправленных событий, которые определенная реализация класса элементов управления не желает распространять дальше, или для предоставления специальной обработки этого перенаправленного события, являющейся функцией класса.For this reason, class handlers are sometimes used to suppress routed events that a particular control class implementation does not wish to propagate further, or to provide special handling of that routed event that is a feature of the class. Например, класс может вызывать собственное событие класса, содержащее дополнительные сведения о том, что означает некоторое пользовательское условие ввода в контексте данного класса.For instance, a class might raise its own class-specific event that contains more specifics about what some user input condition means in the context of that particular class. Затем эта реализация класса может пометить более общее перенаправленное событие как обработанное.The class implementation might then mark the more general routed event as handled. Обработчики классов обычно добавляются таким, что они не вызываются для перенаправленных событий, когда общие данные событий уже помечены как обработанные, но в нетипичных случаях также RegisterClassHandler(Type, RoutedEvent, Delegate, Boolean) существует сигнатура, которая регистрирует обработчики класса для вызова, даже если перенаправленные события помечено как обработанное.Class handlers are typically added such that they are not invoked for routed events where shared event data was already marked handled, but for atypical cases there is also a RegisterClassHandler(Type, RoutedEvent, Delegate, Boolean) signature that registers class handlers to invoke even when routed events are marked handled.

Виртуальные функции обработчиков классовClass Handler Virtuals

Некоторые элементы, в частности базовые элементы, такие UIElementкак, предоставляют пустые виртуальные методы "On * Event" и*"OnPreview Event", соответствующие их списку общих перенаправленных событий.Some elements, particularly the base elements such as UIElement, expose empty "On*Event" and "OnPreview*Event" virtual methods that correspond to their list of public routed events. Эти виртуальные методы можно переопределить, чтобы реализовать обработчик класса для перенаправленного события.These virtual methods can be overridden to implement a class handler for that routed event. Классы базовых элементов регистрируют эти виртуальные методы в качестве обработчика класса для каждого такого перенаправленного события RegisterClassHandler(Type, RoutedEvent, Delegate, Boolean) , используя, как описано выше.The base element classes register these virtual methods as their class handler for each such routed event using RegisterClassHandler(Type, RoutedEvent, Delegate, Boolean) as described earlier. Виртуальные методы On*Event существенно упрощают реализацию обработки класса для соответствующих перенаправленных события, не требуя специальной инициализации в статических конструкторах для каждого типа.The On*Event virtual methods make it much simpler to implement class handling for the relevant routed events, without requiring special initialization in static constructors for each type. Например, можно добавить обработку класса для DragEnter события в любом UIElement производном OnDragEnter классе, переопределив виртуальный метод.For instance, you can add class handling for the DragEnter event in any UIElement derived class by overriding the OnDragEnter virtual method. В переопределении можно обрабатывать перенаправленное событие, вызывать другие события, инициировать логику данного класса, которая может изменять свойства элементов в экземплярах или задавать любое сочетание этих действий.Within the override, you could handle the routed event, raise other events, initiate class-specific logic that might change element properties on instances, or any combination of those actions. Обычно в таких переопределениях следует вызывать базовую реализацию, даже если событие помечается как обработанное.You should generally call the base implementation in such overrides even if you mark the event handled. Вызов базовой реализации настоятельно рекомендуется, так как виртуальный метод находится в базовом классе.Calling the base implementation is strongly recommended because the virtual method is on the base class. Стандартный защищенный виртуальный шаблон вызова базовых реализаций из каждого виртуального метода в сущности заменяет и дублирует аналогичный механизм, встроенный в обработку класса перенаправленных событий, в котором обработчики классов для всех классов в иерархии вызываются в любом указанном экземпляре, начиная с обработчика класса, самого дальнего в иерархии, и заканчивая обработчиком базового класса.The standard protected virtual pattern of calling the base implementations from each virtual essentially replaces and parallels a similar mechanism that is native to routed event class handling, whereby class handlers for all classes in a class hierarchy are called on any given instance, starting with the most-derived class' handler and continuing to the base class handler. Вам достаточно лишь опустить вызов базовой реализации, если класс обоснованно требует изменить логику обработки базового класса.You should only omit the base implementation call if your class has a deliberate requirement to change the base class handling logic. Вызов базовой реализации до или после переопределения кода будет зависеть от природы реализации.Whether you call the base implementation before or after your overriding code will depend on the nature of your implementation.

Обработка классов событий вводаInput Event Class Handling

Все виртуальные методы обработчика класса регистрируются таким образом, что они вызываются только в случаях, когда общие данные события еще не помечены как обработанные.The class handler virtual methods are all registered such that they are only invoked in cases where any shared event data are not already marked handled. Кроме того, исключительно для событий ввода, нисходящая и восходящая версии маршрутизации обычно вызываются последовательно и совместно используют данные события.Also, for the input events uniquely, the tunneling and bubbling versions typically are raised in sequence and share event data. Это влечет за собой то, что для конкретной пары обработчиков класса событий ввода, где один является версией для нисходящей маршрутизации, а другой — для восходящей, вы можете не захотеть немедленно пометить событие как обработанное.This entails that for a given pair of class handlers of input events where one is the tunneling version and the other is the bubbling version, you may not want to mark the event handled immediately. Если вы реализуете виртуальный метод обработки класса событий нисходящей маршрутизации для пометки события как обработанного, это препятствует вызову обработчика класса событий восходящей маршрутизации (а также препятствует вызову любых обычно зарегистрированных обработчиков экземпляров для событий как нисходящей, так и восходящей маршрутизации).If you implement the tunneling class handling virtual method to mark the event handled, that will prevent the bubbling class handler from being invoked (as well as preventing any normally registered instance handlers for either the tunneling or bubbling event from being invoked).

После завершения обработки класса в узле рассматриваются прослушиватели экземпляров.Once class handling on a node is complete, the instance listeners are considered.

Добавление обработчиков экземпляра, которые вызываются, даже когда события помечены как обработанныеAdding Instance Handlers That Are Raised Even When Events Are Marked Handled

AddHandler Метод предоставляет определенную перегрузку, которая позволяет добавлять обработчики, которые будут вызываться системой событий каждый раз, когда событие достигнет обрабатывающего элемента в маршруте, даже если какие-либо другие обработчики уже настроили данные события для пометки событие как обработанное.The AddHandler method supplies a particular overload that allows you to add handlers that will be invoked by the event system whenever an event reaches the handling element in the route, even if some other handler has already adjusted the event data to mark that event as handled. Обычно это не делается.This is not typically done. Как правило, обработчики могут быть написаны для корректировки всех областей кода приложения, на которые может влиять событие, независимо от того, где оно было обработано в дереве элементов, даже если требуется несколько конечных результатов.Generally, handlers can be written to adjust all areas of application code that might be influenced by an event, regardless of where it was handled in an element tree, even if multiple end results are desired. Кроме того, обычно существует только один элемент, который должен отвечать на это событие, и соответствующая прикладная логика уже была применена.Also, typically there is really only one element that needs to respond to that event, and the appropriate application logic had already happened. Однако перегрузка handledEventsToo доступна в исключительных случаях, когда некоторые элементы в дереве элементов или в составных элементах управления уже пометили событие как обработанное, но другие элементы, находящиеся выше или ниже в дереве элементов (в зависимости от маршрута), по-прежнему требуют вызов своих собственных обработчиков.But the handledEventsToo overload is available for the exceptional cases where some other element in an element tree or control compositing has already marked an event as handled, but other elements either higher or lower in the element tree (depending on route) still wish to have their own handlers invoked.

Когда следует помечать обработанные события как необработанныеWhen to Mark Handled Events as Unhandled

Как правило, перенаправленные события, помеченные как обработанные, не должны помечаться как falseнеобработанные (Handled устанавливаются обратно handledEventsToo) даже обработчиками, которые действуют.Generally, routed events that are marked handled should not be marked unhandled (Handled set back to false) even by handlers that act on handledEventsToo. Однако некоторые события ввода имеют представления событий высокого и низкого уровня, которые могут перекрываться, когда событие высокого уровня отображается в одной позиции в дереве, а событие низкого уровня — в другой позиции.However, some input events have high-level and lower-level event representations that can overlap when the high-level event is seen at one position in the tree and the low-level event at another position. Например, рассмотрим случай, когда дочерний элемент прослушивает событие ключа высокого уровня, например TextInput , в то время как родительский элемент ожидает события низкого уровня, такого как. KeyDownFor instance, consider the case where a child element listens to a high-level key event such as TextInput while a parent element listens to a low-level event such as KeyDown. Если родительский элемент обрабатывает событие нижнего уровня, событие верхнего уровня может подавляться даже в дочернем элементе, который интуитивно должен иметь возможность первым обработать это событие.If the parent element handles the low-level event, the higher-level event can be suppressed even in the child element that intuitively should have first opportunity to handle the event.

В таких ситуациях может потребоваться добавить обработчики события нижнего уровня и в родительский, и в дочерний элемент.In these situations it may be necessary to add handlers to both parent elements and child elements for the low-level event. Реализация обработчика дочернего элемента может пометить событие нижнего уровня как обработанное, но реализация обработчика родительского элемента будет снова устанавливать его как необработанное, чтобы последующие элементы в дереве (а также события высокого уровня) имели возможность ответить.The child element handler implementation can mark the low-level event as handled, but the parent element handler implementation would set it unhandled again so that further elements up the tree (as well as the high-level event) can have the opportunity to respond. Это достаточно редкая ситуация.This situation is should be fairly rare.

Намеренное подавление событий ввода для составных элементов управленияDeliberately Suppressing Input Events for Control Compositing

Основной сценарий, в котором используется обработка класса перенаправленных событий, предназначен для событий ввода и составных элементов управления.The main scenario where class handling of routed events is used is for input events and composited controls. Составной элемент управления по определению состоит из нескольких фактических элементов управления или базовых классов элементов управления.A composited control is by definition composed of multiple practical controls or control base classes. Часто разработчик элемента управления хочет объединить все возможные события ввода, которые могут вызываться каждым из компонентов, чтобы полный элемент управления был единственным источником событий.Often the author of the control wishes to amalgamate all of the possible input events that each of the subcomponents might raise, in order to report the entire control as the singular event source. В некоторых случаях разработчик элемента управления может захотеть полностью подавить события от компонентов или заменить на определяемое компонентом событие, которое содержит дополнительные сведения или подразумевает более конкретное поведение.In some cases the control author might wish to suppress the events from components entirely, or substitute a component-defined event that carries more information or implies a more specific behavior. Канонический пример, непосредственно видимый для любого автора компонента, заключается в Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) Button том, как обработчик обрабатывает любое событие мыши, которое в конечном итоге будет разрешать интуитивно понятному событию, что Click все кнопки имеют: событие.The canonical example that is immediately visible to any component author is how a Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) Button handles any mouse event that will eventually resolve to the intuitive event that all buttons have: a Click event.

ButtonBase Control UIElement UIElement FrameworkElement Базовый класс () является производным от, который, в свою очередь, является производным от и, и большая часть инфраструктуры событий, необходимая для обработки входных данных управления, доступна на уровне. ButtonThe Button base class (ButtonBase) derives from Control which in turn derives from FrameworkElement and UIElement, and much of the event infrastructure needed for control input processing is available at the UIElement level. В частности, UIElement обрабатывает общие Mouse события, которые обрабатывают проверку попадания курсора мыши в пределах границ, и предоставляет отдельные события для наиболее распространенных действий кнопок, таких как MouseLeftButtonDown.In particular, UIElement processes general Mouse events that handle hit testing for the mouse cursor within its bounds, and provides distinct events for the most common button actions, such as MouseLeftButtonDown. UIElementтакже предоставляет пустой виртуальный OnMouseLeftButtonDown в качестве предварительно зарегистрированного обработчика класса для MouseLeftButtonDownи ButtonBase переопределяет его.UIElement also provides an empty virtual OnMouseLeftButtonDown as the preregistered class handler for MouseLeftButtonDown, and ButtonBase overrides it. Аналогичным образом MouseLeftButtonUp используетобработчикиButtonBase классов для.Similarly, ButtonBase uses class handlers for MouseLeftButtonUp. В переопределениях, которые передают данные события, реализации отмечают этот RoutedEventArgs экземпляр как обработанный, trueприсвоив параметру Handled значение, и эти данные события будут продолжаться в оставшейся части маршрута к другим обработчикам класса и также к обработчикам экземпляров или методам задания событий.In the overrides, which are passed the event data, the implementations mark that RoutedEventArgs instance as handled by setting Handled to true, and that same event data is what continues along the remainder of the route to other class handlers and also to instance handlers or event setters. Кроме того, OnMouseLeftButtonUp переопределение приводит к Click последующему вызову события.Also, the OnMouseLeftButtonUp override will next raise the Click event. Конечным результатом для большинства прослушивателей является то, MouseLeftButtonDown что MouseLeftButtonUp события и исчезают, а вместо них Clickзаменяются на событие, которое содержит больше смысла, поскольку известно, что это событие поступило от кнопки «истина», а не для некоторых составной элемент кнопки или из другого элемента полностью.The end result for most listeners will be that the MouseLeftButtonDown and MouseLeftButtonUp events "disappear" and are replaced instead by Click, an event that holds more meaning because it is known that this event originated from a true button and not some composite piece of the button or from some other element entirely.

Обход скрытия события элементами управленияWorking Around Event Suppression by Controls

Иногда это поведение скрытия события внутри отдельных элементов управления может конфликтовать с некоторыми более общими целями логики обработки событий в приложении.Sometimes this event suppression behavior within individual controls can interfere with some more general intentions of event handling logic for your application. Например, если по какой-то причине в приложении имелся обработчик MouseLeftButtonDown для размещается в корневом элементе приложения, можно заметить, что любой щелчок кнопки мыши не MouseLeftButtonUp вызовет MouseLeftButtonDown обработчиков на корневом уровне.For instance, if for some reason your application had a handler for MouseLeftButtonDown located at the application root element, you would notice that any mouse click on a button would not invoke MouseLeftButtonDown or MouseLeftButtonUp handlers at the root level. Само событие действительно передается вверх (еще раз, маршруты событий на самом деле не завершены, но система перенаправления событий изменяет поведение вызова их обработчика после пометки их как обработанных).The event itself actually did bubble up (again, event routes are not truly ended, but the routed event system changes their handler invocation behavior after being marked handled). Когда перенаправленное событие достигает кнопки, обработка ButtonBase класса MouseLeftButtonDown помечается как обработанная, так как Click она замещает событие более значимым значением.When the routed event reached the button, the ButtonBase class handling marked the MouseLeftButtonDown handled because it wished to substitute the Click event with more meaning. Таким образом, любой MouseLeftButtonDown стандартный обработчик, расположенный дальше по маршруту, не будет вызываться.Therefore, any standard MouseLeftButtonDown handler further up the route would not be invoked. Существует два способа гарантировать, что в таких обстоятельствах ваши обработчики будут вызываться.There are two techniques you can use to ensure that your handlers would be invoked in this circumstance.

Первый способ — намеренно добавить обработчик, используя handledEventsToo AddHandler(RoutedEvent, Delegate, Boolean)сигнатуру.The first technique is to deliberately add the handler using the handledEventsToo signature of AddHandler(RoutedEvent, Delegate, Boolean). Этот подход ограничен тем, что такой способ присоединения обработчика событий возможен только из кода, но не из разметки.A limitation of this approach is that this technique for attaching an event handler is only possible from code, not from markup. Простой синтаксис указания имени обработчика событий в качестве значения атрибута события посредством Язык XAMLExtensible Application Markup Language (XAML) не позволяет такое поведение.The simple syntax of specifying the event handler name as an event attribute value via Язык XAMLExtensible Application Markup Language (XAML) does not enable that behavior.

Второй способ работает только для событий ввода, где версии нисходящей и восходящей маршрутизации перенаправленного события объединены в пару.The second technique works only for input events, where the tunneling and bubbling versions of the routed event are paired. Для этих перенаправленных событий можно добавлять обработчики в версию перенаправленного события нисходящей маршрутизации.For these routed events, you can add handlers to the preview/tunneling equivalent routed event instead. Это перенаправленное событие будет спускаться по маршруту, начиная от корня, поэтому код обработки класса кнопки не будет его перехватывать, при условии что вы присоединили обработчик предварительного просмотра на уровне предшествующего элемента в дереве элементов приложения.That routed event will tunnel through the route starting from the root, so the button class handling code would not intercept it, presuming that you attached the Preview handler at some ancestor element level in the application's element tree. При использовании этого подхода будьте внимательны при пометке любого события предварительного просмотра как обработанного.If you use this approach, be cautious about marking any Preview event handled. В примере PreviewMouseLeftButtonDown , который обрабатывается в корневом элементе, если событие помечено как Handled в реализации обработчика, это Click событие будет подавлено.For the example given with PreviewMouseLeftButtonDown being handled at the root element, if you marked the event as Handled in the handler implementation, you would actually suppress the Click event. Обычно это нежелательное поведение.That is typically not desirable behavior.

См. такжеSee also