Archive for May 19th, 2009

WPF Routed Events

Tuesday, May 19th, 2009

Windows Presentation Foundation (WPF) has brought, among other new and interesting things, a concept of routed events. So, what is so special about them?

Earlier, if you wanted to handle some sort of event, you needed to explicitly register for that event. When the event is raised, your handler is invoked. WPF uses a different approach.

All elements in WPF are organized in element trees (logical and visual). When a routed event is raised, it can travel up (so called bubbling) or down (tunneling) the visual and logical tree invoking handlers along the elements tree.

When a bubbling event is raised, the handler at the element source is invoked and the event is forwarded to its successive parents, all the way to the root of the element tree. Because of this, you handle an event on an element further up the element hierarchy from the source element. An example for a bubbling event would be the KeyDown event.

Tunneling events travel down the element tree. Event handlers at the element tree root are raised and the event is then forwarded to successive child elements until it reaches the source element. This allows upstream elements to intercept the event and handle it before the event reaches the source element. By convention they are named with the prefix Preview (e.g. PreviewKeyDown).

Direct event handling is also supported. This means that only explicitly registered event handlers will be invoked when the event is raised. The event does not travel up or down the element tree. This is the same as Windows Forms event-handling mechanism.

Input events are usually a pair of events, both the bubbling event and the tunneling event. For example, the KeyDown event and the PreviewKeyDown event are raised after a single user input action. First, the tunneling event is raised and travels its route. After that, the bubbling event is raised and travels its route. This allows listeners with handlers for the tunneling event to mark the routed event handled and thus stops the input bubbling events handler from invoking.

private void OnPreviewKeyDown(object sender, RoutedEventArgs e)

{

e.Handled = true;

}

But, there is a way to overcome this. What happens in background is that the event is routed anyway, just because of the Handled property set to true, handlers are not invoked. However, you can explicitly hook up event handlers with additional argument which states that handler will be invoked even if the event is marked as handled.

Elem.AddHandler(KeyDownEvent, new RoutedEventHandler(OnKeyDown), true);