Custom Routed Events in WPF

By Michael Flanakin @ 8:38 AM :: 13687 Views :: .NET :: Digg it!

WPF/Silverlight (XAML) Routed events are one of the foundational components of the WPF and Silverlight architecture. If you're not familiar with the concepts behind routed events, check out Brian NoyesSyndicated feed MSDN Magazine article, Understanding Routed Events and Commands in WPF. This is a great start to understanding the architecture, but Brian doesn't tackle creating your own routed events. After seemingly endless searches, I finally whipped out Reflector to get to the bottom of it. It's pretty simple, but it is different.

For this scenario, I have a collection of items and I needed to raise an event when the selected item changes. Pretty basic. There are three components to this: (1) the routed event identifier, (2) accessor, and (3) event raising call. Again, not too far off what we're used to, but it is slightly different.

public static readonly RoutedEvent SelectedIndexChangedEvent = EventManager.RegisterRoutedEvent("SelectedIndexChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyControl));

/// <summary>
/// Occurs when the selected index changes.
/// </summary>

public event RoutedEventHandler SelectedIndexChanged
{
    add { AddHandler(SelectedIndexChangedEvent, value); }
    remove { RemoveHandler(SelectedIndexChangedEvent, value); }
}

This is where I got stuck. I tried the traditional method to raise the event:

/// <summary>
/// Raises the <see cref="SelectedIndexChanged"/> event.
/// </summary>
/// <param name="args">The <see cref="RoutedEventArgs"/> instance containing the event data.</param>

protected virtual void OnSelectedIndexChanged(RoutedEventArgs args)
{
    if (SelectedIndexChanged != null)
        SelectedIndexChanged(this, args);
}

Obviously, we wouldn't be here if this would have worked. Luckily, all we need to do is replace the if block: RaiseEvent(args). I should also mention that, when you initialize the event arguments, you need to specify the routed event it's being triggered for. this is as simple as new RoutedEventArgs(SelectedIndexChangedEvent).

There can (and probably should) be some deeper thinking with respect to the best way to make this call, but I'm not going to cover that here. I have some half-baked ideas about this as well as what hooking up a routed event should look like, but I'll save that for another time.

Ratings