ListView上的水平滚动

我目前正在页面上捕获PointerMoved事件以使用水平菜单。 因此,用户可以向左/向右滑动,页面将相应地设置动画。

这在用户触摸静态元素(TextBlock等)时有效,但如果它们触摸ListView则会捕获触摸事件。

如何实现ListView,以便当用户垂直滚动时,它正常工作,但当用户水平滚动时,它会将事件传递给我的代码?

这是可能的,但你需要一个小技巧。 作为一个参考,我把Rob Caplan的文章放在这里。

开始吧:

  1. 首先 – 您的活动在哪里? – 答案很简单 – 当您启用ScrollViewer ,所有事件都会被它拦截并处理。 ListView将只获得PointerEntered事件,并且在PointerExited ,所有进一步的procprocing都由ScrollViewer处理。 那就是问题所在。 但正如我所说,有一种方法可以做你想要的。

  2. 为此,我们假设您仅使用VerticalScroll定义了ListView

      

    当然可以为两个方向做,但这是一个简单的例子。

  3. 现在让我们看一下Page构造函数:

     PointerPoint firstPoint = null; ScrollViewer listScrollviewer = null; public MainPage() { this.InitializeComponent(); myList.ItemsSource = yourItemSource; myList.PointerEntered += myList_PointerEntered; myList.PointerMoved += myList_PointerMoved; } 

    这里没什么奇怪的 – 我只是订阅了事件,并声明了两个变量firstPointlistScrollviewer ,我稍后会需要它们。

  4. 我们还需要获取ListViewScrollViewer – 以下方法将完成这项工作:

     public static ScrollViewer GetScrollViewer(DependencyObject depObj) { if (depObj is ScrollViewer) return depObj as ScrollViewer; for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) { var child = VisualTreeHelper.GetChild(depObj, i); var result = GetScrollViewer(child); if (result != null) return result; } return null; } 
  5. 现在 - 要启用我们的活动,我们需要禁用ScrollViewer

     private ScrollViewer DisableScrolling(DependencyObject depObj) { ScrollViewer foundOne = GetScrollViewer(depObj); if (foundOne != null) foundOne.VerticalScrollMode = ScrollMode.Disabled; return foundOne; } 
  6. 我们将在PointerEntered事件时禁用ScrollViewer 。 在这一步中,我们还会记住按下的PointerPoint - 因为我们禁用了Scrollviewer ,我们将不得不手动滚动它 - 这就是我们需要这个PointerPoint for。

     private void myList_PointerEntered(object sender, PointerRoutedEventArgs e) { firstPoint = e.GetCurrentPoint(myList); if (listScrollviewer == null) listScrollviewer = DisableScrolling(myList); } 
  7. 最后我们的PointerMoved事件,现在我们已经禁用了ScrollViewer - 移动ScrollViewer +你需要放置的其他代码:

     private void myList_PointerMoved(object sender, PointerRoutedEventArgs e) { if (listScrollviewer != null) { PointerPoint secondPoint = e.GetCurrentPoint(myList); double verticalDifference = secondPoint.Position.Y - firstPoint.Position.Y; listScrollviewer.ChangeView(null, listScrollviewer.VerticalOffset - verticalDifference, null); } // some other code you need } 

几句话:

  • 这种方法仍需要很多调整,但希望能告诉你如何实现目标,
  • 你可能还需要将一些小的水平运动与垂直运动分开,
  • 如果你的ListView或其他控件有水平滚动,那么你还需要禁用和处理它,
  • 这种方法可能不像原版ScrollViewer那样顺畅。

我还在OneDrive上放了一个简单的工作示例。