I have a ScrollViewer
in my WPF App, and I want it to have smooth/animated scrolling effect just like Firefox has (if you know what I am talking about).
I tried to search over the internet, and the only thing I've found is this:
How To Create An Animated ScrollViewer (or ListBox) in WPF
It works pretty good, but I have one problem with it - it animates the scrolling effect but the ScrollViewer
's Thumb
goes directly to the point pressed - I want it to be animated aswell
How can I cause the ScrollViewer
's Thumb
to be animated aswell, or else is there a working control with the same properties/features I want?
The best example of scroll customization can be found in an article by Sacha Barber on Code Project. See this code project article on Friction scrolling article on the topic.
A number of Sacha Barbers WPF code has been integrated into a Github project for WPF. See MahaApps Metro for some very useful open source WPF implementations.
For those getting here from google Anatoliy's code works, but has some issues with mouse wheel scrolling specifically.
Scrolling without Fix (Keep in mind i am attempting to rapid scroll to the bottom)
Scrolling with Fix
(self plug, you can find out what this application is over Here)
Let's take a look at why.
In this handler code, you'll notice that it is called every time you scroll the mouse wheel. So when you hit it with rapid scrolling the animation doesn't have time to complete, and you are stuck attempting to scroll from where you are in the middle of the animation. This causes jittery slow scrolling when attempting to scroll faster.
Additionally their code here:
Has unneeded storyboard implementation, that can be removed to make the scroll animation interruptible, which is what we will need to in order to smooth out rapid scrolling.
At the top of their code we are going to add a new variable.
We need to save the intended location of the animation, so that if we call the scroller event again, we can jump to that location right away before starting the next animation call.
Now there's something else we have to change. The intendedLocation needs to be updated when the user either uses one of the keydown events (Page up or page down) or if they manually move the scrollbar with the mouse.
So we need to add another event to handle the left mouse button up on the scrollviewer, and when the mouse is lifted (put at intended location) then we can change the intended location, so that the scroll wheel gets the updated position.
We still need to update the page up and page down area as well though.
Now that we have the non-mousewheel events handled to update the intended location, let's fix up the mouse wheel event.
So the changes are as follows
Changed newVOffset to function from the intendedLocation and the mouseWheelChange.
Cleaned up when the newVOffset is over or under acceptable boundaries.
We jumped to the intendedLocation, which was created by the last scrollwheel event with where it wanted to go.
If you want to change the "speed" of the scroll simply change
You can change the modifier from times 2 to times 5 for faster or times 1 for slower.
With all the events handled now, let's make the animation cancel itself, so this all has a point.
So what we did here was remove the storyboard, and nullified any existing animation so that we can start with a fresh new one.
Below is the full code (Provided AS IS), incase you're too lazy to change it like I was just copying it.
In your example there are two controls inherited from
ScrollViewer
andListBox
, the animation is implemented bySplineDoubleKeyFrame
[MSDN]. In my time, I realized animation scrolling via the attached dependency propertyVerticalOffsetProperty
, which allows you to directly transfer offset scrollbar into a double animation, like this:Examples can be found here:
How to: Animate the Horizontal/VerticalOffset properties of a ScrollViewer
WPF - Animate ListBox.ScrollViewer.HorizontalOffset?
In this case, works well smooth scrolling of the content and the
Thumb
. Based on this approach, and using your example [How To Create An Animated ScrollViewer (or ListBox) in WPF], I created an attached behaviorScrollAnimationBehavior
, which can be applied toScrollViewer
andListBox
.Example of using:
XAML
Output
IsEnabled
property is responsible for the scrolling animation forScrollViewer
and forListBox
. Below its implementation:In these
Loaded
handlers are set event handlers forPreviewMouseWheel
andPreviewKeyDown
.Helpers (auxiliary procedures) are taken from the example and provide a value of
double
type, which is passed to the procedureAnimateScroll()
. Here and are the magic key of animation:Some notes
The example only implemented vertical animation, if you will accept this project, you will realize itself without problems horizontal animation.
Selection of the current item in
ListBox
not transferred to the next element of this is due to the interception of eventsPreviewKeyDown
, so you have to think about this moment.This implementation is fully suited for the MVVM pattern. To use this behavior in the
Blend
, you need to inherit interfaceBehavior
. Example can be found here and here.Tested on Windows XP, Windows Seven, .NET 4.0.
Sample project is available at this link.
Below is a full code of this implementation: