Input with Windows Presentation Foundation
(Page 1 of 4 )
This five-part article series walks you through the input handling mechanisms available in WPF. It is excerpted from
Programming WPF, Second Edition, written by Chris Sells and Ian Griffiths (O'Reilly, 2007; ISBN: 0596510373). Copyright © 2007 O'Reilly Media, Inc. All rights reserved. Used with permission from the publisher. Available from booksellers or direct from O'Reilly Media.
A user interface wouldn’t be much use if it couldn’t respond to user input. In this chapter, we will examine the input handling mechanisms available in WPF. There are three main kinds of user input for a Windows application: mouse, keyboard, and ink.* Any user interface element can receive input—not just controls. This is not surprising, because controls rely entirely on the services of lower-level elements like Rectangle andTextBlock in order to provide visuals. All of the input mechanisms described in the following sections are, therefore, available on all user interface element types.
Raw user input is delivered to your code through WPF’s routed event mechanism. There is also a higher-level concept of a command—a particular action that might be accessible through several different inputs such as keyboard shortcuts, toolbar buttons, and menu items.
Routed Events The .NET Framework defines a standard mechanism for managing events. A class may expose several events, and each event may have any number of subscribers. WPF augments this standard mechanism to overcome a limitation: if a normal .NET event has no registered handlers, it is effectively ignored.
Consider what this would mean for a typical WPF control. Most controls are made up of multiple visual components. For example, suppose you give a button a very plain appearance consisting of a singleRectangle, and provide a simple piece of text as the content. (Chapter 9 describes how to customize a control’s appearance.) Even with such basic visuals, there are still two elements present: the text and the rectangle. The button should respond to a mouse click whether the mouse is over the text or the rectangle. In the standard .NET event handling model, this would mean registering aMouseLeftButtonUp event handler for both elements.
This problem would get much worse when taking advantage of WPF’s content model. AButtonis not restricted to having plain text as a caption—it can contain any object as content. The example in Figure 4-1 is not especially ambitious, but even this has six visible elements: the yellow outlined circle, the two dots for the eyes, the curve for the mouth, the text, and the button background itself. Attaching event handlers for every single element would be tedious and inefficient. Fortunately, it’s not necessary.

Figure 4-1. A button with nested content
WPF uses routed events, which are rather more thorough than normal events. Instead of just calling handlers attached to the element that raised the event, WPF walks the tree of user interface elements, calling all handlers for the routed event attached to any node from the originating element right up to the root of the user interface tree. This behavior is the defining feature of routed events, and is at the heart of event handling in WPF.
Example 4-1 shows markup for the button in Figure 4-1. If one of the Ellipse elements inside theCanvas were to receive input, event routing would enable theButton,Grid,Canvas, andEllipseto receive the event, as Figure 4-2 shows.
Example 4-1. Handling events in a user interface tree
<Button PreviewMouseDown="PreviewMouseDownButton"
MouseDown="MouseDownButton">
<Grid PreviewMouseDown="PreviewMouseDownGrid"
MouseDown="MouseDownGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Canvas PreviewMouseDown="PreviewMouseDownCanvas"
MouseDown="MouseDownCanvas"
Width="20" Height="18" VerticalAlignment="Center">
<Ellipse PreviewMouseDown="PreviewMouseDownEllipse"
MouseDown="MouseDownEllipse"
x:Name="myEllipse"
Canvas.Left="1" Canvas.Top="1" Width="16" Height="16"
Fill="Yellow" Stroke="Black" />
<Ellipse Canvas.Left="4.5" Canvas.Top="5" Width="2.5" Height="3"
Fill="Black" />
<Ellipse Canvas.Left="11" Canvas.Top="5" Width="2.5" Height="3"
Fill="Black" />
<Path Data="M 5,10 A 3,3 0 0 0 13,10" Stroke="Black" />
</Canvas>
<TextBlock Grid.Column="1">Click! </TextBlock>
</Grid>
</Button>

Figure 4-2. Routed events
A routed event can either be bubbling, tunneling, or direct. A bubbling event starts by looking for event handlers attached to the target element that raised the event, and then looks at its parent and then its parent’s parent, and so on until it reaches the root of the tree; this order is indicated by the numbers in Figure 4-2. A tunneling event works in reverse—it looks for handlers at the root of the tree first and works its way down, finishing with the originating element.
Direct events work like normal .NET events: only handlers attached directly to the originating element are notified—no real routing occurs. This is typically used for events that make sense only in the context of their target element. For example, it would be unhelpful if mouse enter and leave events were bubbled or tunneled—the parent element is unlikely to care about when the mouse moves from one child element to another. At the parent element, you would expect “mouse leave” to mean “the mouse has left the parent element,” and because direct event routing is used, that’s exactly what it does mean. If bubbling were used, the event would effectively mean “the mouse has left an element that is inside the parent, and is now inside another element that may or may not be inside the parent,” which would be less useful.
Next: Routed Events, continued >>
More .NET Articles
More By O'Reilly Media
|
This article is excerpted from Programming WPF, Second Edition, written by Chris Sells and Ian Griffiths (O'Reilly, 2007; ISBN: 0596510373). Check it out today at your favorite bookstore. Buy this book now.
|
|