This chapter
is taken from book "Programming Windows Phone 7" by Charles Petzold published by
Microsoft press.
http://www.charlespetzold.com/phone/index.html
The Events Manipulation
As you learn about the touch interface of windows phone
7 in my last article that Windows Phone 7 comes with a feature that is likely to
be new and unusual. The screen on the phone is sensitive to touch. The
multi-touch screen on a Windows Phone 7 device can detect at least four
simultaneous fingers. It is the interaction of these fingers that makes
multi-touch so challenging for programmers. Now in this article we talk about
the events manipulation:
The high-level touch interface in Silverlight involves
three events: ManipulationStarted,
ManipulationDelta,
and ManipulationCompleted.
These events don't bother with reporting the activity of individual fingers.
Instead, they consolidate the activity of multiple fingers into translation and
scaling operations. The events also accumulate velocity information, so while
they don't support inertia directly, they can be used to implement inertia.
While
Touch.FrameReported delivered touch information for
the entire application, the Manipulation
events are based on individual elements, so in
SilverlightTapHello1, a ManipulationStarted
event handler can be set on the
TextBlock:
<Grid
x:Name="ContentPanel"
Grid.Row="1"
Margin="12,0,12,0">
<TextBlock
Text="Hello, Windows
Phone 7!"
Padding="0
22"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ManipulationStarted="OnTextBlockManipulationStarted"
/>
</Grid>
The MainPage.xaml.cs contains this event handler:
public
partial class
MainPage : PhoneApplicationPage
{
Random rand =
new Random();
public MainPage()
{
InitializeComponent();
}
void OnTextBlockManipulationStarted(object
sender, ManipulationStartedEventArgs args)
{
TextBlock txtblk = sender
as TextBlock;
Color clr =
Color.FromArgb(255, (byte)rand.Next(256),
(byte)rand.Next(256),
(byte)rand.Next(256));
txtblk.Foreground = new
SolidColorBrush(clr);
args.Complete();
}
}
The event handler is able to get the element generating
the message from the sender
argument. That will always be the
TextBlock. The
TextBlock is also
available from the args.OriginalSource
property and the
args.ManipulationContainer
property.
Although that's certainly possible, there's actually an
easier way. The UIElement
class defines all the
Manipulation events. But the
Control class (from
which MainPage
derives) supplements those events with protected virtual methods. You don't need
to install a handler for the
ManipulationStarted event on
MainPage; instead you
can override the OnManipulationStarted
virtual method.
This approach is implemented in the SilverlightTapHello2
project. The XAML file doesn't refer to any events but gives the
TextBlock a name so
that it can be referred to in code:
<Grid
x:Name="ContentPanel"
Grid.Row="1"
Margin="12,0,12,0">
<TextBlock
Name="txtblk"
Text="Hello,
Windows Phone 7!"
Padding="0
22"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
</Grid>
The MainPage
class overrides the
OnManipulationStarted method:
public
partial class
MainPage : PhoneApplicationPage
{
Random rand =
new Random();
Brush originalBrush;
public MainPage()
{
InitializeComponent();
originalBrush = txtblk.Foreground;
}
protected
override void OnManipulationStarted(ManipulationStartedEventArgs
args)
{
if (args.OriginalSource == txtblk)
{
txtblk.Foreground = new
SolidColorBrush(Color.FromArgb(255,
(byte)rand.Next(256),
(byte)rand.Next(256),(byte)rand.Next(256)));
}
else
{
txtblk.Foreground = originalBrush;
}
args.Complete();
base.OnManipulationStarted(args);
}
}
In the
ManipulationStartedEventArgs a property named
OriginalSource
indicates where this event began—in other words, the topmost element that the
user tapped. If this equals the txtblk
object, the method creates a random color for the
Foreground
property. If not, then the Foreground
property is set to the original brush.
In this
OnManiulationStarted method we're handling events
for MainPage,
but that OriginalSource
property tells us the event actually originated lower in
the visual tree. This is part of the benefit of the Silverlight feature known as
routed event handling.
Routed Events
In Microsoft Windows programming, keyboard and mouse
input always go to particular controls. Keyboard input always goes to the
control with the input focus. Mouse input always goes to the topmost enabled
control under the mouse pointer. Stylus and touch input is handled similarly to
the mouse. But sometimes this is inconvenient. Sometimes the control underneath
needs the user-input more than the control on top.
The Manipulation
events originate at the topmost enabled element
touched by the user. However, if that element is not interested in the event,
the event then goes to that element's parent, and so forth up the visual tree
ending at the PhoneApplicationFrame
element. Any element along the way can grab the input and do something with it,
and also inhibit further progress of the event up the tree.
This is why you can override the OnManipulationStarted method in MainPage and
also get manipulation events for the TextBlock. By default the TextBlock isn't
interested in those events. The event argument for the
ManipulationStarted event is ManipulationStartedEventArgs, which derives from
RoutedEventArgs. It is RoutedEventArgs that defines the OriginalSource property
that indicates the element on which the event began. But this suggests another
approach that combines the two techniques shown in SilverlightTapHello1 and
SilverlightTapHello2.
Here's the XAML file of SilverlightTapHello3:
<Grid
x:Name="ContentPanel"
Grid.Row="1"
Margin="12,0,12,0">
<TextBlock
Name="txtblk"
Text="Hello,
Windows Phone 7!"
Padding="0
22"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ManipulationStarted="OnTextBlockManipulationStarted"
</Grid>
The TextBlock
has a Name
as in the first program. A handler for the
ManipulationStarted
event is set on the TextBlock
as in the first program. Both the event handler and an
override of OnManipulationStarted
appear in the code-behind file:
public
partial class
MainPage : PhoneApplicationPage
{
Random rand =
new Random();
Brush originalBrush;
public MainPage()
{
InitializeComponent();
originalBrush = txtblk.Foreground;
}
void OnTextBlockManipulationStarted(object
sender, ManipulationStartedEventArgs args)
{
txtblk.Foreground = new
SolidColorBrush(Color.FromArgb(255, (byte)rand.Next(256),
(byte)rand.Next(256),(byte)rand.Next(256)));
args.Complete();
args.Handled = true;
}
protected
override void OnManipulationStarted(ManipulationStartedEventArgs
args)
{
txtblk.Foreground = originalBrush;
args.Complete();
base.OnManipulationStarted(args);
}
}
The logic has been split between the two methods, making
the whole thing rather more elegant, I think. The
OnTextBlockManipulationStarted
method only gets events when the
TextBlock is touched.
The OnManipulationStarted
event gets all events for
MainPage.
Summary
I hope this article helps you to clear the touch
interface programming and event manipulation for windows phone 7.