@AdamMcMahon 从您的帖子的声音中可以看出,您希望列表中的图像项目能够响应拖动触摸(PointerPressed),这本身可以通过连接列表视图项目模板来实现并且相当简单以下行:
<DataTemplate x:Key="ListViewItemTemplate1" x:DataType="x:String">
<Grid>
<Image Source="{x:Bind}" CanDrag="True" PointerPressed="Image_PointerPressed" DragStarting="Image_DragStarting" />
</Grid>
</DataTemplate>
并按照以下事件处理程序的方式添加一些内容
private async void Image_PointerPressed(object sender, PointerRoutedEventArgs e)
{
var image = sender as Image;
var pointerPoint = e.GetCurrentPoint(sender as UIElement);
var dropStatus = await image.StartDragAsync(pointerPoint);
}
private void Image_DragStarting(UIElement sender, DragStartingEventArgs args)
{
args.Data.Properties.Add("myKey", sender);
}
还有一个用于放置目标的处理程序,例如
private async void TargetImage_Drop(object sender, DragEventArgs e)
{
Image result = e.DataView.Properties["myKey"] as Image;
TargetImage.Source = result.Source;
}
但是,问题的核心是 scrollviewer 水平滚动和拖动操作相互干扰,您可能会在 PointerMoved 事件中尝试使用典型的解决方法来测试移动是水平还是垂直direction 实现起来并不简单,因为 ScrollViewer 会吞下大部分 PointerMoved 事件,如下所述:https://blogs.msdn.microsoft.com/wsdevsol/2013/02/15/where-did-all-my-gestures-go/
因此,根据用户体验,您最终可能会尝试断开拖动和滚动这两个用户交互。例如,您可以在列表视图的末端放置左右滚动按钮,为用户提供滚动列表的方式,并保留与列表视图的直接触摸交互以触发拖动操作。
如下代码可用于向左滚动
private void ScrollLeftButton_Click(object sender, RoutedEventArgs e)
{
Border border = VisualTreeHelper.GetChild(ImageListview, 0) as Border;
ScrollViewer scrollViewer = border.Child as ScrollViewer;
scrollViewer.HorizontalScrollMode = ScrollMode.Enabled;
scrollViewer.ChangeView(scrollViewer.HorizontalOffset + 100, null, null);
scrollViewer.HorizontalScrollMode = ScrollMode.Disabled;
}
另一个选项可能是引入两种交互模式,一个按钮可以打开和关闭滚动模式。
当scrollOn bool 为true 时,您不会在PointerPressed 上启动StartDrag,当它为false 时您会这样做。这将使用户既可以平滑滚动列表,也可以简单地从列表中拖动,但在任何给定时间点只能以一种或另一种方式工作。
也许根据您尝试为用户提供的特定体验,您可能会想出其他方法来为用户分离两种交互。
HTH。