Drag shape with touch inside a ScrollViewer UWP

Viewed 862

I am trying to drag a shape inside a scroll viewer. My solution was to temporarily disable the scroll viewer when touching the shape, then re-enabling when releasing. Feels a bit hacky, but couldn't find a better solution. Has anyone a better recommendation?

The XAML code below.

<Page
x:Class="testdragshape.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:testdragshape"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" Height="390.667">

<Grid>
    <ScrollViewer Name="scrollViewer" >
        <Grid Name="pageGrid">
            <TextBlock Name="log" Text="Position:"/>
            <Canvas Name="myCanvas" Width="500" Height="500">
                <Rectangle Name="myTarget"  Width="272" Height="272" Fill="Red" Canvas.Left="41" Canvas.Top="53" />
            </Canvas>
        </Grid>            
    </ScrollViewer>

</Grid>

The C# UWP code below

using Windows.Foundation;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;

namespace testdragshape
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            myCanvas.RenderTransform = new TranslateTransform();
            myTarget.PointerPressed += Target_PointerPressed;
            myTarget.PointerMoved += Target_PointerMoved;
            myTarget.PointerReleased += MyTarget_PointerReleased;
        }

        Point _drag0;
        private void Target_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            // disable the scroll mode
            scrollViewer.HorizontalScrollMode = ScrollMode.Disabled;
            scrollViewer.VerticalScrollMode = ScrollMode.Disabled;

            _drag0 = e.GetCurrentPoint(myCanvas).Position;
            log.Text = "Position - X: " + _drag0.X + " Y: " + _drag0.Y;
        }

        private void Target_PointerMoved(object sender, PointerRoutedEventArgs e)
        {
            if (!e.Pointer.IsInContact) return;

            var point = e.GetCurrentPoint(myCanvas).Position;
            var t = new Point(point.X - _drag0.X, point.Y - _drag0.Y);
            TranslateTransform previous = (TranslateTransform)myCanvas.RenderTransform;
            myCanvas.RenderTransform = new TranslateTransform()
            {
                X = previous.X + t.X,
                Y = previous.Y + t.Y
            };

            log.Text = "Position - X: " + point.X + " Y: " + point.Y;
        }

        private void MyTarget_PointerReleased(object sender, PointerRoutedEventArgs e)
        {
            // re-enable scroll mode
            scrollViewer.HorizontalScrollMode = ScrollMode.Auto;
            scrollViewer.VerticalScrollMode = ScrollMode.Auto;
        }
    }
}
1 Answers
Related