Title: Understand event bubbling and tunneling in WPF and C#
This example demonstrates event bubbling and tunneling in WPF programs. In a Windows Forms application, a control raises an event and that's that. WPF uses more complicated routed events that are routed through a sequence of controls.
First the event tunnels down through the control hierarchy in a sequence of preview events. Then it bubbles back up through the control hierarchy in a sequence of final, possibly converted events.
All of the controls in the tunneling and bubbling chain can handle the event and take action. They can also set their e.Handled parameters to true to stop the event from continuing on its little adventure.
This example contains a main Grid control. At the top, that control contains another Grid that holds a StackPanel holding three Button controls. If you ignore the top-level Grid, which doesn't participate in the events used by this example, the hierarchy looks like this:
When you click on Button 1, PreviewMouseDown events start at the Grid control and tunnel their way down the hierarchy until they reach the button. After that, Click events bubble up from the Button through the hierarchy to the Grid. This picture shows the events.
In the example program you can use the CheckBox controls to make an event handler set its e.Handled parameter to true to interrupt the flow of events. For example, if you check the "Handle in Button.Preview" box, then the last preview event flags its event as handled so none of the Click events occur.
Here's the XAML code that creates the first button.
<Button Name="Button1" Content="Button 1"
PreviewMouseDown="Button1_PreviewMouseDown"
Click="Button1_Click" />
This code creates the button and assigns event handlers to its PreviewMouseDown and Click events. The following code shows those event handlers.
private void Button1_PreviewMouseDown(object sender,
MouseButtonEventArgs e)
{
e.Handled = chkHandleInButtonPreview.IsChecked.Value;
ShowMethodName();
}
private void Button1_Click(object sender, RoutedEventArgs e)
{
e.Handled = chkHandleInButtonClick.IsChecked.Value;
ShowMethodName();
}
The event handlers set e.Handled appropriately depending on whether the corresponding check boxes are checked. They then call the following ShowMethodName method to record the name of the executing event handler.
// Record the name of the method that called this one.
private void ShowMethodName()
{
txtResults.AppendText(
new StackTrace(1).GetFrame(0).GetMethod().Name + '\n');
}
The ShowMethodName adds the calling event handler's name to the text in the txtResults TextBox.
Download the example to experiment with it and to see additional details.
|