將路由事件標記為已處理以及類別處理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參數版本 (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已在RegisterClassHandler其靜態的函式中呼叫特定的 API, 或已從 element 基類覆寫類別處理常式虛擬方法。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呼叫做為 common language runtime (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 * 事件」和「OnPreview*事件」虛擬方法, 其對應至其公用路由事件的清單。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 OnDragEnter虛擬方法, 為任何UIElement衍生類別中的事件加入類別處理。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

一般來說, 已標示為已處理的路由事件不應標記為Handled未處理 ( false設定回), 即使處理常式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 , 當父元素接聽較低層級的事件KeyDown時 (例如)。For 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.

FrameworkElement UIElement UIElement基類 (ButtonBase)衍生Control自, 而後者又衍生自和, 而控制項輸入處理所需的許多事件基礎結構在層級都有提供。 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. 同樣地ButtonBase , 會使用的MouseLeftButtonUp類別處理常式。Similarly, ButtonBase uses class handlers for MouseLeftButtonUp. 在傳遞事件資料的覆寫中, 此執行會將設定RoutedEventArgs Handledtrue來將該實例標示為已處理, 而相同的事件資料則會沿著其他類別處理常式的其餘路由繼續進行。同時也是實例處理常式或事件 setter。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. 大部分接聽程式的最終結果會是MouseLeftButtonDownMouseLeftButtonUp事件「消失」, Click並改為取代, 因為已知此事件是源自 true 按鈕而非部分, 所以有更多意義的事件按鈕的複合部分, 或從某個其他專案中完全移除。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位於應用程式根項目的處理常式, 您會注意到在按鈕上按下滑鼠時, MouseLeftButtonDown不會叫MouseLeftButtonUp用根層級的或處理常式。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 Click會將類別處理MouseLeftButtonDown標示為已處理, 因為它想要以更多意義來取代事件。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. 透過 Extensible Application Markup Language (XAML)Extensible Application Markup Language (XAML),將事件處理常式名稱指定為事件屬性值的簡單語法不會啟用該行為。The simple syntax of specifying the event handler name as an event attribute value via Extensible Application Markup Language (XAML)Extensible 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