Udostępnij za pośrednictwem


A word on WPF4 manipulations.

You may be able to perform most of your manipulation needs by using the manipulation related members WPF4 added to UIElement (IsManipulationEnabled property  and events such as ManipulationStarting, ManipulationDelta and ManipulationCompled). This walkthrough is a great resource if you are new to manipulations.

There are times when you may want to do something a bit more complicated. For instance, you may want to decide what types of input will actually influence the manipulators, instead of allowing all input devices to manipulate an object. For instance you may want fingers to manipulate while tags and blobs perform some other action. For these situations you can use the Manipulation class.

That said, one of the developers in the Microsoft® Surface® team told me about something that is not very clear from just reading the documentation. So we decided to share the pattern with you.The issue is that Manipulation.IsManipulationActive(element) may return false even before all manipulator has been removed from the Manipulation. In order to prevent our manipulation from having a lingering manipulator, we track the
active touch devices ourselves.

#region manipulation related events.

// We are assuming a UIElement with the name of element is the one being
// manipulated. 

// We are using this list in order to make sure we don't leave any manipulators
// lingering behind.

private readonly IList<int> activeTouchDevices = new List<int>();

private void OnTouchDown(object sender, TouchEventArgs e)
{
    if (e.TouchDevice.Capture(element))
    {
        e.Handled = true;
    }
}

 

private void OnGotTouchCapture(object sender, TouchEventArgs e)
{
   if (e.TouchDevice.Captured == element)
   {
        Manipulation.AddManipulator(element, e.TouchDevice.AsManipulator());
        activeTouchDevices.Add(e.TouchDevice.Id);
        e.Handled = true;
    }
}

private void OnTouchUp(object sender, TouchEventArgs e)
{
    if (e.TouchDevice.Captured == element)
    {
        if (e.TouchDevice.Capture(null)) // manipulator will be removed by LostTouchCapture
        {
            e.Handled = true;
        } 

        // complete manipulation.
    }
}

 

private void OnLostTouchCapture(object sender, TouchEventArgs e)
{
    if (e.OriginalSource == element)
    {
        if (activeTouchDevices.Remove(e.TouchDevice.Id))

        // In this line Manipulation.IsManipulationActive(element) may
        // be false even when there are elements that have not been
        // removed from the manipulation
        {
            Manipulation.RemoveManipulator(element, 
                         e.TouchDevice.AsManipulator());
        }

        e.Handled = true;
    }
}

#endregion

I hope you find this helpful!

Comments

  • Anonymous
    March 29, 2012
    Hi , First of all thank u for sharing your experience. I try to create a dragable object on surfaceScrollViewer so when i use element.onleftmousedown it works perfectly but sometimes it does not listen mouse event because it listen touch events. than i try to google it i found your side and try to drag with manipulation but it does not find Manipulation.AddManipulator(sender as Image, e.TouchDevice.AsManipulator()); Asmanipulator(), can you help me thank you