#503 – Be Careful When Casting RoutedEventArgs.Source

In an event handler, you’ll often cast the RoutedEventsArgs.Source property to a particular type.  When you have an event handler attached to a panel that can contain controls of various types, this can lead to problems.

In the example below, we’re assuming that the originator of the Click event is a Button.

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Button b = e.Source as Button;
            MessageBox.Show(string.Format("You clicked on {0} button, sender is of type {1}",
                b.Content, sender.GetType().ToString()));
        }

If we have a panel that contains some Buttons, but also a ToggleButton control–which has a Click event but is not a Button–we get a crash when clicking on the ToggleButton.

A better solution is to check the type of the originator.

            if (e.Source is Button)
            {
                Button b = e.Source as Button;
                MessageBox.Show(string.Format("You clicked on {0} button, sender is of type {1}",
                    b.Content, sender.GetType().ToString()));
            }

About Sean
Software developer in the Twin Cities area, passionate about software development and sailing.

7 Responses to #503 – Be Careful When Casting RoutedEventArgs.Source

  1. Przemo says:

    Even better:

    Button b = e.Source as Button;
    if (b != null)
    {
    MessageBox.Show(string.Format(“You clicked on {0} button, sender is of type {1}”,
    b.Content, sender.GetType().ToString()));
    }

    • Sean says:

      Yes, agreed–that’s another way of doing it. I tend to prefer to be more explicit in checking the type of the object, for readability. But what you show is a very common pattern as well.

      • Another way you could explicitly check is to use the ‘is’ keyword

        instead of

        if (e.Source.GetType() == typeof(Button)) { … }

        you could say

        if (e.Source is Button) { … }

        which reads nicer and is more succinct, but personally I would probably just do what Przemo suggested as well

      • Sean says:

        Yes, thanks Jon–is operator much more clean then invoking GetType().

  2. Both Button and ToggleButton derive from ButtonBase, so I suggest to cast to that. But I see your point 😉

    • Sean says:

      You’re right–in this example, we’re accessing the Content property, which is present in the ButtonBase class that serves as the base class for Button and ToggleButton–and is also where the Click event is defined. You only really need to be careful when you’re going to access properties or methods that are not present on all child controls that handle the routed event. In this example, I was assuming that the intent was to just report on the Button clicks and not the toggle. But in the end, it’s worth following a pattern of always checking the type, or checking for null after a cast. Good practice. :O)

  3. Pingback: Dew Drop – February 28, 2012 (#1,276) | Alvin Ashcraft's Morning Dew

Leave a comment