C# 在WinRT应用程序中处理两个、三个、四个手指的滑动手势

C# 在WinRT应用程序中处理两个、三个、四个手指的滑动手势,c#,.net,xaml,windows-8,windows-runtime,C#,.net,Xaml,Windows 8,Windows Runtime,我有以下代码: private Point initialpoint; private void ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e) { initialpoint = e.Position; } private void ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) { Poi

我有以下代码:

private Point initialpoint;

private void ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
{
    initialpoint = e.Position;
}

private void ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
    Point currentpoint = e.Position;
    if (currentpoint.X - initialpoint.X >= 100)
    {
        System.Diagnostics.Debug.WriteLine("Swipe Right");
        e.Complete();
    }
}
我可以很容易地处理1个手指的滑动手势,但我也想处理2、3、4个手指的滑动手势。有人能告诉我怎么做吗?

根据这一点,您需要使用通知。带有工作示例代码的文档位于

从最后一个链接:

指针对象表示来自输入设备(如鼠标、笔/触笔、单指或多指)的单个唯一输入“触点”(指针点)。系统在首次检测到触点时创建指针,并在指针离开(离开)检测范围或取消时将其销毁。在多个设备或多点触摸输入的情况下,每个触点都被视为唯一的指针


请注意,我没有多点触控Windows8设备来测试这段代码。因此,它已经在Simuator中进行了测试,并具有所有的局限性,正如上面的链接所述,Windows 8没有内置的手势支持来检测多个手指,您必须使用较低级别的功能

首先,我在上面的MSDN示例代码中添加了两个字典,在类定义中添加了两个滑动阈值变量

Dictionary<uint, Point> startLocation;
Dictionary<uint, bool> pointSwiped;
int swipeThresholdX = 100;
int swipeThresholdY = 100;
删除:

startLocation.Remove(pt.PointerId);
pointSwiped.Remove(pt.PointerId);
最后将它们放在PointerMovedEvent中:

private void targetContainer_PointerMoved(object sender, PointerRoutedEventArgs e)
{
    Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(targetContainer);
    if (currentPoint.IsInContact)
    {
        if (startLocation.ContainsKey(currentPoint.PointerId))
        {
            Point startPoint = startLocation[currentPoint.PointerId];
            if (Math.Abs(currentPoint.Position.X - startPoint.X) > swipeThresholdX) // I only did one Axis for testing
            {
                pointSwiped[currentPoint.PointerId] = true;
            }
        }
    }
    updateInfoPop(e);
}               
最终修改的MSDN示例:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace PointerInput
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        Windows.Devices.Input.TouchCapabilities SupportedContacts = new Windows.Devices.Input.TouchCapabilities();

        uint numActiveContacts;
        Dictionary<uint, Windows.UI.Input.PointerPoint> contacts;
        Dictionary<uint, Point> startLocation;
        Dictionary<uint, bool> pointSwiped;
        int swipeThresholdX = 100;
        int swipeThresholdY = 100;

        public MainPage()
        {
            this.InitializeComponent();
            numActiveContacts = 0;
            contacts = new Dictionary<uint, Windows.UI.Input.PointerPoint>((int)SupportedContacts.Contacts);
            startLocation = new Dictionary<uint, Point>((int)SupportedContacts.Contacts);
            pointSwiped = new Dictionary<uint, bool>((int)SupportedContacts.Contacts);
            targetContainer.PointerPressed += new PointerEventHandler(targetContainer_PointerPressed);
            targetContainer.PointerEntered += new PointerEventHandler(targetContainer_PointerEntered);
            targetContainer.PointerReleased += new PointerEventHandler(targetContainer_PointerReleased);
            targetContainer.PointerExited += new PointerEventHandler(targetContainer_PointerExited);
            targetContainer.PointerCanceled += new PointerEventHandler(targetContainer_PointerCanceled);
            targetContainer.PointerCaptureLost += new PointerEventHandler(targetContainer_PointerCaptureLost);
            targetContainer.PointerMoved += new PointerEventHandler(targetContainer_PointerMoved);
        }

        // PointerPressed and PointerReleased events do not always occur in pairs. 
        // Your app should listen for and handle any event that might conclude a pointer down action 
        // (such as PointerExited, PointerCanceled, and PointerCaptureLost).
        void targetContainer_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            if (Convert.ToBoolean(SupportedContacts.TouchPresent) && (numActiveContacts > SupportedContacts.Contacts))
            {
                // cannot support more contacts
                eventLog.Text += "\nNumber of contacts exceeds the number supported by the device.";
                return;
            }

            Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);

            // Update event sequence.
            eventLog.Text += "\nDown: " + pt.PointerId;

            // Change background color of target when pointer contact detected.
            targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Green);

            // Check if pointer already exists (if enter occurred prior to down).
            if (contacts.ContainsKey(pt.PointerId))
            {
                return;
            }
            contacts[pt.PointerId] = pt;
            startLocation[pt.PointerId] = pt.Position;
            pointSwiped[pt.PointerId] = false;
            ++numActiveContacts;
            e.Handled = true;

            // Display pointer details.
            createInfoPop(e);
        }

        private void targetContainer_PointerEntered(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);

            // Update event sequence.
            eventLog.Text += "\nOver: " + pt.PointerId;

            if (contacts.Count == 0)
            {
                // Change background color of target when pointer contact detected.
                targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Blue);
            }

            // Check if pointer already exists (if enter occurred prior to down).
            if (contacts.ContainsKey(pt.PointerId))
            {
                return;
            }

            // Push new pointer Id onto expando target pointers array.
            contacts[pt.PointerId] = pt;
            startLocation[pt.PointerId] = pt.Position;
            pointSwiped[pt.PointerId] = false;
            ++numActiveContacts;
            e.Handled = true;

            // Display pointer details.
            createInfoPop(e);
        }

        // Fires for for various reasons, including: 
        //    - User interactions
        //    - Programmatic caputre of another pointer
        //    - Captured pointer was deliberately released
        // PointerCaptureLost can fire instead of PointerReleased. 
        private void targetContainer_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);

            // Update event sequence.
            eventLog.Text += "\nPointer capture lost: " + pt.PointerId;

            if (contacts.ContainsKey(pt.PointerId))
            {
                checkSwipe();
                contacts[pt.PointerId] = null;
                contacts.Remove(pt.PointerId);
                startLocation.Remove(pt.PointerId);
                if (pointSwiped.ContainsKey(pt.PointerId))
                    pointSwiped.Remove(pt.PointerId);

                --numActiveContacts;
            }

            // Update the UI and pointer details.
            foreach (TextBlock tb in pointerInfo.Children)
            {
                if (tb.Name == e.Pointer.PointerId.ToString())
                {
                    pointerInfo.Children.Remove(tb);
                }
            }

            if (contacts.Count == 0)
            {
                targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Black);
            }

            e.Handled = true;
        }

        // Fires for for various reasons, including: 
        //    - A touch contact is canceled by a pen coming into range of the surface.
        //    - The device doesn't report an active contact for more than 100ms.
        //    - The desktop is locked or the user logged off. 
        //    - The number of simultaneous contacts exceeded the number supported by the device.
        private void targetContainer_PointerCanceled(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);

            // Update event sequence.
            eventLog.Text += "\nPointer canceled: " + pt.PointerId;

            if (contacts.ContainsKey(pt.PointerId))
            {
                checkSwipe();
                contacts[pt.PointerId] = null;
                contacts.Remove(pt.PointerId);
                startLocation.Remove(pt.PointerId);
                if (pointSwiped.ContainsKey(pt.PointerId))
                    pointSwiped.Remove(pt.PointerId);

                --numActiveContacts;
            }

            // Update the UI and pointer details.
            foreach (TextBlock tb in pointerInfo.Children)
            {
                if (tb.Name == e.Pointer.PointerId.ToString())
                {
                    pointerInfo.Children.Remove(tb);
                }
            }

            if (contacts.Count == 0)
            {
                targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Black);
            }

            e.Handled = true;
        }

        private void targetContainer_PointerExited(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);

            // Update event sequence.
            eventLog.Text += "\nPointer exited: " + pt.PointerId;

            if (contacts.ContainsKey(pt.PointerId))
            {
                checkSwipe();
                contacts[pt.PointerId] = null;
                contacts.Remove(pt.PointerId);
                startLocation.Remove(pt.PointerId);
                if (pointSwiped.ContainsKey(pt.PointerId))
                    pointSwiped.Remove(pt.PointerId);

                --numActiveContacts;
            }

            // Update the UI and pointer details.
            foreach (TextBlock tb in pointerInfo.Children)
            {
                if (tb.Name == e.Pointer.PointerId.ToString())
                {
                    pointerInfo.Children.Remove(tb);
                }
            }

            if (contacts.Count == 0)
            {
                targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Gray);

            }
            e.Handled = true;
        }

        /// <summary>
        /// Invoked when this page is about to be displayed in a Frame.
        /// </summary>
        /// <param name="e">Event data that describes how this page was reached.  The Parameter
        /// property is typically used to configure the page.</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }

        void targetContainer_PointerReleased(object sender, PointerRoutedEventArgs e)
        {
            foreach (TextBlock tb in pointerInfo.Children)
            {
                if (tb.Name == e.Pointer.PointerId.ToString())
                {
                    pointerInfo.Children.Remove(tb);
                }
            }

            Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);

            // Update event sequence.
            eventLog.Text += "\nUp: " + pt.PointerId;

            // Change background color of target when pointer contact detected.
            targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Red);

            if (contacts.ContainsKey(pt.PointerId))
            {
                checkSwipe();
                contacts[pt.PointerId] = null;
                contacts.Remove(pt.PointerId);
                startLocation.Remove(pt.PointerId);
                if(pointSwiped.ContainsKey(pt.PointerId))
                    pointSwiped.Remove(pt.PointerId);

                --numActiveContacts;
            }
            e.Handled = true;
        }

        private void targetContainer_PointerMoved(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(targetContainer);
            if (currentPoint.IsInContact)
            {
                if (startLocation.ContainsKey(currentPoint.PointerId))
                {
                    Point startPoint = startLocation[currentPoint.PointerId];
                    if (Math.Abs(currentPoint.Position.X - startPoint.X) > swipeThresholdX) // I only did one Axis for testing
                    {
                        pointSwiped[currentPoint.PointerId] = true;
                    }
                }

            }
            updateInfoPop(e);
        }

        int numberOfSwipedFingers()
        {
            int count = 0;
            foreach (var item in pointSwiped)
            {
                if (item.Value) { count += 1; }
            }
            return count;
        }

        void checkSwipe()
        {
            int fingers = numberOfSwipedFingers();
            if (fingers > 1)
            {
                eventLog.Text += "\nNumber of Swiped fingers = " + fingers;
            }
            else if (fingers == 1)
            {
                eventLog.Text += "\nNumber of Swiped fingers = " + fingers;
            }
            if(fingers > 0)
                pointSwiped.Clear();
        }            

        void createInfoPop(PointerRoutedEventArgs e)
        {
            Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(targetContainer);
            TextBlock pointerDetails = new TextBlock();
            pointerDetails.Name = currentPoint.PointerId.ToString();
            pointerDetails.Foreground = new SolidColorBrush(Windows.UI.Colors.White);
            pointerInfo.Children.Add(pointerDetails);
            pointerDetails.Text = queryPointer(e);
        }

        void updateInfoPop(PointerRoutedEventArgs e)
        {
            foreach (TextBlock pointerDetails in pointerInfo.Children)
            {
                if (pointerDetails.Name == e.Pointer.PointerId.ToString())
                {
                    pointerDetails.Text = queryPointer(e);
                }
            }
        }

        String queryPointer(PointerRoutedEventArgs e)
        {
            Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(targetContainer);
            String details = "";
            switch (e.Pointer.PointerDeviceType)
            {
                case Windows.Devices.Input.PointerDeviceType.Mouse:
                    details += "\nPointer type: mouse";
                    break;
                case Windows.Devices.Input.PointerDeviceType.Pen:
                    details += "\nPointer type: pen";
                    if (e.Pointer.IsInContact)
                    {
                        details += "\nPressure: " + currentPoint.Properties.Pressure;
                        details += "\nrotation: " + currentPoint.Properties.Orientation;
                        details += "\nTilt X: " + currentPoint.Properties.XTilt;
                        details += "\nTilt Y: " + currentPoint.Properties.YTilt;
                        details += "\nBarrel button pressed: " + currentPoint.Properties.IsBarrelButtonPressed;
                    }
                    break;
                case Windows.Devices.Input.PointerDeviceType.Touch:
                    details += "\nPointer type: touch";
                    details += "\nrotation: " + currentPoint.Properties.Orientation;
                    details += "\nTilt X: " + currentPoint.Properties.XTilt;
                    details += "\nTilt Y: " + currentPoint.Properties.YTilt;
                    break;
                default:
                    details += "\nPointer type: n/a";
                    break;
            }

            GeneralTransform gt = targetContainer.TransformToVisual(page);
            Point screenPoint;

            screenPoint = gt.TransformPoint(new Point(currentPoint.Position.X, currentPoint.Position.Y));
            details += "\nPointer Id: " + currentPoint.PointerId.ToString() +
                "\nPointer location (parent): " + currentPoint.Position.X + ", " + currentPoint.Position.Y +
                "\nPointer location (screen): " + screenPoint.X + ", " + screenPoint.Y;
            return details;
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用Windows基金会;
使用Windows。
使用Windows.UI.Xaml;
使用Windows.UI.Xaml.Controls;
使用Windows.UI.Xaml.Controls.Primitives;
使用Windows.UI.Xaml.Data;
使用Windows.UI.Xaml.Input;
使用Windows.UI.Xaml.Media;
使用Windows.UI.Xaml.Navigation;
//空白页项模板被记录在http://go.microsoft.com/fwlink/?LinkId=234238
命名空间指针输入
{
/// 
///可以单独使用或在框架内导航到的空页。
/// 
公共密封部分类主页面:第页
{
Windows.Devices.Input.TouchCapabilities SupportedContacts=新的Windows.Devices.Input.TouchCapabilities();
uint numActiveContacts;
字典联系人;
词典定位;
偷字典;
int swipeThresholdX=100;
int swipeThresholdY=100;
公共主页()
{
this.InitializeComponent();
numActiveContacts=0;
联系人=新字典((int)SupportedContacts.contacts);
startLocation=新字典((int)SupportedContacts.Contacts);
pointSwiped=新字典((int)SupportedContacts.Contacts);
targetContainer.PointerPressed+=新的PointerEventHandler(targetContainer\u PointerPressed);
targetContainer.PointerEntered+=新的PointerEventHandler(targetContainer\u PointerEntered);
targetContainer.PointerReleased+=新的PointerEventHandler(targetContainer\u PointerReleased);
targetContainer.PointerExited+=新的PointerEventHandler(targetContainer\u PointerExited);
targetContainer.PointerCanceled+=新的PointerEventHandler(targetContainer\u PointerCanceled);
targetContainer.PointerCaptureLost+=新的PointerEventHandler(targetContainer\u PointerCaptureLost);
targetContainer.PointerMoved+=新的PointerEventHandler(targetContainer\u PointerMoved);
}
//PointerPressed和PointerReleased事件并不总是成对发生。
//你的应用程序应该监听并处理任何可能导致指针向下移动的事件
//(例如PointerExit、PointerCanceled和PointerCaptureLost)。
void targetContainer_PointerPressed(对象发送方,PointerRoutedEventArgs e)
{
if(Convert.ToBoolean(SupportedContacts.TouchPresent)和&(numativeContacts>SupportedContacts.Contacts))
{
//无法支持更多联系人
eventLog.Text+=“\n联系人数量超过设备支持的数量。”;
返回;
}
Windows.UI.Input.PointerPoint pt=e.GetCurrentPoint(targetContainer);
//更新事件序列。
eventLog.Text+=“\n下拉:”+pt.PointerId;
//检测到指针接触时更改目标的背景色。
targetContainer.Fill=新的SolidColorBrush(Windows.UI.Colors.Green);
//检查指针是否已经存在(如果enter出现在down之前)。
if(contacts.ContainsKey(pt.PointerId))
{
返回;
}
触点[pt.PointerId]=pt;
起始位置[pt.指针ID]=pt.位置;
PointSwipped[pt.PointerId]=假;
++numActiveContacts;
e、 已处理=正确;
//显示指针详细信息。
创建InfoPop(e);
}
私有void targetContainer_PointerEntered(对象发送方,PointerRoutedEventArgs e)
{
Windows.UI.Input.PointerPoint pt=e.GetCurrentPoint(targetContainer);
//更新事件序列。
eventLog.Text+=“\nOver:”+pt.PointerId;
如果(contacts.Count==0)
{
//检测到指针接触时更改目标的背景色。
targetContainer.Fill=新的SolidColorBrush(Windows.UI.Colors.Blue);
}
//检查指针是否已经存在(如果enter出现在down之前)。
if(contacts.ContainsKey(pt.PointerId))
{
返回;
}
//将新指针Id推送到expando目标指针数组上。
触点[pt.PointerId]=pt;
起始位置[pt.指针ID]=pt.位置;
PointSwipped[pt.PointerId]=假;
++numActiveContacts;
e、 已处理=正确;
//显示指针详细信息。
创建InfoPop(e);
}
//冷杉
private void targetContainer_PointerMoved(object sender, PointerRoutedEventArgs e)
{
    Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(targetContainer);
    if (currentPoint.IsInContact)
    {
        if (startLocation.ContainsKey(currentPoint.PointerId))
        {
            Point startPoint = startLocation[currentPoint.PointerId];
            if (Math.Abs(currentPoint.Position.X - startPoint.X) > swipeThresholdX) // I only did one Axis for testing
            {
                pointSwiped[currentPoint.PointerId] = true;
            }
        }
    }
    updateInfoPop(e);
}               
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace PointerInput
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        Windows.Devices.Input.TouchCapabilities SupportedContacts = new Windows.Devices.Input.TouchCapabilities();

        uint numActiveContacts;
        Dictionary<uint, Windows.UI.Input.PointerPoint> contacts;
        Dictionary<uint, Point> startLocation;
        Dictionary<uint, bool> pointSwiped;
        int swipeThresholdX = 100;
        int swipeThresholdY = 100;

        public MainPage()
        {
            this.InitializeComponent();
            numActiveContacts = 0;
            contacts = new Dictionary<uint, Windows.UI.Input.PointerPoint>((int)SupportedContacts.Contacts);
            startLocation = new Dictionary<uint, Point>((int)SupportedContacts.Contacts);
            pointSwiped = new Dictionary<uint, bool>((int)SupportedContacts.Contacts);
            targetContainer.PointerPressed += new PointerEventHandler(targetContainer_PointerPressed);
            targetContainer.PointerEntered += new PointerEventHandler(targetContainer_PointerEntered);
            targetContainer.PointerReleased += new PointerEventHandler(targetContainer_PointerReleased);
            targetContainer.PointerExited += new PointerEventHandler(targetContainer_PointerExited);
            targetContainer.PointerCanceled += new PointerEventHandler(targetContainer_PointerCanceled);
            targetContainer.PointerCaptureLost += new PointerEventHandler(targetContainer_PointerCaptureLost);
            targetContainer.PointerMoved += new PointerEventHandler(targetContainer_PointerMoved);
        }

        // PointerPressed and PointerReleased events do not always occur in pairs. 
        // Your app should listen for and handle any event that might conclude a pointer down action 
        // (such as PointerExited, PointerCanceled, and PointerCaptureLost).
        void targetContainer_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            if (Convert.ToBoolean(SupportedContacts.TouchPresent) && (numActiveContacts > SupportedContacts.Contacts))
            {
                // cannot support more contacts
                eventLog.Text += "\nNumber of contacts exceeds the number supported by the device.";
                return;
            }

            Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);

            // Update event sequence.
            eventLog.Text += "\nDown: " + pt.PointerId;

            // Change background color of target when pointer contact detected.
            targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Green);

            // Check if pointer already exists (if enter occurred prior to down).
            if (contacts.ContainsKey(pt.PointerId))
            {
                return;
            }
            contacts[pt.PointerId] = pt;
            startLocation[pt.PointerId] = pt.Position;
            pointSwiped[pt.PointerId] = false;
            ++numActiveContacts;
            e.Handled = true;

            // Display pointer details.
            createInfoPop(e);
        }

        private void targetContainer_PointerEntered(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);

            // Update event sequence.
            eventLog.Text += "\nOver: " + pt.PointerId;

            if (contacts.Count == 0)
            {
                // Change background color of target when pointer contact detected.
                targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Blue);
            }

            // Check if pointer already exists (if enter occurred prior to down).
            if (contacts.ContainsKey(pt.PointerId))
            {
                return;
            }

            // Push new pointer Id onto expando target pointers array.
            contacts[pt.PointerId] = pt;
            startLocation[pt.PointerId] = pt.Position;
            pointSwiped[pt.PointerId] = false;
            ++numActiveContacts;
            e.Handled = true;

            // Display pointer details.
            createInfoPop(e);
        }

        // Fires for for various reasons, including: 
        //    - User interactions
        //    - Programmatic caputre of another pointer
        //    - Captured pointer was deliberately released
        // PointerCaptureLost can fire instead of PointerReleased. 
        private void targetContainer_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);

            // Update event sequence.
            eventLog.Text += "\nPointer capture lost: " + pt.PointerId;

            if (contacts.ContainsKey(pt.PointerId))
            {
                checkSwipe();
                contacts[pt.PointerId] = null;
                contacts.Remove(pt.PointerId);
                startLocation.Remove(pt.PointerId);
                if (pointSwiped.ContainsKey(pt.PointerId))
                    pointSwiped.Remove(pt.PointerId);

                --numActiveContacts;
            }

            // Update the UI and pointer details.
            foreach (TextBlock tb in pointerInfo.Children)
            {
                if (tb.Name == e.Pointer.PointerId.ToString())
                {
                    pointerInfo.Children.Remove(tb);
                }
            }

            if (contacts.Count == 0)
            {
                targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Black);
            }

            e.Handled = true;
        }

        // Fires for for various reasons, including: 
        //    - A touch contact is canceled by a pen coming into range of the surface.
        //    - The device doesn't report an active contact for more than 100ms.
        //    - The desktop is locked or the user logged off. 
        //    - The number of simultaneous contacts exceeded the number supported by the device.
        private void targetContainer_PointerCanceled(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);

            // Update event sequence.
            eventLog.Text += "\nPointer canceled: " + pt.PointerId;

            if (contacts.ContainsKey(pt.PointerId))
            {
                checkSwipe();
                contacts[pt.PointerId] = null;
                contacts.Remove(pt.PointerId);
                startLocation.Remove(pt.PointerId);
                if (pointSwiped.ContainsKey(pt.PointerId))
                    pointSwiped.Remove(pt.PointerId);

                --numActiveContacts;
            }

            // Update the UI and pointer details.
            foreach (TextBlock tb in pointerInfo.Children)
            {
                if (tb.Name == e.Pointer.PointerId.ToString())
                {
                    pointerInfo.Children.Remove(tb);
                }
            }

            if (contacts.Count == 0)
            {
                targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Black);
            }

            e.Handled = true;
        }

        private void targetContainer_PointerExited(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);

            // Update event sequence.
            eventLog.Text += "\nPointer exited: " + pt.PointerId;

            if (contacts.ContainsKey(pt.PointerId))
            {
                checkSwipe();
                contacts[pt.PointerId] = null;
                contacts.Remove(pt.PointerId);
                startLocation.Remove(pt.PointerId);
                if (pointSwiped.ContainsKey(pt.PointerId))
                    pointSwiped.Remove(pt.PointerId);

                --numActiveContacts;
            }

            // Update the UI and pointer details.
            foreach (TextBlock tb in pointerInfo.Children)
            {
                if (tb.Name == e.Pointer.PointerId.ToString())
                {
                    pointerInfo.Children.Remove(tb);
                }
            }

            if (contacts.Count == 0)
            {
                targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Gray);

            }
            e.Handled = true;
        }

        /// <summary>
        /// Invoked when this page is about to be displayed in a Frame.
        /// </summary>
        /// <param name="e">Event data that describes how this page was reached.  The Parameter
        /// property is typically used to configure the page.</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }

        void targetContainer_PointerReleased(object sender, PointerRoutedEventArgs e)
        {
            foreach (TextBlock tb in pointerInfo.Children)
            {
                if (tb.Name == e.Pointer.PointerId.ToString())
                {
                    pointerInfo.Children.Remove(tb);
                }
            }

            Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(targetContainer);

            // Update event sequence.
            eventLog.Text += "\nUp: " + pt.PointerId;

            // Change background color of target when pointer contact detected.
            targetContainer.Fill = new SolidColorBrush(Windows.UI.Colors.Red);

            if (contacts.ContainsKey(pt.PointerId))
            {
                checkSwipe();
                contacts[pt.PointerId] = null;
                contacts.Remove(pt.PointerId);
                startLocation.Remove(pt.PointerId);
                if(pointSwiped.ContainsKey(pt.PointerId))
                    pointSwiped.Remove(pt.PointerId);

                --numActiveContacts;
            }
            e.Handled = true;
        }

        private void targetContainer_PointerMoved(object sender, PointerRoutedEventArgs e)
        {
            Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(targetContainer);
            if (currentPoint.IsInContact)
            {
                if (startLocation.ContainsKey(currentPoint.PointerId))
                {
                    Point startPoint = startLocation[currentPoint.PointerId];
                    if (Math.Abs(currentPoint.Position.X - startPoint.X) > swipeThresholdX) // I only did one Axis for testing
                    {
                        pointSwiped[currentPoint.PointerId] = true;
                    }
                }

            }
            updateInfoPop(e);
        }

        int numberOfSwipedFingers()
        {
            int count = 0;
            foreach (var item in pointSwiped)
            {
                if (item.Value) { count += 1; }
            }
            return count;
        }

        void checkSwipe()
        {
            int fingers = numberOfSwipedFingers();
            if (fingers > 1)
            {
                eventLog.Text += "\nNumber of Swiped fingers = " + fingers;
            }
            else if (fingers == 1)
            {
                eventLog.Text += "\nNumber of Swiped fingers = " + fingers;
            }
            if(fingers > 0)
                pointSwiped.Clear();
        }            

        void createInfoPop(PointerRoutedEventArgs e)
        {
            Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(targetContainer);
            TextBlock pointerDetails = new TextBlock();
            pointerDetails.Name = currentPoint.PointerId.ToString();
            pointerDetails.Foreground = new SolidColorBrush(Windows.UI.Colors.White);
            pointerInfo.Children.Add(pointerDetails);
            pointerDetails.Text = queryPointer(e);
        }

        void updateInfoPop(PointerRoutedEventArgs e)
        {
            foreach (TextBlock pointerDetails in pointerInfo.Children)
            {
                if (pointerDetails.Name == e.Pointer.PointerId.ToString())
                {
                    pointerDetails.Text = queryPointer(e);
                }
            }
        }

        String queryPointer(PointerRoutedEventArgs e)
        {
            Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(targetContainer);
            String details = "";
            switch (e.Pointer.PointerDeviceType)
            {
                case Windows.Devices.Input.PointerDeviceType.Mouse:
                    details += "\nPointer type: mouse";
                    break;
                case Windows.Devices.Input.PointerDeviceType.Pen:
                    details += "\nPointer type: pen";
                    if (e.Pointer.IsInContact)
                    {
                        details += "\nPressure: " + currentPoint.Properties.Pressure;
                        details += "\nrotation: " + currentPoint.Properties.Orientation;
                        details += "\nTilt X: " + currentPoint.Properties.XTilt;
                        details += "\nTilt Y: " + currentPoint.Properties.YTilt;
                        details += "\nBarrel button pressed: " + currentPoint.Properties.IsBarrelButtonPressed;
                    }
                    break;
                case Windows.Devices.Input.PointerDeviceType.Touch:
                    details += "\nPointer type: touch";
                    details += "\nrotation: " + currentPoint.Properties.Orientation;
                    details += "\nTilt X: " + currentPoint.Properties.XTilt;
                    details += "\nTilt Y: " + currentPoint.Properties.YTilt;
                    break;
                default:
                    details += "\nPointer type: n/a";
                    break;
            }

            GeneralTransform gt = targetContainer.TransformToVisual(page);
            Point screenPoint;

            screenPoint = gt.TransformPoint(new Point(currentPoint.Position.X, currentPoint.Position.Y));
            details += "\nPointer Id: " + currentPoint.PointerId.ToString() +
                "\nPointer location (parent): " + currentPoint.Position.X + ", " + currentPoint.Position.Y +
                "\nPointer location (screen): " + screenPoint.X + ", " + screenPoint.Y;
            return details;
        }
    }
}
public enum DirectionSwiped
{
    None,
    Up,
    Down,
    Left,
    Right
}


public class SwipeEventArgs : EventArgs
{
    public DirectionSwiped Direction { get; set; }
    public int NumberOfTouches { get; set; }
}


public class SwipeGestureDetector
{
    public EventHandler<SwipeEventArgs> SwipeDetected;




    // How much of the grid needs to be covered by the swipe?
    private const double SWIPE_THRESHOLD = 0.5;

    // How much drift is allowed in the opposite axis?
    private const int ALLOWED_DRIFT = 100;

    Windows.Devices.Input.TouchCapabilities SupportedContacts = new Windows.Devices.Input.TouchCapabilities();

    uint numActiveContacts;
    Dictionary<uint, Windows.UI.Input.PointerPoint> contacts;
    Dictionary<uint, Point> startLocation;
    Dictionary<uint, DirectionSwiped> pointSwiped;

    private Grid mGrid;





    public SwipeGestureDetector(Grid grid)
    {
        mGrid = grid;

        numActiveContacts = 0;
        contacts = new Dictionary<uint, Windows.UI.Input.PointerPoint>((int)SupportedContacts.Contacts);
        startLocation = new Dictionary<uint, Point>((int)SupportedContacts.Contacts);
        pointSwiped = new Dictionary<uint, DirectionSwiped>((int)SupportedContacts.Contacts);
        grid.PointerPressed += new PointerEventHandler(Grid_PointerPressed);
        grid.PointerEntered += new PointerEventHandler(Grid_PointerEntered);
        grid.PointerReleased += new PointerEventHandler(Grid_PointerReleased);
        grid.PointerExited += new PointerEventHandler(Grid_PointerExited);
        grid.PointerCanceled += new PointerEventHandler(Grid_PointerCanceled);
        grid.PointerCaptureLost += new PointerEventHandler(Grid_PointerCaptureLost);
        grid.PointerMoved += new PointerEventHandler(Grid_PointerMoved);
    }





    // PointerPressed and PointerReleased events do not always occur in pairs. 
    // Your app should listen for and handle any event that might conclude a pointer down action 
    // (such as PointerExited, PointerCanceled, and PointerCaptureLost).
    void Grid_PointerPressed(object sender, PointerRoutedEventArgs e)
    {
        if (Convert.ToBoolean(SupportedContacts.TouchPresent) && (numActiveContacts > SupportedContacts.Contacts))
        {
            // cannot support more contacts
            Debug.WriteLine("\nNumber of contacts exceeds the number supported by the device.");
            return;
        }

        Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(mGrid);

        // Check if pointer already exists (if enter occurred prior to down).
        if (contacts.ContainsKey(pt.PointerId))
        {
            return;
        }
        contacts[pt.PointerId] = pt;
        startLocation[pt.PointerId] = pt.Position;
        pointSwiped[pt.PointerId] = DirectionSwiped.None;
        ++numActiveContacts;
        e.Handled = true;
    }


    private void Grid_PointerEntered(object sender, PointerRoutedEventArgs e)
    {
        Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(mGrid);

        // Check if pointer already exists (if enter occurred prior to down).
        if (contacts.ContainsKey(pt.PointerId))
        {
            return;
        }

        // Push new pointer Id onto expando target pointers array.
        contacts[pt.PointerId] = pt;
        startLocation[pt.PointerId] = pt.Position;
        pointSwiped[pt.PointerId] = DirectionSwiped.None;
        ++numActiveContacts;
        e.Handled = true;

    }


    // Fires for for various reasons, including: 
    //    - User interactions
    //    - Programmatic caputre of another pointer
    //    - Captured pointer was deliberately released
    // PointerCaptureLost can fire instead of PointerReleased. 
    private void Grid_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
    {
        Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(mGrid);

        if (contacts.ContainsKey(pt.PointerId))
        {
            checkSwipe();
            contacts[pt.PointerId] = null;
            contacts.Remove(pt.PointerId);
            startLocation.Remove(pt.PointerId);
            if (pointSwiped.ContainsKey(pt.PointerId))
                pointSwiped.Remove(pt.PointerId);

            --numActiveContacts;
        }

        e.Handled = true;
    }


    // Fires for for various reasons, including: 
    //    - A touch contact is canceled by a pen coming into range of the surface.
    //    - The device doesn't report an active contact for more than 100ms.
    //    - The desktop is locked or the user logged off. 
    //    - The number of simultaneous contacts exceeded the number supported by the device.
    private void Grid_PointerCanceled(object sender, PointerRoutedEventArgs e)
    {
        Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(mGrid);

        if (contacts.ContainsKey(pt.PointerId))
        {
            checkSwipe();
            contacts[pt.PointerId] = null;
            contacts.Remove(pt.PointerId);
            startLocation.Remove(pt.PointerId);
            if (pointSwiped.ContainsKey(pt.PointerId))
                pointSwiped.Remove(pt.PointerId);

            --numActiveContacts;
        }

        e.Handled = true;
    }


    private void Grid_PointerExited(object sender, PointerRoutedEventArgs e)
    {
        Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(mGrid);

        if (contacts.ContainsKey(pt.PointerId))
        {
            checkSwipe();
            contacts[pt.PointerId] = null;
            contacts.Remove(pt.PointerId);
            startLocation.Remove(pt.PointerId);
            if (pointSwiped.ContainsKey(pt.PointerId))
                pointSwiped.Remove(pt.PointerId);

            --numActiveContacts;
        }
        e.Handled = true;
    }



    void Grid_PointerReleased(object sender, PointerRoutedEventArgs e)
    {
        Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(mGrid);

        if (contacts.ContainsKey(pt.PointerId))
        {
            checkSwipe();
            contacts[pt.PointerId] = null;
            contacts.Remove(pt.PointerId);
            startLocation.Remove(pt.PointerId);
            if (pointSwiped.ContainsKey(pt.PointerId))
                pointSwiped.Remove(pt.PointerId);

            --numActiveContacts;
        }
        e.Handled = true;
    }


    private void Grid_PointerMoved(object sender, PointerRoutedEventArgs e)
    {
        Windows.UI.Input.PointerPoint currentPoint = e.GetCurrentPoint(mGrid);
        if (currentPoint.IsInContact)
        {
            if (startLocation.ContainsKey(currentPoint.PointerId))
            {
                Point startPoint = startLocation[currentPoint.PointerId];

                // Compare startPoint to current location and determine if that point did a swipe?

                double horizontalMovement = currentPoint.Position.X - startPoint.X;
                double verticalMovement = currentPoint.Position.Y - startPoint.Y;

                double horizontalDistance = Math.Abs(horizontalMovement);
                double verticalDistance = Math.Abs(verticalMovement);

                double requiredLeftMovement = mGrid.ActualWidth * SWIPE_THRESHOLD * -1;
                double requiredRightMovement = mGrid.ActualWidth * SWIPE_THRESHOLD;

                double requiredUpMovement = mGrid.ActualHeight * SWIPE_THRESHOLD * -1;
                double requiredDownMovement = mGrid.ActualHeight * SWIPE_THRESHOLD;

                if (verticalMovement < requiredUpMovement && horizontalDistance < 100)
                {
                    pointSwiped[currentPoint.PointerId] = DirectionSwiped.Up;
                }
                else if (verticalMovement > requiredDownMovement && horizontalDistance < ALLOWED_DRIFT)
                {
                    pointSwiped[currentPoint.PointerId] = DirectionSwiped.Down;
                }
                else if (horizontalMovement > requiredRightMovement && verticalDistance < ALLOWED_DRIFT)
                {
                    pointSwiped[currentPoint.PointerId] = DirectionSwiped.Right;
                }
                else if (horizontalMovement < requiredLeftMovement && verticalDistance < ALLOWED_DRIFT)
                {
                    pointSwiped[currentPoint.PointerId] = DirectionSwiped.Left;
                }
            }
        }
    }





    void checkSwipe()
    {
        NotififyListenerIfSwiped(DirectionSwiped.Up);
        NotififyListenerIfSwiped(DirectionSwiped.Down);
        NotififyListenerIfSwiped(DirectionSwiped.Left);
        NotififyListenerIfSwiped(DirectionSwiped.Right);
    }


    private void NotififyListenerIfSwiped(DirectionSwiped direction)
    {
        int fingers = numberOfSwipedFingers(direction);
        if (fingers >= 1)
        {
            if (SwipeDetected != null)
            {
                SwipeDetected(this, new SwipeEventArgs() { Direction = direction, NumberOfTouches = fingers });
            }
        }

        if (fingers > 0)
            pointSwiped.Clear();
    }


    int numberOfSwipedFingers(DirectionSwiped direction)
    {
        int count = 0;
        foreach (var item in pointSwiped)
        {
            DirectionSwiped swipe = item.Value;
            if (swipe == direction)
            {
                count += 1;
            }
        }
        return count;
    }


}
    public void Gesture_Detected(Object sender, SwipeEventArgs e)
    {
        Debug.WriteLine("Number of touches: " + e.NumberOfTouches + " Direction: " + e.Direction);
    }


    public MainPage()
    {
        this.InitializeComponent();

        SwipeGestureDetector gestureDetector = new SwipeGestureDetector(this.rootGrid);
        gestureDetector.SwipeDetected += Gesture_Detected;