Professional Documents
Culture Documents
Prerequisites
This topic assumes that you have basic knowledge of the common language runtime (CLR) and object-oriented programming, as well as the concept of how the relationships between WPF elements can be conceptualized as a tree. In order to follow the examples in this topic, you should also understand Extensible Application Markup Language (XAML) and know how to write very basic WPF applications or pages. For more information, see Walkthrough: Getting Started with WPF and XAML Overview (WPF).
12/19/13
< B o r d e rH e i g h t = " 5 0 "W i d t h = " 3 0 0 "B o r d e r B r u s h = " G r a y "B o r d e r T h i c k n e s s = " 1 " > < S t a c k P a n e lB a c k g r o u n d = " L i g h t G r a y "O r i e n t a t i o n = " H o r i z o n t a l "B u t t o n . C l i c k = " C o m m o n C l i c k H a n d l e r " > < B u t t o nN a m e = " Y e s B u t t o n "W i d t h = " A u t o "> Y e s < / B u t t o n > < B u t t o nN a m e = " N o B u t t o n "W i d t h = " A u t o "> N o < / B u t t o n > < B u t t o nN a m e = " C a n c e l B u t t o n "W i d t h = " A u t o "> C a n c e l < / B u t t o n > < / S t a c k P a n e l > < / B o r d e r >
In this simplified element tree, the source of a Click event is one of the Button elements, and whichever Button was clicked is the first element that has the opportunity to handle the event. But if no handler attached to the Button acts on the event, then the event will bubble upwards to the Button parent in the element tree, which is the StackPanel. Potentially, the event bubbles to Border, and then beyond to the page root of the element tree (not shown). In other words, the event route for this Click event is: Button-->StackPanel-->Border-->...
12/19/13
e . H a n d l e d = t r u e ; }
Class handling: Routed events permit a static handler that is defined by the class. This class handler has the opportunity to handle an event before any attached instance handlers can. Referencing an event without reflection: Certain code and markup techniques require a way to identify a specific event. A routed event creates a RoutedEvent field as an identifier, which provides a robust event identification technique that does not require static or run-time reflection.
msdn.microsoft.com/en-us/library/ms742806(d=printer,v=vs.110).aspx
3/11
12/19/13
Routing Strategies
Routed events use one of three routing strategies: Bubbling: Event handlers on the event source are invoked. The routed event then routes to successive parent elements until reaching the element tree root. Most routed events use the bubbling routing strategy. Bubbling routed events are generally used to report input or state changes from distinct controls or other UI elements. Direct: Only the source element itself is given the opportunity to invoke handlers in response. This is analogous to the "routing" that Windows Forms uses for events. However, unlike a standard CLR event, direct routed events support class handling (class handling is explained in an upcoming section) and can be used by EventSetter and EventTrigger. Tunneling: Initially, event handlers at the element tree root are invoked. The routed event then travels a route through successive child elements along the route, towards the node element that is the routed event source (the element that raised the routed event). Tunneling routed events are often used or handled as part of the compositing for a control, such that events from composite parts can be deliberately suppressed or replaced by events that are specific to the complete control. Input events provided in WPF often come implemented as a tunneling/bubbling pair. Tunneling events are also sometimes referred to as Preview events, because of a naming convention that is used for the pairs.
msdn.microsoft.com/en-us/library/ms742806(d=printer,v=vs.110).aspx
4/11
12/19/13
. . .
} RoutedEventHandler is the basic routed event handler delegate. For routed events that are specialized for certain controls or scenarios, the delegates to use for the routed event handlers also might become more specialized, so that they can transmit specialized event data. For instance, in a common input scenario, you might handle a DragEnter routed event. Your handler should implement the DragEventHandler delegate. By using the most specific delegate, you can process the DragEventArgs in the handler and read the Data property, which contains the clipboard payload of the drag operation. For a complete example of how to add an event handler to an element using XAML, see How to: Handle a Routed Event. Adding a handler for a routed event in an application that is created in code is straightforward. Routed event handlers can always be added through a helper method AddHandler (which is the same method that the existing backing calls for add.) However, existing WPF routed events generally have backing implementations of add and remove logic that allow the handlers for routed events to be added by a language-specific event syntax, which is more intuitive syntax than the helper method. The following is an example usage of the helper method: C# v o i dM a k e B u t t o n ( ) { B u t t o nb 2=n e wB u t t o n ( ) ; b 2 . A d d H a n d l e r ( B u t t o n . C l i c k E v e n t ,n e wR o u t e d E v e n t H a n d l e r ( O n b 2 C l i c k ) ) ; } v o i dO n b 2 C l i c k ( o b j e c ts e n d e r ,R o u t e d E v e n t A r g se ) { / / l o g i ct oh a n d l et h eC l i c ke v e n t }
msdn.microsoft.com/en-us/library/ms742806(d=printer,v=vs.110).aspx 5/11
12/19/13
The next example shows the C# operator syntax (Visual Basic has slightly different operator syntax because of its handling of dereferencing): C# v o i dM a k e B u t t o n 2 ( ) { B u t t o nb 2=n e wB u t t o n ( ) ; b 2 . C l i c k+ =n e wR o u t e d E v e n t H a n d l e r ( O n b 2 C l i c k 2 ) ; } v o i dO n b 2 C l i c k 2 ( o b j e c ts e n d e r ,R o u t e d E v e n t A r g se ) { / / l o g i ct oh a n d l et h eC l i c ke v e n t } For an example of how to add an event handler in code, see How to: Add an Event Handler Using Code. If you are using Visual Basic, you can also use the Handles keyword to add handlers as part of the handler declarations. For more information, see Visual Basic and WPF Event Handling.
msdn.microsoft.com/en-us/library/ms742806(d=printer,v=vs.110).aspx
6/11
12/19/13
either not to register a handler, or the handlers that were registered chose not to manipulate the event data and set Handled to true. (Or, it is of course possible that the current listener is the first point in the route.) Handlers on the current listener now have three possible courses of action: Take no action at all; the event remains unhandled, and the event routes to the next listener. Execute code in response to the event, but make the determination that the action taken was not substantial enough to warrant marking the event as handled. The event routes to the next listener. Execute code in response to the event. Mark the event as handled in the event data passed to the handler, because the action taken was deemed substantial enough to warrant marking as handled. The event still routes to the next listener, but with Handled=true in its event data, so only handledEventsToo listeners have the opportunity to invoke further handlers. This conceptual design is reinforced by the routing behavior mentioned earlier: it is more difficult (although still possible in code or styles) to attach handlers for routed events that are invoked even if a previous handler along the route has already set Handled to true. For more information about Handled, class handling of routed events, and recommendations about when it is appropriate to mark a routed event as Handled, see Marking Routed Events as Handled, and Class Handling. In applications, it is quite common to just handle a bubbling routed event on the object that raised it, and not be concerned with the event's routing characteristics at all. However, it is still a good practice to mark the routed event as handled in the event data, to prevent unanticipated side effects just in case an element that is further up the element tree also has a handler attached for that same routed event.
Class Handlers
If you are defining a class that derives in some way from DependencyObject, you can also define and attach a class handler for a routed event that is a declared or inherited event member of your class. Class handlers are invoked before any instance listener handlers that are attached to an instance of that class, whenever a routed event reaches an element instance in its route. Some WPF controls have inherent class handling for certain routed events. This might give the outward appearance that the routed event is not ever raised, but in reality it is being class handled, and the routed event can potentially still be handled by your instance handlers if you use certain techniques. Also, many base classes and controls expose virtual methods that can be used to override class handling behavior. For more information both on how to work around undesired class handling and on defining your own class handling in a custom class, see Marking Routed Events as Handled, and Class Handling.
12/19/13
For more information about attached events in WPF, see Attached Events Overview.
Here, the parent element listener where the handler is added is a StackPanel. However, it is adding a handler for a routed event that was declared and will be raised by the Button class (ButtonBase actually, but available to Button through inheritance). Button "owns" the event, but the routed event system permits handlers for any routed event to be attached to any UIElement or ContentElement instance listener that could otherwise attach listeners for a common language runtime (CLR) event. The default xmlns namespace for these qualified event attribute names is typically the default WPF xmlns namespace, but you can also specify prefixed namespaces for custom routed events. For more information about xmlns, see XAML Namespaces and Namespace Mapping for WPF XAML.
12/19/13
As an illustration of how input event processing works, consider the following input event example. In the following tree illustration, l e a fe l e m e n t# 2is the source of both a PreviewMouseDown and then a MouseDown event. Input Event Bubbling and Tunneling
The order of event processing is as follows: 1. PreviewMouseDown (tunnel) on root element. 2. PreviewMouseDown (tunnel) on intermediate element #1. 3. PreviewMouseDown (tunnel) on source element #2. 4. MouseDown (bubble) on source element #2. 5. MouseDown (bubble) on intermediate element #1. 6. MouseDown (bubble) on root element. A routed event handler delegate provides references to two objects: the object that raised the event and the object where the handler was invoked. The object where the handler was invoked is the object reported by the sender parameter. The object where the event was first raised is reported by the Source property in the event data. A routed event can still be raised and handled by the same object, in which case sender and Source are identical (this is the case with Steps 3 and 4 in the event processing example list). Because of tunneling and bubbling, parent elements receive input events where the Source is one of their child elements. When it is important to know what the source element is, you can identify the source element by accessing the Source property. Usually, once the input event is marked Handled, further handlers are not invoked. Typically, you should mark input events as handled as soon as a handler is invoked that addresses your application-specific logical handling of the meaning of the input event. The exception to this general statement about Handled state is that input event handlers that are registered to deliberately ignore Handled state of the event data would still be invoked along either route. For more information, see Preview Events or Marking Routed Events as Handled, and Class Handling. The shared event data model between tunneling and bubbling events, and the sequential raising of first tunneling then bubbling events, is not a concept that is generally true for all routed events. That behavior is specifically implemented by how WPF input devices choose to raise and connect the input event pairs. Implementing your own input events is an advanced scenario, but you might choose to follow that model for your own input events also. Certain classes choose to class-handle certain input events, usually with the intent of redefining what a particular usermsdn.microsoft.com/en-us/library/ms742806(d=printer,v=vs.110).aspx
9/11
12/19/13
Certain classes choose to class-handle certain input events, usually with the intent of redefining what a particular userdriven input event means within that control and raising a new event. For more information, see Marking Routed Events as Handled, and Class Handling. For more information on input and how input and events interact in typical application scenarios, see Input Overview.
12/19/13
See Also
Reference
EventManager RoutedEvent RoutedEventArgs
Concepts
Marking Routed Events as Handled, and Class Handling Input Overview Commanding Overview Custom Dependency Properties Trees in WPF Weak Event Patterns
msdn.microsoft.com/en-us/library/ms742806(d=printer,v=vs.110).aspx
11/11