WPF introduces an augmentation to the standard .NET event-driven programming model. A new type of event, called the routed event, allows for much greater flexibility in event-driven programming scenarios. Subscribing to a routed event can be achieved with the same syntax as a “normal” event (referred to as a CLR event), because it is typical that routed events are exposed via CLR events.
Before discussing routed events any further, it is important to mention the concept of the visual tree. A WPF user interface is constructed in a layered approach, where one visual element can have zero or more child elements. The hierarchy of visible layers in a user interface constitutes what is known as its visual tree.
Routed events are a new infrastructure provided by WPF which allows events to tunnel down the visual tree to the target element, or bubble up to the root element. When an event is raised, it “travels” up or down the visual tree invoking handlers for that event on any element subscribed to that event it encounters en route. Note that this tree traversal does not cover the entire visual tree, only the ancestral element chain between the root element and the element which is the target of the event.
Figure 1 – Routed events in the visual tree (image borrowed from Routed Events Overview article in the SDK.)
It is common that one logical routed event is represented by two actual events, one tunneling and one bubbling. The naming convention for tunneling events is PreviewXYZ, where XYZ is the name of the bubbling event. For example, PreviewMouseLeftButtonDown and MouseLeftButtonDown are a pair of routed events used to notify elements in the visual tree that the user has depressed the left mouse button. Not all routed events have a tunneling event, and some events do not tunnel or bubble at all. Those are referred to as direct events, and they are essentially the same as standard CLR events.
The routed notification pattern has many benefits. One very important benefit of routed events is that a high-level visual element in a UI need not explicitly hook the same event on all of its descendants, such as MouseMove. Instead it can hook the event on itself, and when the mouse moves over one of its descendants, the high level element will be notified appropriately.
Another important advantage of routed events is that elements at all levels of the visual tree can execute code in response to events of their descendants, without expecting the descendant to notify them when the event fires. An ancestor element which hooks a tunneling event can even prevent its descendants from ever receiving both the tunneling and bubbling events at all (although it is possible for an element to demand that it is notified of the event, regardless of it is handled or not).
For more information about routed events, including how to create custom routed events, read Routed Events Overview from the SDK.