Published: 16 Feb 2011
By: Xianzhong Zhu
Download Sample Code

In this article, we will focus upon MultiTouch and manipulation related operations in Silverlight for Windows Phone programming.

Contents [hide]

The Windows Phone 7 Silverlight Programming series

  • Part 1 In this article, we will focus upon MultiTouch and manipulation related operations in Silverlight for Windows Phone programming.
  • Part 2 In this article, we will delve into how to perform navigation operations between pages as well as passing data in a Silverlight for Windows Phone application.
  • Part 3 In this article I will introduce to you how to handle XML data in Windows Phone 7 for Silverlight applications.
  • Introduction

    As Microsoft's latest mobile operating system, Windows Phone 7 is a vast improvement over its previous buddies. Based on the ready-made facilities, such as Silverlight, XNA, and C#, with a slight modification you can develop most types of extremely powerful mobile applications. And also, as you can image, Windows Phone 7 aims at high platforms and high configurations.

    In this article, we will focus upon MultiTouch and manipulation related operations in Silverlight for Windows Phone programming. In fact, there are several ways to obtain the equipment touch information and gain control over the phone. The most closely related event should be Touch.FrameReported and three other ones defined in UIElement, i.e. ManipulationStarted, ManipulationDelta, and ManipulationCompleted. In addition, there are some more, to be covered later on.

    First of all, let's research into the Touch class and its FrameReported event.

    NOTE

    The sample test environments in this article involve:

    1. Windows 7;

    2. .NET 4.0;

    3. Visual Studio 2010;

    4. Windows Phone Developer Tools RTW;

    5. An open sourced project named Silverlight for Windows Phone Toolkit at codeplex (http://silverlight.codeplex.com/releases).

    The Touch Class and Its FrameReported Event

    The Touch.FrameReported event serves as an application-level service, providing an underlying touch programming interface for Silverlight for Windows Phone. In detail, we can use it to get information for each touch point whether in scope of the operating system or the entire application. Touch is a public static class, which only contains a static member - the FrameReported event.

    As you can easily image, we can, in our applications, subscribe to this event and then through the TouchFrameEventArgs parameter in the event handler to obtain data we want to work with.

    Subscribe to the Touch.FrameReported event

    Now, let's first look at the event subscription in our sample page TouchPage.xaml (the sample project is named WP7Touch).

    Completely the same event subscription sketch as that in Silverlight, isn't it? TouchFrameEventArgs contains a couple of secrets that can tell all we want to make clear. So, let's continue to look at this class definition.

    First, the GetTouchPoints method returns a collection of touch points, which will be of great help when you want to use multiple fingers to manipulate your Windows Phone 7 application and at the same time you want to identify the specific location for each finger.

    Next, the GetPrimaryTouchPoint method returns the primary touch point for the current frame. Note the primary touch point refers to the corresponding touch point when you use only one finger to touch the screen. If you use only one finger when you touch the screen, it must be the primary touch point. Consider another case: the first finger is touching the screen while the second finger is put on the screen. In this case, the second finger isn't the primary touch point. But now if you are still putting the second finger on the screen while lift the first finger and then put it back on the screen. It is no more the primary touch point! Primary touch point will only appear only in the absence of other fingers touching the screen.

    Note GetPrimaryTouchPoint and GetTouchPoints both require a parameter of type UIElement, both returning information associated with the touch point.

    Next, let's look more closely at the TouchPoint class related definition.

    In essence, TouchPoint is an abstraction of the touching finger across the screen. It provides 4 read- only properties:

    Action: of enum type TouchAction, contains 3 values: Down, Move and Up.

    Position: of type Point, which is relative to the upper left corner of the referencing element ( i.e. the UIElement parameter in the above-mentioned methods GetPrimaryTouchPoint or GetTouchPoints). If the parameter passed in is null, then the resulting Position is relative to the upper left corner of the screen (the Position may be negative when the incoming value is non- null).

    Size: of type Size, corresponding to a rectangular area within the touch on the screen. But the value of the property seemingly cannot obtain the desired valid value because, in my demo, its Width and Height properties are always 1 (perhaps because we are running on an emulator?).

    TouchDevice: of type TouchDevice, contains 2 read-only properties: one is Id property (of type int) to differentiate fingers; the other is the DirectlyOver property of type UIElement, which is the top-level UI element closest to the fingers. Note if we need to distinguish between multiple fingers, then the Id attribute comes to help. When a particular finger touches the screen, a series of specific events associated with the finger always begin with a Down operation, followed by the Move event, and finally Up event. All of these events are associated with the same Id. (However, we should not take for granted that the primary touch point related Id value is always 0 or 1, although it is always 0 in my demo.)

    Now let's tidy up: first, subscribe to the Touch.FrameReported event; second, invoke the GetPrimaryTouchPoint or GetTouchPoints method of the TouchFrameEventArgs parameter in the event handler to obtain the corresponding touch point data. Note the method GetPrimaryTouchPoint returns a TouchPoint while the method GetTouchPoints returns a TouchPointCollection (this collection contains 0 or more TouchPoints). Last, from the TouchPoint corresponding attribute, we can get more detailed information. Please see the following code:

    There are 3 types of information, Down, Move and Up, hidden inside the TouchPoint structure returned in the GetPrimaryTouchPoint method or TouchPointCollection returned in the GetTouchPoints method. In another word, when you press and then release the fingers the FrameReported event will be fired once respectively, the action information being Up and Down, respectively. If you move your fingers on the screen, then the FrameReported event will be triggered at least 3 times, and the action information being Down, Move, and Up. Let's look at the running-time screenshots, as shown from Figure 1 to 3.

    Figure 1: When the mouse is pressed (in the Simulator)

    When the mouse is pressed (in the Simulator)

    Figure 2: When the mouse moves(in the Simulator)

    When the mouse moves(in the Simulator)

    Figure 3: When the mouse is released (in the Simulator)

    When the mouse is released (in the Simulator)

    In addition, if you use two fingers touching the screen, the FrameReported event will be triggered twice respectively. But, if you call the GetPrimaryTouchPoint method it only returns the first finger touching screen information. GetPrimaryTouchPoint will return null for the second finger. When you touch the screen using more than two fingers the case will be same as using two fingers.

    About the SuspendMousePromotionUntilTouchUp method

    Till now, we've not mentioned another method SuspendMousePromotionUntilTouchUp of the TouchFrameEventArgs class. This method is used to disable automatic mouse-event promotion for the primary touch point until all touch points report as Up. The mouse event promotion term derives from the desktop version of Silverlight, so that MultiTouch users can use touch and gestures to substitute the mouse moves or mouse clicks. For example, when a user uses the MultiTouch devices to click on a button, the expected behavior of the button will be the same as when the mouse is clicked, so the desktop version of Silverlight delivers the touch input mechanism for automatic promotion to mouse events, and later it gets extended to Silverlight for Windows Phone. However, mouse event promotion is only valid for the primary touch point (the first finger touching the screen and at the same time there are no other fingers touching the screen), so if you don't want to make the movements of a specified finger be promoted, you can use the SuspendMousePromotionUntilTouchUp method to suspend mouse event promotion.

    Note the SuspendMousePromotionUntilTouchUp method can only be invoked in the primary touch point down case; otherwise, an InvalidOperationException exception will be thrown.

    When the above invocation condition is not met, the program will throw an exception, as shown in Figure 4.

    Figure 4: An exception is thrown when the SuspendMousePromotionUntilTouchUp method calling condition is not met

    An exception 

is thrown when the SuspendMousePromotionUntilTouchUp method calling condition is not met

    The correct calling approach should be like the following.

    The last point to notice is in Windows Phone 7 the mouse operation usually does not need to be handled, unless the mobile contains controls that cannot be dealt with MultiTouch input. So, in most cases, we do not have to suppress the mouse event promotion.

    Well, regarding the underlying Touch interface we've introduced so much. Starting from the next section, I will introduce the high-level MultiTouch programming interface, associated with the UIElement class.

    The Manipulation Related Events

    The three events, i.e. ManipulationStarted, ManipulationDelta and ManipulationCompleted are not alone to deal with each finger's touch information. In fact, all finger- panning and zooming manipulations have been integrated. Due to these three events are all defined in the UIElement class, based on a specific element, rather than the application-level events, so we can add them to any UI element, such as ListBox, Canvas, Rectangle, and so on. The following XAML code (in the sample page ManipulationPage.xaml) illustrates an example of subscribing to these three events for a Rectangle element.

    Seen from their name, the order in which they are triggered can be easily deduced: first a ManipulationStarted event, followed by 0 or more of the ManipulationDelta events, and finally the ManipulationCompleted event. Their corresponding event handlers defined in the Code-Behind file are as follows:

    In most cases we need to deal with these three types of event parameters. Despite different types, they all have the following same properties:

    • OriginalSource: of type object and defined within the RoutedEventArgs class, through which we can obtain the original object to trigger the event.
    • ManipulationContainer: of type UIElement, through which we can get the object that defines the current touch operation coordinate (usually the same as OriginalSource).
    • ManipulationOrigin: of type Point, through which we can get the original coordinates of the action, i.e. the finger touch point coordinates (whose values are relative to the left corner of the ManipulationContainer object). If you have two or more fingers touching one element, then the ManipulationOrigin property gives the average coordinates of multiple fingers.
    • Handled: of type bool, used to indicate the event handling states of routed events during the routing process. If we don't want the current event to be propagated down the visual tree we can set it to true.

    In the next section, I will describe all the Manipulation events-related stuff through a concrete example.

    Manipulating the rectangle

    This sample page is also simple, with a Rectangle control in the Grid named ContentPanel (see Figure 5). We can drag the rectangle with the parent control to look at the interested Manipulation events. To gain a better result I've also capture the document tree in the left of Figure 5.

    Figure 5: A screenshot in the design time

    A screenshot in the design time

    Now, let's look at the Behind-Code implementation.

    Some of the running-time output results are shown in Figure 6.

    Figure 6: The tracking manipulation result is output to the Debug window

    The tracking manipulation result is output to the 

Debug window

    It is the same order as anticipated above. And also, the preceding actions trigger the ManipulationDelta event 3 times. Because the fingers (here is a mouse, because it is the act on the Simulator) move on the screen, so each time the ManipulationOrigin value is not the same. At the same time, we can also see OriginalSource and ManipulationContainer are the same.

    Select the correct events triggered on an element

    Different from the Touch.FrameReported event that associates specific fingers with a different Id, the Manipulation related events are based on the UI element, so these events do not require Id. When multiple fingers touch a single element they will be converted to a series of Manipulation related events, while when the two fingers touch the different elements two different series of Manipulation related events occur (and the two series are independent). Of course, they can be distinguished using the ManipulationContainer property. For example, placing a finger upon an element, a ManipulatedStarted event will be triggered; and if your finger moves the ManipulationDelta event will also be triggered. Keeping this finger intact, placing another finger on the same element will not trigger a new ManipulatonStarted event. But if I put another finger on the other element, it triggers the ManipulationStarted event of the corresponding element.

    If you want to keep track of different fingers touch information on a single element, then you should fall back upon the Touch.FrameReported event.

    Detailing 3 kinds of Manipulation event arguments

    First, let's look at the simplest ManipulationStartedEventArgs class. In addition to the above 4 same properties, it also has a Complete method, which is used to tell the system to end off the ManipulationStarted event, so that if your fingers move on the screen the ManipulationDelta will not be triggered.

    Next is the ManipulationDeltaEventArgs class. In addition to common properties, this class also contains 2 properties of type ManipulationDelta: CumulativeManipulation and DeltaManipulation. And ManipulationDelta contains 2 properties of type Point: Scale and Translation.

    Scale and Translation can help us resolve the compound action of one or more fingers on an element into moving and sizing of the element itself. Scale represents a scaling factor; Translation is a translation of the distance. We can change the value of Translation using one finger, but if you want to change Scale you need to use two fingers. When you move your finger on an element, the difference of new and original locations of the finger will be reflected in Translation. If you are using two fingers to zoom, the difference of distances between the original fingers and new fingers after zooming will be reflected in Scale. One thing to note is: if we do not have the element scaled, the Scale value is (0, 0).

    Now, let's look at the differences between CumulativeManipulation and DeltaManipulation. Although both of them contains Scale and Translation, those in CumulativeManipulation are the result of adding accumulation from the ManipulationStarted event to the current event (can be seen by the property name), while those in DeltaManipulation are the result of the latest ManipulationDelta event relative to the previous ManipulationDelta or ManipulationStarted event, just a onetime change.

    In addition to the CumulativeManipulation and DeltaManipulation properties, ManipulationDeltaEventArgs also has a Complete method, whose role is same as that in the ManipulationStarted event, notifying system the current operation is over. So, after calling this method even if the finger moves on some element the ManipulationDelta event will only be triggered one time, as a result of which this series of Manipulation operations will no longer follow up the ManipulationDelta event (However the ManipulationCompleted event can be triggered).

    In addition, ManipulationDeltaEventArgs also has an IsInertial property and a Velocities property. For the related details, readers can continue the related researching.

    Finally, ManipulationCompletedEventArgs also contains the following 3 attributes:

    • FinalVelocities: of same type as Velocities in the ManipulationDeltaEventArgs class - ManipulationVelocities, through which you can obtain the speed when your finger leaves the screen.
    • IsInertial: of type bool, same as IsInertial in ManipulationDeltaEventArgs, to be explained in detail later.
    • TotalManipulation: similar to CumulativeManipulation in ManipulationDeltaEventArgs, of type ManipulationDelta, corresponds to the whole process of accumulation from the ManipulationStarted event to the ManipulationCompleted event.

    A complete demo

    Now, let's look into a complete example. I've added a TranslateTransform to the RenderTransform property of the Rectangle element. Now, in the ManipulationDelta event handler of the Rectangle element we work with TranslateTransform, making this rectangle movable on the screen, and at the same time having the obtained information output to the Output window. Let's check out the rewritten code:

    In the rectangle_ManipulationDelta method above, I assign the x and y of Translation to the x and y of TranslateTransform, to ensure that the rectangle is free to move. The following is a simulator and a screenshot of the output window:

    Figure 7: Move the rectangle to find more result

    Move the rectangle to find more result

    Figure 8: Part of the related output

    Part of the related output

    Note in the figure above the FinalVelocities value in the ManipulationCompleted event parameter is large; it is because I drag the rectangle very quickly. However, if it is a very slow moving, then this value is changed to 0, and the IsInertial property to False. In addition, if you call the Complete method of the event arguments in the ManipulationDelta event handler, then you can only move the rectangle one time and then another, because the ManipulationDelta event will only be triggered for one time and the FinalVelocities property in the ManipulationCompleted event parameters will throw a NullReferenceException exception.

    More about the IsInertial property

    In WPF, by setting the ManipulationInertiaStartingEventArgs parameter, the system, when fingers leave the screen, can simulate the effect of inertia using an algorithm, i.e. an extra ManipulationDelta event is triggered. Silverlight for Windows Phone, however, does not support this feature. In WPF, the IsInertial property in the ManipulationDelta and ManipulationCompleted event parameters is used to indicate whether the current event is triggered during the course of inertial effects occurring. In Silverlight for Windows Phone, the IsInertial property in the ManipulationDelta event parameter is always False. Even in the case of fast moving and the IsInertial in the ManipulationCompleted event being True, any inertia effects do not appear, just the process of moving smooth. And also, as soon as the finger lifts the rectangle element immediately stops moving. So, in my opinion, the IsInertial property in the ManipulationDelta and ManipulationCompleted event parameters does not have too much value. As a result, if you want to simulate inertia effects in Silverlight for Windows Phone, then we can achieve this with the help of the FinalVelocities property in the ManipulationCompleted event argument.

    Well, we talk so much concerning the high-level touch programming interfaces on Windows Phone 7. Starting from the next section, we will explore the gesture-related touch operations.

    GestureListener in Silverlight for Windows Phone Toolkit

    Silverlight for Windows Phone Toolkit from CodePlex offers developers a couple of controls for Windows Phone application development, designed to match the rich user experience of the Windows Phone 7. In this article, we will only show interest in the GestureListener control in the toolkit.

    Install Silverlight for Windows Phone Toolkit

    Follow the steps below to download and install Silverlight for Windows Phone Toolkit:

    1. Open your browser and navigate to the url http://silverlight.codeplex.com/releases to download the file Silverlight for Windows Phone Toolkit - Nov 2010.msi (1828KB).

    2. Double click the above .msi file to install Silverlight for Windows Phone Toolkit. By default, the install path should be C:\Program Files\Microsoft SDKs\Windows Phone\v7.0\Toolkit\Nov10.

    Using the GestureListener Control

    1. Add a simple Windows Phone 7 Protrait Page named GestureListenerPage.xaml.

    2. Right click the sample project to add reference to the Silverlight for Windows Phone Toolkit assembly, as shown in Figure 9.

    Figure 9: Add reference to the Silverlight for Windows Phone Toolkit assembly

    Add reference to the Silverlight for Windows 

Phone Toolkit assembly

    3. Open the file GestureListenerPage.xaml and add the following xmlns reference.

    4. Inside the Grid control named ContentPanel add the following:

    Here GestureService is a helper wrapper around the control GestureListener. In fact, an easy and typical way to add the preceding interested event listeners is clicking the GestureListener control and then double clicking the related items from the Events tab in the Properties dialog. In this case, I've added our interested gesture listeners to the target rectangle control.

    Next, let's continue to look at the related Code-Behind event handlers programming.

    As is seen, the above events are very easy to use. GestureBegin and GestureCompleted are quite similar to the previous ManipulationStarted and ManipulationCompleted, while the most similar events like Manipulation should be Drag.

    Now, let's watch the running result. When you click (Tap) the rectangle, it will change the color randomly. The output is as shown in Figure 10.

    Figure 10: Click (Tap) the rectangle related output

    Click (Tap) the rectangle related output

    When you double click (Double Tap) the rectangle, it will return to its original location, and color changes because a double click includes a single click. The output is as shown in Figure 11.

    Figure 11: Double click the rectangle related output

    Double click the rectangle related output

    In the state of Press and Hold, a dialog box will pop up. The output is shown in Figure 12.

    Figure 12: Press and hold will result in a popup dialog

    Press and hold will result in a popup dialog

    A Flick operation includes the Drag operation. The output is as shown in Figure 13.

    Figure 13: The flick operation corresponding output

    The flick operation corresponding output

    On the whole, with the help of the GestureListener object and its related events in Silverlight for Windows Phone Toolkit, we can more easily identify the gesture.

    More to Explore

    There is also another gesture related solution in the XNA library. This mainly revolves around the TouchPanel class. I want to leave this to the readers to start new exploration.

    Summary

    In Windows Phone 7 Silverlight Programming, MultiTouch and Manipulation are one of the fundamentals. This article brought you a very elementary tutorial with very simple and even ugly samples. Although you may have a good foundation in the area of C# and Silverlight, there are still much to learn. Anyway, we have enough reasons to say tomorrow of Windows Phone 7 will be brilliant.

    The Windows Phone 7 Silverlight Programming series

  • Part 1 In this article, we will focus upon MultiTouch and manipulation related operations in Silverlight for Windows Phone programming.
  • Part 2 In this article, we will delve into how to perform navigation operations between pages as well as passing data in a Silverlight for Windows Phone application.
  • Part 3 In this article I will introduce to you how to handle XML data in Windows Phone 7 for Silverlight applications.
  • <<  Previous Article Continue reading and see our next or previous articles Next Article >>

    About Xianzhong Zhu

    I'm a college teacher and also a freelance developer and writer from WeiFang China, with more than fourteen years of experience in design, and development of various kinds of products and applications on Windows platform. My expertise is in Visual C++/Basic/C#, SQL Server 2000/2005/2008, PHP+MyS...

    This author has published 81 articles on DotNetSlackers. View other articles or the complete profile here.

    Other articles in this category


    Displaying Notification Messages in a Silverlight Dashboard Application
    In this article we will see how we could display a notification message and further a list of notifi...
    Develop a Flexible 2.5D Scene Editor Targeting Silverlight RPG Games - Part 1
    Starting from this article, I'm going to introduce to you an excellent 2.5D RPG games scene editor -...
    Develop a Flexible 2.5D Scene Editor Targeting Silverlight RPG Games - Part 2
    In this article, I'm going to introduce to you how to construct such a 2.5D RPG game scene editor th...
    Widget Refresh Timer in MVVM in Silverlight
    In this article we'll see how to refresh and disable widgets using the Model View View-Model pattern...
    Air Space Issue in Web Browser Control in Silverlight
    Air Space issue is a common issue in Web Browser control in Silverlight and WPF. To explain the issu...

    You might also be interested in the following related blog posts


    Why DataBinding With ComboBoxes is NonTrivial read more
    Moonlight 1.0 Released, Silverlight script updated – and a Chrome hack read more
    Apple Safari for Windows and Microsoft Silverlight read more
    Streamline Model-View-Presenter with new StructureMap feature - level 300 read more
    Sim Card and Tablet PC - Would Be Perfect Together read more
    Top
     
     
     

    Please login to rate or to leave a comment.

    Free Agile Project Management Tool from Telerik
    TeamPulse Community Edition helps your team effectively capture requirements, manage project plans, assign and track work, and most importantly, be continually connected with each other.