Routed Events
Most events in Avalonia are implemented as Routed Events. Routed events are events that are raised on the whole tree rather than just the control that raised the event.
What Is a Routed Event
A typical Avalonia 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 HTML DOM previously.
Top-level Scenarios for Routed Events
The following is a brief summary of the scenarios that motivated the routed event concept, and why a typical CLR event was not adequate for these scenarios:
Control composition and encapsulation: Various controls in Avalonia have a rich content model. For example, you can place an image inside of a Button
, which effectively extends the visual tree of the button. However, the added image must not break the hit-testing behavior that causes a button to respond to a Click
of its content, even if the user clicks on pixels that are technically part of the image.
Singular handler attachment points: In Windows Forms, you would have to attach the same handler multiple times to process events that could be raised from multiple elements. Routed events enable you to attach that handler only once, as was shown in the previous example, and use handler logic to determine where the event came from if necessary. For instance, this might be the handler for the previously shown XAML:
private void CommonClickHandler(object sender, RoutedEventArgs e)
{
var source = e.Source as Control;
switch (source.Name)
{
case "YesButton":
// do something here ...
break;
case "NoButton":
// do something ...
break;
case "CancelButton":
// do something ...
break;
}
e.Handled=true;
}
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.