开发者

Scroll animation

How can I animate the the scrolling for ListBox? I know I can 开发者_如何学Cuse scrollIntoView but how can I animate it? I want to press the arrow keys to move from one listBoxItem to another.


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;
    }
}


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜