Search code examples
wpfrouted-events

WPF Routed Event, subscribing to custom events


I am trying to get routed events working with child controls that will manually fire these events and they will bubble up and be handled at the main grid level. I basically want to do something like this:

<Grid Name="Root" WpfApplication5:SpecialEvent.Tap="Catcher_Tap">
    <Grid.RowDefinitions>
        <RowDefinition Height="40" />
        <RowDefinition Height="40" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <WpfApplication5:UserControl2 Grid.Row="0" x:Name="Catcher" />
    <WpfApplication5:UserControl1 Grid.Row="1" />
    <Frame Grid.Row="2" Source="Page1.xaml" />
</Grid>

But when I run my example, I get a null reference in the presentation framework, the application never initializes, it fails when it's trying to load/initialize the XAML (InitializeComponent()). Here's the small file that contains the event:

public class SpecialEvent
{
    public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
        "Tap", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(UserControl1));

    // Provide CLR accessors for the event
    public event RoutedEventHandler Tap;
}

I am basically wanting to copy the behavior of how ButtonBase.Click allows parents to subscribe to any button click() methods for their children. But, this doesn't seem to be working for anything but ButtonBase.Click(). That is, when I switch out my custom WpfApplication5:SpecialEvent.Tap="Catcher_Tap" to ButtonBase.Click="Catcher_Tap" it works. Any ideas why? What is ButtonBase doing that I'm not doing?


Solution

  • After playing around some more, I found that it's possible to accomplish what I needed in the code behind of the main window like so:

    public MainWindow()
        {
            InitializeComponent();
            Root.AddHandler(SpecialEvent.TapEvent, new RoutedEventHandler(Catcher_Tap));
        }
    

    For some reason, specifying it in the XAML as you would do for ButtonBase() does not work, but adding the Handler in the code behind does.