22 Sep
2009

NETDUG: WPF Event Routing Sample Code

Category:UncategorizedTag: , , :

Here is the sample code for last Thursday’s WPF Event Routing presentation.

Download Sample Code

I know I covered the subject fast, but I was in a hurry. I had to go to the airport. So here is a quick review.

Event Types:

  • Direct events are like ordinary .NET events. They originate in one element and don’t pass to any other. For example, MouseEnter is a direct event.
  • Bubbling events are events that travel up the containment hierarchy. For example, MouseDown is a bubbling event. It is raised first by the element that is clicked. Next, it is raised by that element’s parent, and then by that element’s parent, and so on, until WPF reaches the top of the element tree.
  • Tunneling events are events that travel down the containment hierarchy. They give you the chance to preview (and possible stop) an event before it reaches the appropriate control. For example, PreviewKeyDown allows you to intercept a key press, first at the window level, and then in increasingly more specific containers until you reach the element that had focus when the key was pressed.

RoutedEventArgs Class:

  • Source indicates what object raised the event.
  • OriginalSource indicates what object originally raised the event. Usually the OriginalSource is the same a the Source. But in some cases they could be different. For example, if you click close to the border of a window, you will get a Window object for the Source but a Border object for the OriginalSource.
  • RoutedEvent provides the RoutedEvent object for the event triggered by your event handler.
  • Handled allows you to halt the event bubbling or tunneling process.

Here is a simple example of when you might use a bubbling event:

<StackPanel Hyperlink.Click="StackPanel_Click">
    <TextBlock>
        <Hyperlink NavigateUri="http://www.yahoo.com">Yahoo!</Hyperlink>
   </TextBlock>
   <TextBlock>
       <Hyperlink NavigateUri="http://www.google.com">Google</Hyperlink>
   </TextBlock>
   <TextBlock>
       <Hyperlink NavigateUri="http://www.msn.com">MSN</Hyperlink>
   </TextBlock>
</StackPanel>
private void StackPanel_Click(object sender, RoutedEventArgs e)
{
    Process.Start(((Hyperlink)e.Source).NavigateUri.ToString());
}

So instead of having to create an event handler for each hyperlink, or creating a single event handler and pointing each hyperlink to the same event handler, I can use one event handler on the parent element.

5 thoughts on “NETDUG: WPF Event Routing Sample Code

  1. I know this is a quick piece of code to show how you can do it but lots of people will just copy paste it. So a good method name (HyperlinkClicked or something), and at least check the arguments

    var hyperlink = e.Source as Hyperlink;
    if (hyperlink != null)
    Process.Start(hyperlink.NavigateUri.ToString());

  2. @Steve

    I agree, you want a relevant method name, but I dissagree on checking the parameters. I know that based on my XAML element hierarchy that the only items performing the attached Hyperlink.Click event is a hyperlink object, therefore it will be impossible for the e.Source to be anything but a hyperlink or for it to be null. But if it makes you feel all warm and fuzzy by adding the extra code to explicitly check the source, then knock yourself out.

  3. @Steve

    I understand that it is the one from ButtonBase, but based on my XAML there are no buttons in the element tree. Therefore it will be a hyperlink that performs the event. Granted, if I were to add a button to my element tree, I would need to check the source, but I am not going to add a button there, so I don’t need to check my parameters in this example.

  4. @Steve
    Actually a better reason for not having the parameter check is that if Brian is correct and the event should never fire for anything other than a hyperlink, you would not want to mask the issue if it firing for any other reason by just bypassing the code. A nice invalid cast exception will point immediately to an issue with your event structure that could be eating performance by routing unneeded events.

Comments are closed.