ScrollViewer 上的动画(平滑)滚动 [英] Animated (Smooth) scrolling on ScrollViewer

查看:23
本文介绍了ScrollViewer 上的动画(平滑)滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 WPF 应用程序中有一个 ScrollViewer,我希望它像 Firefox 一样具有平滑/动画滚动效果(如果你知道我在说什么).

我试图通过互联网搜索,但我发现的唯一一件事是:

这里.

在 Windows XP、Windows 7、.NET 4.0 上测试.

<小时>

示例项目可在此 链接.

<小时>

下面是这个实现的完整代码:

公共静态类ScrollAnimationBehavior{#region 用于列表框的私有滚动查看器私有静态 ScrollViewer _listBoxScroller = new ScrollViewer();#endregion#region VerticalOffset 属性公共静态 DependencyProperty VerticalOffsetProperty =DependencyProperty.RegisterAttached("VerticalOffset",类型(双),typeof(ScrollAnimationBehavior),新的 UIPropertyMetadata(0.0, OnVerticalOffsetChanged));public static void SetVerticalOffset(FrameworkElement target, double value){target.SetValue(VerticalOffsetProperty, value);}public static double GetVerticalOffset(FrameworkElement 目标){返回(双)target.GetValue(VerticalOffsetProperty);}#endregion#region TimeDuration 属性公共静态 DependencyProperty TimeDurationProperty =DependencyProperty.RegisterAttached("TimeDuration",类型(时间跨度),typeof(ScrollAnimationBehavior),new PropertyMetadata(new TimeSpan(0, 0, 0, 0, 0)));public static void SetTimeDuration(FrameworkElement target, TimeSpan value){target.SetValue(TimeDurationProperty, value);}public static TimeSpan GetTimeDuration(FrameworkElement target){返回 (TimeSpan)target.GetValue(TimeDurationProperty);}#endregion#region PointsToScroll 属性公共静态 DependencyProperty PointsToScrollProperty =DependencyProperty.RegisterAttached("PointsToScroll",类型(双),typeof(ScrollAnimationBehavior),新的属性元数据(0.0));public static void SetPointsToScroll(FrameworkElement target, double value){target.SetValue(PointsToScrollProperty, value);}public static double GetPointsToScroll(FrameworkElement target){return (double)target.GetValue(PointsToScrollProperty);}#endregion#region OnVerticalOffset 已更改private static void OnVerticalOffsetChanged(DependencyObject target, DependencyPropertyChangedEventArgs e){ScrollViewer scrollViewer = target as ScrollViewer;如果(滚动查看器!= null){scrollViewer.ScrollToVerticalOffset((double)e.NewValue);}}#endregion#region IsEnabled 属性公共静态 DependencyProperty IsEnabledProperty =DependencyProperty.RegisterAttached("IsEnabled",类型(布尔),typeof(ScrollAnimationBehavior),新的 UIPropertyMetadata(false, OnIsEnabledChanged));public static void SetIsEnabled(FrameworkElement target, bool value){target.SetValue(IsEnabledProperty, value);}public static bool GetIsEnabled(FrameworkElement target){返回(布尔)target.GetValue(IsEnabledProperty);}#endregion#region OnIsEnabledChanged 已更改private static void OnIsEnabledChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e){var 目标 = 发件人;if (target != null && target is ScrollViewer){ScrollViewer scroller = target as ScrollViewer;scroller.Loaded += new RoutedEventHandler(scrollerLoaded);}if (target != null && target is ListBox){ListBox listbox = target as ListBox;listbox.Loaded += new RoutedEventHandler(listboxLoaded);}}#endregion#region AnimateScroll 助手私有静态无效 AnimateScroll(ScrollViewer scrollViewer, double ToValue){DoubleAnimation verticalAnimation = new DoubleAnimation();VerticalAnimation.From = scrollViewer.VerticalOffset;VerticalAnimation.To = ToValue;VerticalAnimation.Duration = new Duration(GetTimeDuration(scrollViewer));Storyboard storyboard = new Storyboard();storyboard.Children.Add(verticalAnimation);Storyboard.SetTarget(verticalAnimation, scrollViewer);Storyboard.SetTargetProperty(verticalAnimation, new PropertyPath(ScrollAnimationBehavior.VerticalOffsetProperty));storyboard.Begin();}#endregion#region NormalizeScrollPos 助手private static double NormalizeScrollPos(ScrollViewer scroll, double scrollChange, Orientation o){double returnValue = scrollChange;如果 (scrollChange <0){返回值 = 0;}if (o == Orientation.Vertical && scrollChange > scroll.ScrollableHeight){returnValue = scroll.ScrollableHeight;}else if (o == Orientation.Horizo​​ntal && scrollChange > scroll.ScrollableWidth){returnValue = scroll.ScrollableWidth;}返回返回值;}#endregion#region UpdateScrollPosition 助手私有静态无效 UpdateScrollPosition(对象发送者){ListBox listbox = sender as ListBox;如果(列表框!= null){双滚动到 = 0;for (int i = 0; i <(listbox.SelectedIndex); i++){ListBoxItem tempItem = listbox.ItemContainerGenerator.ContainerFromItem(listbox.Items[i]) as ListBoxItem;如果(临时项目!= null){scrollTo += tempItem.ActualHeight;}}AnimateScroll(_listBoxScroller, scrollTo);}}#endregion#region SetEventHandlersForScrollViewer 助手private static void SetEventHandlersForScrollViewer(ScrollViewer scroller){scroller.PreviewMouseWheel += new MouseWheelEventHandler(ScrollViewerPreviewMouseWheel);scroller.PreviewKeyDown += new KeyEventHandler(ScrollViewerPreviewKeyDown);}#endregion#region scrollerLoaded 事件处理程序private static void scrollerLoaded(object sender, RoutedEventArgs e){ScrollViewer scroller = sender as ScrollViewer;SetEventHandlersForScrollViewer(scroller);}#endregion#region listboxLoaded 事件处理程序private static void listboxLoaded(object sender, RoutedEventArgs e){ListBox listbox = sender as ListBox;_listBoxScroller = FindVisualChildHelper.GetFirstChildOfType(listbox);SetEventHandlersForScrollViewer(_listBoxScroller);SetTimeDuration(_listBoxScroller, new TimeSpan(0, 0, 0, 0, 200));SetPointsToScroll(_listBoxScroller, 16.0);listbox.SelectionChanged += new SelectionChangedEventHandler(ListBoxSelectionChanged);listbox.Loaded += new RoutedEventHandler(ListBoxLoaded);listbox.LayoutUpdated += new EventHandler(ListBoxLayoutUpdated);}#endregion#region ScrollViewerPreviewMouseWheel 事件处理程序私有静态无效ScrollViewerPreviewMouseWheel(对象发送者,MouseWheelEventArgs e){double mouseWheelChange = (double)e.Delta;ScrollViewer 滚动条 = (ScrollViewer)sender;double newVOffset = GetVerticalOffset(scroller) - (mouseWheelChange/3);如果 (newVOffset <0){AnimateScroll(scroller, 0);}else if (newVOffset > scroller.ScrollableHeight){AnimateScroll(scroller, scroller.ScrollableHeight);}别的{AnimateScroll(scroller, newVOffset);}e.handled = true;}#endregion#region ScrollViewerPreviewKeyDown 处理程序私有静态无效ScrollViewerPreviewKeyDown(对象发送者,KeyEventArgs e){ScrollViewer 滚动条 = (ScrollViewer)sender;键 keyPressed = e.Key;double newVerticalPos = GetVerticalOffset(scroller);bool isKeyHandled = false;if (keyPressed == Key.Down){newVerticalPos = NormalizeScrollPos(scroller, (newVerticalPos + GetPointsToScroll(scroller)), Orientation.Vertical);isKeyHandled = true;}else if (keyPressed == Key.PageDown){newVerticalPos = NormalizeScrollPos(scroller, (newVerticalPos + scroller.ViewportHeight), Orientation.Vertical);isKeyHandled = true;}否则如果(keyPressed == Key.Up){newVerticalPos = NormalizeScrollPos(scroller, (newVerticalPos - GetPointsToScroll(scroller)), Orientation.Vertical);isKeyHandled = true;}否则如果(keyPressed == Key.PageUp){newVerticalPos = NormalizeScrollPos(scroller, (newVerticalPos - scroller.ViewportHeight), Orientation.Vertical);isKeyHandled = true;}if (newVerticalPos != GetVerticalOffset(scroller)){AnimateScroll(scroller, newVerticalPos);}e.Handled = isKeyHandled;}#endregion#region ListBox 事件处理程序private static void ListBoxLayoutUpdated(object sender, EventArgs e){更新滚动位置(发件人);}私有静态无效 ListBoxLoaded(对象发送者,RoutedEventArgs e){更新滚动位置(发件人);}private static void ListBoxSelectionChanged(object sender, SelectionChangedEventArgs e){更新滚动位置(发件人);}#endregion}

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 as well, or else is there a working control with the same properties/features I want?

解决方案

In your example there are two controls inherited from ScrollViewer and ListBox, the animation is implemented by SplineDoubleKeyFrame [MSDN]. In my time, I realized animation scrolling via the attached dependency property VerticalOffsetProperty, which allows you to directly transfer offset scrollbar into a double animation, like this:

DoubleAnimation verticalAnimation = new DoubleAnimation();

verticalAnimation.From = scrollViewer.VerticalOffset;
verticalAnimation.To = some value;
verticalAnimation.Duration = new Duration( some duration );

Storyboard storyboard = new Storyboard();

storyboard.Children.Add(verticalAnimation);
Storyboard.SetTarget(verticalAnimation, scrollViewer);
Storyboard.SetTargetProperty(verticalAnimation, new PropertyPath(ScrollAnimationBehavior.VerticalOffsetProperty)); // Attached dependency property
storyboard.Begin();

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 behavior ScrollAnimationBehavior, which can be applied to ScrollViewerand ListBox.

Example of using:

XAML

<Window x:Class="ScrollAnimateBehavior.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:AttachedBehavior="clr-namespace:ScrollAnimateBehavior.AttachedBehaviors"
        Title="MainWindow" 
        WindowStartupLocation="CenterScreen"
        Height="350"
        Width="525">

    <Window.Resources>
        <x:Array x:Key="TestArray" Type="{x:Type sys:String}">
            <sys:String>TEST 1</sys:String>
            <sys:String>TEST 2</sys:String>
            <sys:String>TEST 3</sys:String>
            <sys:String>TEST 4</sys:String>
            <sys:String>TEST 5</sys:String>
            <sys:String>TEST 6</sys:String>
            <sys:String>TEST 7</sys:String>
            <sys:String>TEST 8</sys:String>
            <sys:String>TEST 9</sys:String>
            <sys:String>TEST 10</sys:String>
        </x:Array>
    </Window.Resources>

    <Grid>
        <TextBlock Text="ScrollViewer"
                   FontFamily="Verdana"
                   FontSize="14"
                   VerticalAlignment="Top"
                   HorizontalAlignment="Left"
                   Margin="80,80,0,0" />

        <ScrollViewer AttachedBehavior:ScrollAnimationBehavior.IsEnabled="True"                         
                      AttachedBehavior:ScrollAnimationBehavior.TimeDuration="00:00:00.20"
                      AttachedBehavior:ScrollAnimationBehavior.PointsToScroll="16"
                      HorizontalAlignment="Left"
                      Width="250"
                      Height="100">

            <StackPanel>
                <ItemsControl ItemsSource="{StaticResource TestArray}"
                              FontSize="16" />
            </StackPanel>
        </ScrollViewer>

        <TextBlock Text="ListBox"
                   FontFamily="Verdana"
                   FontSize="14"
                   VerticalAlignment="Top"
                   HorizontalAlignment="Right"
                   Margin="0,80,100,0" />

        <ListBox AttachedBehavior:ScrollAnimationBehavior.IsEnabled="True"
                 ItemsSource="{StaticResource TestArray}"
                 ScrollViewer.CanContentScroll="False"
                 HorizontalAlignment="Right"
                 FontSize="16"
                 Width="250"
                 Height="100" />        
    </Grid>
</Window>

Output

IsEnabled property is responsible for the scrolling animation for ScrollViewer and for ListBox. Below its implementation:

public static DependencyProperty IsEnabledProperty =
                                 DependencyProperty.RegisterAttached("IsEnabled",
                                 typeof(bool),
                                 typeof(ScrollAnimationBehavior),
                                 new UIPropertyMetadata(false, OnIsEnabledChanged));

public static void SetIsEnabled(FrameworkElement target, bool value)
{
    target.SetValue(IsEnabledProperty, value);
}

public static bool GetIsEnabled(FrameworkElement target)
{
    return (bool)target.GetValue(IsEnabledProperty);
}

private static void OnIsEnabledChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    var target = sender;

    if (target != null && target is ScrollViewer)
    {
        ScrollViewer scroller = target as ScrollViewer;
        scroller.Loaded += new RoutedEventHandler(scrollerLoaded);
    }

    if (target != null && target is ListBox) 
    {
        ListBox listbox = target as ListBox;
        listbox.Loaded += new RoutedEventHandler(listboxLoaded);
    }
}

In these Loaded handlers are set event handlers for PreviewMouseWheel and PreviewKeyDown.

Helpers (auxiliary procedures) are taken from the example and provide a value of double type, which is passed to the procedure AnimateScroll(). Here and are the magic key of animation:

private static void AnimateScroll(ScrollViewer scrollViewer, double ToValue)
{
    DoubleAnimation verticalAnimation = new DoubleAnimation();

    verticalAnimation.From = scrollViewer.VerticalOffset;
    verticalAnimation.To = ToValue;
    verticalAnimation.Duration = new Duration(GetTimeDuration(scrollViewer));

    Storyboard storyboard = new Storyboard();

    storyboard.Children.Add(verticalAnimation);
    Storyboard.SetTarget(verticalAnimation, scrollViewer);
    Storyboard.SetTargetProperty(verticalAnimation, new PropertyPath(ScrollAnimationBehavior.VerticalOffsetProperty));
    storyboard.Begin();
}

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 events PreviewKeyDown, 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 interface Behavior. 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:

public static class ScrollAnimationBehavior
{
    #region Private ScrollViewer for ListBox

    private static ScrollViewer _listBoxScroller = new ScrollViewer();

    #endregion

    #region VerticalOffset Property

    public static DependencyProperty VerticalOffsetProperty =
        DependencyProperty.RegisterAttached("VerticalOffset",
                                            typeof(double),
                                            typeof(ScrollAnimationBehavior),
                                            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);
    }

    #endregion

    #region TimeDuration Property

    public static DependencyProperty TimeDurationProperty =
        DependencyProperty.RegisterAttached("TimeDuration",
                                            typeof(TimeSpan),
                                            typeof(ScrollAnimationBehavior),
                                            new PropertyMetadata(new TimeSpan(0, 0, 0, 0, 0)));

    public static void SetTimeDuration(FrameworkElement target, TimeSpan value)
    {
        target.SetValue(TimeDurationProperty, value);
    }

    public static TimeSpan GetTimeDuration(FrameworkElement target)
    {
        return (TimeSpan)target.GetValue(TimeDurationProperty);
    }

    #endregion

    #region PointsToScroll Property

    public static DependencyProperty PointsToScrollProperty =
        DependencyProperty.RegisterAttached("PointsToScroll",
                                            typeof(double),
                                            typeof(ScrollAnimationBehavior),
                                            new PropertyMetadata(0.0));

    public static void SetPointsToScroll(FrameworkElement target, double value)
    {
        target.SetValue(PointsToScrollProperty, value);
    }

    public static double GetPointsToScroll(FrameworkElement target)
    {
        return (double)target.GetValue(PointsToScrollProperty);
    }

    #endregion

    #region OnVerticalOffset Changed

    private static void OnVerticalOffsetChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
    {
        ScrollViewer scrollViewer = target as ScrollViewer;

        if (scrollViewer != null)
        {
            scrollViewer.ScrollToVerticalOffset((double)e.NewValue);
        }
    }

    #endregion

    #region IsEnabled Property

    public static DependencyProperty IsEnabledProperty =
                                            DependencyProperty.RegisterAttached("IsEnabled",
                                            typeof(bool),
                                            typeof(ScrollAnimationBehavior),
                                            new UIPropertyMetadata(false, OnIsEnabledChanged));

    public static void SetIsEnabled(FrameworkElement target, bool value)
    {
        target.SetValue(IsEnabledProperty, value);
    }

    public static bool GetIsEnabled(FrameworkElement target)
    {
        return (bool)target.GetValue(IsEnabledProperty);
    }

    #endregion

    #region OnIsEnabledChanged Changed

    private static void OnIsEnabledChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var target = sender;

        if (target != null && target is ScrollViewer)
        {
            ScrollViewer scroller = target as ScrollViewer;
            scroller.Loaded += new RoutedEventHandler(scrollerLoaded);
        }

        if (target != null && target is ListBox) 
        {
            ListBox listbox = target as ListBox;
            listbox.Loaded += new RoutedEventHandler(listboxLoaded);
        }
    }

    #endregion

    #region AnimateScroll Helper

    private static void AnimateScroll(ScrollViewer scrollViewer, double ToValue)
    {
        DoubleAnimation verticalAnimation = new DoubleAnimation();

        verticalAnimation.From = scrollViewer.VerticalOffset;
        verticalAnimation.To = ToValue;
        verticalAnimation.Duration = new Duration(GetTimeDuration(scrollViewer));

        Storyboard storyboard = new Storyboard();

        storyboard.Children.Add(verticalAnimation);
        Storyboard.SetTarget(verticalAnimation, scrollViewer);
        Storyboard.SetTargetProperty(verticalAnimation, new PropertyPath(ScrollAnimationBehavior.VerticalOffsetProperty));
        storyboard.Begin();
    }

    #endregion

    #region NormalizeScrollPos Helper

    private static double NormalizeScrollPos(ScrollViewer scroll, double scrollChange, Orientation o)
    {
        double returnValue = scrollChange;

        if (scrollChange < 0)
        {
            returnValue = 0;
        }

        if (o == Orientation.Vertical && scrollChange > scroll.ScrollableHeight)
        {
            returnValue = scroll.ScrollableHeight;
        }
        else if (o == Orientation.Horizontal && scrollChange > scroll.ScrollableWidth)
        {
            returnValue = scroll.ScrollableWidth;
        }

        return returnValue;
    }

    #endregion

    #region UpdateScrollPosition Helper

    private static void UpdateScrollPosition(object sender)
    {
        ListBox listbox = sender as ListBox;

        if (listbox != null)
        {
            double scrollTo = 0;

            for (int i = 0; i < (listbox.SelectedIndex); i++)
            {
                ListBoxItem tempItem = listbox.ItemContainerGenerator.ContainerFromItem(listbox.Items[i]) as ListBoxItem;

                if (tempItem != null)
                {
                    scrollTo += tempItem.ActualHeight;
                }
            }

            AnimateScroll(_listBoxScroller, scrollTo);
        }
    }

    #endregion

    #region SetEventHandlersForScrollViewer Helper

    private static void SetEventHandlersForScrollViewer(ScrollViewer scroller) 
    {
        scroller.PreviewMouseWheel += new MouseWheelEventHandler(ScrollViewerPreviewMouseWheel);
        scroller.PreviewKeyDown += new KeyEventHandler(ScrollViewerPreviewKeyDown);
    }

    #endregion

    #region scrollerLoaded Event Handler

    private static void scrollerLoaded(object sender, RoutedEventArgs e)
    {
        ScrollViewer scroller = sender as ScrollViewer;

        SetEventHandlersForScrollViewer(scroller);
    }

    #endregion

    #region listboxLoaded Event Handler

    private static void listboxLoaded(object sender, RoutedEventArgs e)
    {
        ListBox listbox = sender as ListBox;

        _listBoxScroller = FindVisualChildHelper.GetFirstChildOfType<ScrollViewer>(listbox);
        SetEventHandlersForScrollViewer(_listBoxScroller);

        SetTimeDuration(_listBoxScroller, new TimeSpan(0, 0, 0, 0, 200));
        SetPointsToScroll(_listBoxScroller, 16.0);

        listbox.SelectionChanged += new SelectionChangedEventHandler(ListBoxSelectionChanged);
        listbox.Loaded += new RoutedEventHandler(ListBoxLoaded);
        listbox.LayoutUpdated += new EventHandler(ListBoxLayoutUpdated);
    }

    #endregion

    #region ScrollViewerPreviewMouseWheel Event Handler

    private static void ScrollViewerPreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        double mouseWheelChange = (double)e.Delta;
        ScrollViewer scroller = (ScrollViewer)sender;
        double newVOffset = GetVerticalOffset(scroller) - (mouseWheelChange / 3);

        if (newVOffset < 0)
        {
            AnimateScroll(scroller, 0);
        }
        else if (newVOffset > scroller.ScrollableHeight)
        {
            AnimateScroll(scroller, scroller.ScrollableHeight);
        }
        else
        {
            AnimateScroll(scroller, newVOffset);
        }

        e.Handled = true;
    }

    #endregion

    #region ScrollViewerPreviewKeyDown Handler

    private static void ScrollViewerPreviewKeyDown(object sender, KeyEventArgs e)
    {
        ScrollViewer scroller = (ScrollViewer)sender;

        Key keyPressed = e.Key;
        double newVerticalPos = GetVerticalOffset(scroller);
        bool isKeyHandled = false;

        if (keyPressed == Key.Down)
        {
            newVerticalPos = NormalizeScrollPos(scroller, (newVerticalPos + GetPointsToScroll(scroller)), Orientation.Vertical);
            isKeyHandled = true;
        }
        else if (keyPressed == Key.PageDown)
        {
            newVerticalPos = NormalizeScrollPos(scroller, (newVerticalPos + scroller.ViewportHeight), Orientation.Vertical);
            isKeyHandled = true;
        }
        else if (keyPressed == Key.Up)
        {
            newVerticalPos = NormalizeScrollPos(scroller, (newVerticalPos - GetPointsToScroll(scroller)), Orientation.Vertical);
            isKeyHandled = true;
        }
        else if (keyPressed == Key.PageUp)
        {
            newVerticalPos = NormalizeScrollPos(scroller, (newVerticalPos - scroller.ViewportHeight), Orientation.Vertical);
            isKeyHandled = true;
        }

        if (newVerticalPos != GetVerticalOffset(scroller))
        {
            AnimateScroll(scroller, newVerticalPos);
        }

        e.Handled = isKeyHandled;
    }

    #endregion

    #region ListBox Event Handlers

    private static void ListBoxLayoutUpdated(object sender, EventArgs e)
    {
        UpdateScrollPosition(sender);
    }

    private static void ListBoxLoaded(object sender, RoutedEventArgs e)
    {
        UpdateScrollPosition(sender);
    }

    private static void ListBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        UpdateScrollPosition(sender);
    }

    #endregion
}

这篇关于ScrollViewer 上的动画(平滑)滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆