【问题标题】:How to drag elements out of a scrollable ListView using touch, without having to hold on the element [UWP]如何使用触摸将元素拖出可滚动的 ListView,而无需按住元素 [UWP]
【发布时间】:2019-07-22 12:42:45
【问题描述】:

就目前而言,将元素 拖出 ListView 的功能意味着用户必须长按或“按住”该元素才能激活元素。

问题在于,我们的实时测试表明,这对于最终用户来说远非直观。

我遇到了this question,提出了一些有趣的想法,但 cmets 表示他们最终找不到解决方案,并且上一次关于它的活动是 3 年前。

也许有人在此期间找到了解决方案或解决方法?上下文是我目前使用ListView,因为它必须可以水平滚动,但我需要ListView 中的images 可以垂直拖动并与ListView 分离。

【问题讨论】:

  • 你有什么特殊需要来改变拖动行为?
  • 仅仅是因为我们的现场测试表明它不够直观。我想避免“长按”并允许用户简单地将元素垂直拖出 ListView
  • 你可以尝试在 Github 上提出 WinUI 的功能请求 - github.com/Microsoft/microsoft-ui-xaml - 一切都在公开中完成,你只需要等待下一个版本的库来使用它,其中包含你的修复

标签: c# xaml listview uwp touch


【解决方案1】:

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

【讨论】:

  • 是的,这几乎证实了我在提出这个问题之前所做的研究。也许是时候让我面对这不可能的事实了!就目前而言,我的 ListView 侧面有一个左右滚动按钮,它可以为我滚动,但它不适合我的应用程序的其余部分,因为我有许多不需要元素的 ListView从它们中拖出,因此使用 Scroll 作为标准可以正常工作。因此,只有一个不符合标准滚动行为的 ListView 似乎很奇怪且不直观。
  • 是的,我同意,一致性是良好交互设计的一个重要方面。也许需要拖动功能的列表视图的“切换模式”方法可能值得考虑,特别是如果拖动很容易在您的应用程序工作流程中作为可理解的“任务”传达给用户。从我过去在用户那里看到的情况来看,较旧的双滚动或粘性拉出拖动并不总是那么直观或容易被发现,并且经常需要向用户解释。
猜你喜欢
  • 1970-01-01
  • 2016-08-16
  • 1970-01-01
  • 1970-01-01
  • 2019-11-04
  • 1970-01-01
  • 1970-01-01
  • 2016-02-25
  • 2018-09-19
相关资源
最近更新 更多