Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
139 views
in Technique[技术] by (71.8m points)

c# - Horizontal scroll on ListView

I'm currently capturing the PointerMoved event on the page to use with a horizontal menu. So the user can swipe left/right and the page will animate accordingly.

This works when the user touches a static element (TextBlock etc.) but if they touch a ListView it captures the touch events.

How can I implement the ListView so when the user scrolls vertically it works as normal, but when the user scrolls horizontally it passes the events to my code?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It is possible, but you will need a small trick. As a refference I put here Rob Caplan's article.

Let's start:

  1. First - where are your events? - answer is simple - while you have ScrollViewer enabled, all events are intercepted by it and handeled. You ListView will get only PointerEntered event and just after it PointerExited, all further proccesing is handeled by ScrollViewer. That is the problem. But as I've said there is a method to do what you want.

  2. For this purpose lets assume that you have defined your ListView only with VerticalScroll:

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

    Of course it is possible to do for both directions, but it's a simple example.

  3. Now let's have a look at constructor of a Page:

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

    Nothing weird here - I just subscribe to events, and declare two variables firstPoint and listScrollviewer, which I'll need later.

  4. We will need also to get our ScrollViewer of our ListView - the following method will do the job:

    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. Now - to enable our events we will need to disable the ScrollViewer:

    private ScrollViewer DisableScrolling(DependencyObject depObj)
    {
        ScrollViewer foundOne = GetScrollViewer(depObj);
        if (foundOne != null) foundOne.VerticalScrollMode = ScrollMode.Disabled;
        return foundOne;
    }
    
  6. We will disable the ScrollViewer upon PointerEntered event which is fired. In this step we will also remember the pressed PointerPoint - as we have disable Scrollviewer, we will have to scroll it manually - that is what we need this PointerPoint for.

    private void myList_PointerEntered(object sender, PointerRoutedEventArgs e)
    {
        firstPoint = e.GetCurrentPoint(myList);
        if (listScrollviewer == null) listScrollviewer = DisableScrolling(myList);
    }
    
  7. Finally our PointerMoved event, which now wil be fired as we had disabled ScrollViewer - moving ScrollViewer + other code you need to put there:

    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
    }
    

Few remarks:

  • this method still needs much tuning, but hopefuly will show you how to achieve your goal,
  • you may need also to separate some small horizontal movements from vertical ones,
  • if your ListView or other Control has horizontal scroll, then you will also need to disable and handle it,
  • this method won't probably work so smooth like original ScrollViewer.

I've also put a simple working example here at OneDrive.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...