Translate

Wednesday, 30 October 2013

WPF Routed Events

WPF 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 single Rectangle, 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
a MouseLeftButtonUp event handler for both elements.
This problem would get much worse when taking advantage of WPF’s content
model. A Button is not restricted to having plain text as a caption—it can contain any
object as content. The example 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.
WPF uses routedevents , 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 . If one of the Ellipse elements
inside the Canvas were to receive input, event routing would enable the Button,
Grid, Canvas, and Ellipse to receive the event, as shows.

Example. 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" />

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 . 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.

No comments: