ListView上的水平滚动

时间:2014-05-14 21:24:54

标签: c# xaml listview windows-runtime windows-phone-8.1

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

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

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

1 个答案:

答案 0 :(得分:5)

有可能,但你需要一个小技巧。作为参考,我在这里Rob Caplan's article

让我们开始吧:

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

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

    <ListView Name="myList" ScrollViewer.HorizontalScrollMode="Disabled">
    

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

  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. 我们还需要获取ScrollViewer的{​​{1}} - 以下方法可以完成此任务:

    ListView
  5. 现在 - 要启用我们的活动,我们需要停用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; }

    ScrollViewer
  6. 我们将在private ScrollViewer DisableScrolling(DependencyObject depObj) { ScrollViewer foundOne = GetScrollViewer(depObj); if (foundOne != null) foundOne.VerticalScrollMode = ScrollMode.Disabled; return foundOne; } 被触发的事件中停用ScrollViewer。在此步骤中,我们还会记住按下的PointerEntered - 因为我们已禁用PointerPoint,我们必须手动滚动它 - 这就是我们需要Scrollviewer

    PointerPoint
  7. 最后我们的private void myList_PointerEntered(object sender, PointerRoutedEventArgs e) { firstPoint = e.GetCurrentPoint(myList); if (listScrollviewer == null) listScrollviewer = DisableScrolling(myList); } 事件,现在因为我们已停用PointerMoved而被解雇 - 移动ScrollViewer +您需要放置的其他代码:

    ScrollViewer

  8. 几点评论:

    • 这种方法仍需要很多调整,但希望能告诉你如何实现目标,
    • 您可能还需要将一些小的水平移动与垂直移动分开,
    • 如果您的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那样顺畅地工作。

    我还提出了一个简单的工作示例here at OneDrive