2014-05-14 144 views
2

我目前正在捕获页面上的PointerMoved事件以便与水平菜单一起使用。所以用户可以向左/向右滑动,页面会相应地生成动画。ListView上的水平滚动

这适用于用户触摸静态元素(TextBlock等),但如果他们触摸ListView它捕捉触摸事件。

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

回答

5

这是可能的,但你需要一个小窍门。作为参考,我把这里放在Rob Caplan's article

让我们开始:

  1. 第一 - 在那里是你的事件? - 回答很简单 - 当你有ScrollViewer启用时,所有的事件都会被拦截并处理。您ListView将只获得PointerEntered事件,并且紧随其后PointerExited,所有进一步的处理都由ScrollViewer处理。那就是问题所在。但正如我所说,有一种方法可以做你想做的事。

  2. 为此,让我们假设你有你的ListView只有VerticalScroll定义:

    <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. 我们也需要得到我们的我们的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

    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 
    } 
    

几句话:

  • 这种方法仍然需要很多调整,但hopefuly将告诉你如何实现自己的目标,
  • 你可能也需要一些小的水平运动与垂直孩子们分开,
  • 如果您ListView或其他控制具有水平滚动,然后您还需要禁用并处理它,
  • 此方法不会像原始ScrollViewer那样平滑运行。

我也把一个简单的工作示例here at OneDrive