Event Manipulation in Touch screen for Windows Phone 7


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.


Similar Articles