It is possible, but you will need a small trick. As a refference I put here Rob Caplan's article.
Let's start:
First - where are your events? - answer is simple - while you have
ScrollViewer
enabled, all events are intercepted by it and handeled. YouListView
will get onlyPointerEntered
event and just after itPointerExited
, all further proccesing is handeled byScrollViewer
. That is the problem. But as I've said there is a method to do what you want.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.
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
andlistScrollviewer
, which I'll need later.We will need also to get our
ScrollViewer
of ourListView
- 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; }
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; }
We will disable the
ScrollViewer
uponPointerEntered
event which is fired. In this step we will also remember the pressedPointerPoint
- as we have disableScrollviewer
, we will have to scroll it manually - that is what we need thisPointerPoint
for.private void myList_PointerEntered(object sender, PointerRoutedEventArgs e) { firstPoint = e.GetCurrentPoint(myList); if (listScrollviewer == null) listScrollviewer = DisableScrolling(myList); }
Finally our
PointerMoved
event, which now wil be fired as we had disabledScrollViewer
- movingScrollViewer
+ 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.