滚动动画

时间:2011-08-22 20:36:44

标签: wpf animation

如何为ListBox的滚动设置动画?我知道我可以使用scrollIntoView,但我该如何设置它的动画?我想按箭头键从一个listBoxItem移动到另一个。

2 个答案:

答案 0 :(得分:7)

以下是基于与以下链接相同的方法的粗略实现 http://aniscrollviewer.codeplex.com/

VerticalOffset属性是只读的,因此您可以在VerticalOffset上使用附加属性ScrollViewerScrollToVerticalOffset依次为ItemsControl。此附加属性可以设置动画。

您还可以为名为AnimateScrollIntoView的{​​{1}}创建扩展方法。

像这样称呼

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

因为你还需要抓住ScrollViewer,你需要这个

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

答案 1 :(得分:0)

看看这个article,它解释了动画滚动和添加触摸手势的方式。下载页面底部的源代码并查看WpfScrollContent解决方案。我会扩展WPF ListBox并向其添加滚动动画,以便您可以重用该控件。