在 ScrollViewer UWP 中通过触摸拖动形状

Drag shape with touch inside a ScrollViewer UWP

我正在尝试在滚动查看器中拖动一个形状。 我的解决方案是在触摸形状时暂时禁用滚动查看器,然后在释放时重新启用。感觉有点hacky,但找不到更好的解决方案。有没有更好的推荐?

下面的 XAML 代码。

<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>

下面的 C# UWP 代码

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;
        }
    }
}

你几乎完成了,除了你应该禁用直接操作 ScrollViewer 而不是禁用滚动,并在完成后重新启用它。

private void OnPointerPressed(object sender, PointerRoutedEventArgs e)
{
    scrollViewer.CancelDirectManipulations();
}

private void OnPointerReleased(object sender, PointerRoutedEventArgs e)
{
    TryStartDirectManipulation(e.Pointer);
}