Cobold
Cobold

Reputation: 2613

Scroll animation

How can I animate the the scrolling for ListBox? I know I can use scrollIntoView but how can I animate it? I want to press the arrow keys to move from one listBoxItem to another.

Upvotes: 5

Views: 6878

Answers (2)

Fredrik Hedblad
Fredrik Hedblad

Reputation: 84676

Here is a rough implementation based on the same approach as the following link
http://aniscrollviewer.codeplex.com/

The VerticalOffset property is read-only so instead you can use an attached property VerticalOffset on the ScrollViewer which in turn does ScrollToVerticalOffset. This attached property can be animated.

You can also create an extension method for ItemsControl called AnimateScrollIntoView.

Call it like this

listBox.AnimateScrollIntoView(yourItem);

ScrollViewerBehavior

public class ScrollViewerBehavior
{
    public static DependencyProperty VerticalOffsetProperty =
        DependencyProperty.RegisterAttached("VerticalOffset",
                                            typeof(double),
                                            typeof(ScrollViewerBehavior),
                                            new UIPropertyMetadata(0.0, OnVerticalOffsetChanged));

    public static void SetVerticalOffset(FrameworkElement target, double value)
    {
        target.SetValue(VerticalOffsetProperty, value);
    }
    public static double GetVerticalOffset(FrameworkElement target)
    {
        return (double)target.GetValue(VerticalOffsetProperty);
    }
    private static void OnVerticalOffsetChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
    {
        ScrollViewer scrollViewer = target as ScrollViewer;
        if (scrollViewer != null)
        {
            scrollViewer.ScrollToVerticalOffset((double)e.NewValue);
        }
    }
}

ItemsControlExtensions

public static class ItemsControlExtensions
{
    public static void AnimateScrollIntoView(this ItemsControl itemsControl, object item)
    {
        ScrollViewer scrollViewer = VisualTreeHelpers.GetVisualChild<ScrollViewer>(itemsControl);

        UIElement container = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as UIElement;
        int index = itemsControl.ItemContainerGenerator.IndexFromContainer(container);
        double toValue = scrollViewer.ScrollableHeight * ((double)index / itemsControl.Items.Count);
        Point relativePoint = container.TranslatePoint(new Point(0.0, 0.0), Window.GetWindow(container));

        DoubleAnimation verticalAnimation = new DoubleAnimation();
        verticalAnimation.From = scrollViewer.VerticalOffset;
        verticalAnimation.To = toValue;
        verticalAnimation.DecelerationRatio = .2;
        verticalAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(1000));
        Storyboard storyboard = new Storyboard();
        storyboard.Children.Add(verticalAnimation);
        Storyboard.SetTarget(verticalAnimation, scrollViewer);
        Storyboard.SetTargetProperty(verticalAnimation, new PropertyPath(ScrollViewerBehavior.VerticalOffsetProperty));
        storyboard.Begin();
    }
}

And since you also need to get a hold of the ScrollViewer you'll need this

public static class VisualTreeHelpers
{
    public static T GetVisualChild<T>(DependencyObject parent) where T : Visual
    {
        T child = default(T);

        int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < numVisuals; i++)
        {
            Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
            child = v as T;
            if (child == null)
            {
                child = GetVisualChild<T>(v);
            }
            if (child != null)
            {
                break;
            }
        }
        return child;
    }
}

Upvotes: 8

evanb
evanb

Reputation: 3111

Take a look at this article, it explains how animate scrolling and add touch gestures. Download the source at the bottom of the page and look at WpfScrollContent solution. I would extend the WPF ListBox and add the scroll animation to it that way you can reuse the control.

Upvotes: 0

Related Questions