In a typical application, UI elements will contain other elements as children. A Page contains a Button and a Label; a StackPanel might contain multiple Button elements as well as text-based and Image elements. UI elements and their children are designed with user interaction in mind. When a user interacts with an element, a corresponding event is raised andif declaredan event handler is executed. When a Button is clicked, the Click event is raised; when the selection in a ComboBox changes, the SelectionChanged event is raised; and so on. Chapter 8 notes the events raised by controls along with each element and lists the common events for all controls.
While this material is likely familiar to developers, there is a fundamental difference in how Avalon elements deal with events. In a typical Windows Forms or other Microsoft .NET application, only the element that raised the event responds to the event. If a Button is clicked by a user, the Button element receives the corresponding event indicating that the button has been clicked. In a XAML application, the parent element of the Button may handle the event instead, or any other element in the tree in which the Button is declared.
Consider the following XAML application (Figure 12-1) and its XAML code (Example 12-1).
Figure 12-1. A simple XAML application
Example 12-1. A simple XAML application
The application consists of four elements: Page, Border, StackPanel, and Button. Button is a child of StackPanel, StackPanel is a child of Border, and Border is a child of Page. Just as your grandparent is a kind of "parent," so too are the parent elements of a XAML element's parent. This is illustrated by the formatting of the examples in this book; using indentation to nest elements within their parent helps to visualize their relationship.
Usually, the event handler for the Button element's Click event would be defined with the Button element and handled by the Button. However, Avalon does not require that Button handle its own Click event. In Example 12-1, StackPanel or Border can just as easily handle the Click event by declaring it as through it were an attached attribute:
<StackPanel Margin="10 " Button.Click ="MyButtonHandler " />
Avalon allows parent elements to participate in many events directed at its children through event routing . An event can be routed through multiple elements in a parent/child relationship (the "tree") until it is marked as Handled by one of the elements in the tree.
This might be useful to group together controls that should use the same event handler when any one of them raises a particular event (Example 12-2). For example, a "Yes" and a "No" button might be grouped together in a StackPanel. The same application logic will likely be executed when either button is clicked, but there will probably be some differences to account for.
Example 12-2. Grouping Buttons together to use a common event handler
A single event handler (Example 12-3) can then be defined to handle both cases and to execute common application logic.
Example 12-3. Common event code in C#
Avalon uses three distinct types of routing, which will be discussed further in the next section.