Handling already handled events in WPF

By Mirek on (tags: routed events, WPF, categories: code)

This is a simple trick to handle already handled routed events in WPF application.

In WPF the routed events are passed down through the visual tree from the source of the event until they meet the element that can handle them. This behavior, called bubbling, is sometimes not what we expect. Imagine a situation when we have a grid and other child controls in it. We want to know whenever any button is clicked inside the grid for instance or even better when the mouse is down on any of the contained buttons.

   1: <Grid x:Name="grid" >       
   2:   <Button Width="80" Margin="0,0,0,0" Height="21" Content="Button" />
   3:   <Button Width="80" Margin="0,50,0,0" Height="21" Content="Button2" />
   4:   <Button Width="80" Margin="0,100,0,0" Height="21" Content="Button3" />
   5: </Grid>

To achieve it we just need to add a proper handle to our grid so button mouse down routed event is also handled by the grid. This however can be done only in code, because there is no equivalent of this method in xaml.

   1: void MainWindow_Loaded(object sender, RoutedEventArgs e)
   2: {
   3:     grid.AddHandler(Button.MouseDownEvent, new RoutedEventHandler(grid_ButtonMOuseDown), true);
   4: }
   5:  
   6: private void grid_ButtonMOuseDown(object sender, RoutedEventArgs e)
   7: {
   8:     //do stuff here
   9: }

Last boolean parameter is crucial here and says that the handled events have to be considered too.
That’s it. We can now re-handle handled events in the grid.
One thing to note. There is also a possibility to handle the preview events like this

   1: void MainWindow_Loaded(object sender, RoutedEventArgs e)
   2: {
   3:     grid.PreviewMouseDown += grid_PreviewMouseDown;
   4: }
   5:  
   6: void grid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
   7: {
   8:    //do stuff here before the event meets the source of the action
   9: }

but since preview events traverse the virtual tree from the bottom to the top then the grid’s handler will be informed about the event  before it’s handled by the source button. This may not necessarily be always the desired behavior.

Cheers