Routed events form the event mechanism used for WPF applications. The basic principle behind routed events is that potentially, anyone in the visual tree (and implicitly the logical tree) can be ‘notified’ of this event if they so wish to.
The concept is that when an event occurs, it will travel both up (bubbling) and down (tunnelling) the visual tree.
Since WPF uses element composition to create UX, you can probably already appreciate how crucial this mechanism is. Imagine attaching a ‘click’ event handler to a button which never gets fired since you happen to be clicking on the TextBlock that forms the text on the button, or on its border. Thanks to the bubbling and tunnelling characteristic, you can either choose to handle the event when it reaches the button, or the text, or even both… it’s really up to you.
Routed events are very similar to dependency properties (though instead of the Property suffix, by convention, you’d use an Event suffix… though you don’t have to). You also need to register a RoutedEvent in the static constructor, followed by a standard .NET event wrapper. Same as for dependency properties, DO NOT put any logic in the event wrapper itself.
Creating and raising a RoutedEvent
The AddHandler, RemoveHandler and RaiseEvent methods are all defined in System.Windows.UIElement, i.e. the mother class of almost all WPF components.
A RoutingStrategy (selected when registering the event), defines how the event is propagated down/up the visual tree. This is an enumeration that provides easy access to the 3 methods available, tabulated below:
|Tunnel||The event instance routes downwards through the tree, from root to source element|
|Bubble||The event instance routes upwards through the tree, from event source to root|
|Direct||The routed event does not route through an element tree, but does support other routed event capabilities such as class handling, System.Windows.EventTrigger orSystem.Windows.EventSetter|
Routing Event Handlers
Event handlers for routed events follow the same syntax as traditional .NET events and share the same signature tuple. The first parameter, of type System.Object is a reference to the object to which the handler was attached to, whilst the second parameter is always a type extending System.Windows.RoutedEventArgs (or an instance of RoutedEventArgs), which exposes 4 very useful properties as tabulated below
|Handled||Gets or sets a value that indicates the present state of the event handling for a routed event as it travels the route|
|OriginalSource||The original reporting source, before any possibleSystem.Windows.RoutedEventArgs.Source adjustment made by class handling, which may have been done to flatten composited element trees|
|RoutedEvent||The System.Windows.RoutedEventArgs.RoutedEvent associated with thisSystem.Windows.RoutedEventArgs instance.|
|Source||A reference to the object that raised the event.|
That’s pretty much it. Listening and handling an event follows the normal syntax, and if I find time in the coming days I will write a blog post about a typical scenario of how you would consume a RoutedEvent.