ListView上的水平滚动

ng9*_*g93 2 c# xaml listview windows-runtime windows-phone-8.1

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

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

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

Rom*_*asz 5

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

开始吧:

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

  2. 为此,我们假设您已ListView使用VerticalScroll 定义了您的唯一内容:

    <ListView Name="myList" ScrollViewer.HorizontalScrollMode="Disabled">
    
    Run Code Online (Sandbox Code Playgroud)

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

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

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

    没有什么奇怪的在这里-我只是订阅事件,并宣布两个变量firstPointlistScrollviewer,我将在以后需要.

  4. 我们还需要得到我们ScrollViewerListView- 以下方法将完成这项工作:

    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;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. 现在 - 要启用我们的活动,我们需要禁用ScrollViewer:

    private ScrollViewer DisableScrolling(DependencyObject depObj)
    {
        ScrollViewer foundOne = GetScrollViewer(depObj);
        if (foundOne != null) foundOne.VerticalScrollMode = ScrollMode.Disabled;
        return foundOne;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  6. 我们将禁止ScrollViewerPointerEntered其被解雇的事件.在这一步中,我们还会记住按下PointerPoint- 因为我们已禁用Scrollviewer,我们将不得不手动滚动它 - 这就是我们需要它PointerPoint.

    private void myList_PointerEntered(object sender, PointerRoutedEventArgs e)
    {
        firstPoint = e.GetCurrentPoint(myList);
        if (listScrollviewer == null) listScrollviewer = DisableScrolling(myList);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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
    }
    
    Run Code Online (Sandbox Code Playgroud)

几句话:

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

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