Routed Events in WPF
When you are first getting started with WPF, you will likely use routed events without even knowing you are using them. For example, if you add a button to your window in the Visual Studio® designer and name it myButton and then double-click on it, the Click event will get hooked up in your XAML markup and an event handler for the Click event will be added to the codebehind of your Window class. This should feel no different than hooking up events in Windows Forms and ASP.NET. It is actually a little closer to the coding model for ASP.NET but more like the runtime model of Windows Forms.
Routed events normally appear as pair. The first is a tunneling event called PreviewMouseDown and the second is the bubbling called MouseDown. They don’t stop routing if the reach an event handler. To stop routing then you have to set e.Handled = true;
- Tunneling The event is raised on the root element and navigates down to the visual tree until it reaches the source element or until the tunneling is stopped by marking the event as handeld. By naming convention it is called
Preview...and appears before corresponding bubbling event. - Bubbling The event is raised on the source element and navigates up to the visual tree until it reaches the root element or until the bubbling is stopped by marking the event as handled. The bubbling event is raised after the tunneling event.
- Direct The event is raised on the source element and must be handled on the source element itself. This behavior is the same as normal .NET events.
You can think about routed events either from a functional or implementation perspective. Both definitions are presented here, because some people find one or the other definition more useful.
Functional definition: A routed event is a type of event that can invoke handlers on multiple listeners in an element tree, rather than just on the object that raised the event.
Implementation definition: A routed event is a CLR event that is backed by an instance of the RoutedEvent class and is processed by the Windows Presentation Foundation (WPF) event system.
A typical WPF application contains many elements. Whether created in code or declared in XAML, these elements exist in an element tree relationship to each other. The event route can travel in one of two directions depending on the event definition, but generally the route travels from the source element and then "bubbles" upward through the element tree until it reaches the element tree root (typically a page or a window). This bubbling concept might be familiar to you if you have worked with the DHTML object model previously.
A code snippet
1: <StackPanel Orientation="Horizontal" Button.Click="ButtonCLickHandler">
2: <Button Name="btnYes" Width="Auto" >Yes</Button>
3: <Button Name="btnNo" Width="Auto" >No</Button>
4: <Button Name="btnCancel" Width="Auto" >Cancel</Button>
5: </StackPanel>
As an application developer, you do not always need to know or care that the event you are handling is implemented as a routed event. Routed events have special behavior, but that behavior is largely invisible if you are handling an event on the element where it is raised.
Where routed events become powerful is if you use any of the suggested scenarios: defining common handlers at a common root, compositing your own control, or defining your own custom control class.
Routed event listeners and routed event sources do not need to share a common event in their hierarchy. Any UIElement or ContentElement can be an event listener for any routed event. Therefore, you can use the full set of routed events available throughout the working API set as a conceptual "interface" whereby disparate elements in the application can exchange event information. This "interface" concept for routed events is particularly applicable for input events.
Routed events can also be used to communicate through the element tree, because the event data for the event is perpetuated to each element in the route. One element could change something in the event data, and that change would be available to the next element in the route.
Other than the routing aspect, there are two other reasons that any given WPF event might be implemented as a routed event instead of a standard CLR event. If you are implementing your own events, you might also consider these principles:
Certain WPF styling and templating features such as EventSetter and EventTrigger require the referenced event to be a routed event. This is the event identifier scenario mentioned earlier.
Routed events support a class handling mechanism whereby the class can specify static methods that have the opportunity to handle routed events before any registered instance handlers can access them. This is very useful in control design, because your class can enforce event-driven class behaviors that cannot be accidentally suppressed by handling an event on an instance.
Each of the above considerations is discussed in a separate section of this topic.
