WPF开发者QQ群: 340500857 | 微信群 -> 进入公众号主页 加入组织
欢迎转发、分享、点赞、在看,谢谢~。
前言
看了看原生UWP的ScrollViewer,滑动很流畅(例如 开始菜单),但是WPF自带的ScrollViewer滚动十分生硬..
突发奇想,今天来实现一个流畅滚动的ScrollViewer.
01
—
效果预览
效果预览(更多效果请下载源码体验):
02
—
代码如下
一、ScrollViewerBehavior.cs 代码如下
using System.Windows;
using System.Windows.Controls;namespace WPFDevelopers.Controls
{public static class ScrollViewerBehavior{public static readonly 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) => (double)target.GetValue(VerticalOffsetProperty);private static void OnVerticalOffsetChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) => (target as ScrollViewer)?.ScrollToVerticalOffset((double)e.NewValue);}
}
二、ScrollViewerAnimation.cs 代码如下
using System;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Animation;namespace WPFDevelopers.Controls
{public class ScrollViewerAnimation : ScrollViewer{//记录上一次的滚动位置private double LastLocation = 0;//重写鼠标滚动事件protected override void OnMouseWheel(MouseWheelEventArgs e){double WheelChange = e.Delta;//可以更改一次滚动的距离倍数 (WheelChange可能为正负数!)double newOffset = LastLocation - (WheelChange * 2);//Animation并不会改变真正的VerticalOffset(只是它的依赖属性) 所以将VOffset设置到上一次的滚动位置 (相当于衔接上一个动画)ScrollToVerticalOffset(LastLocation);//碰到底部和顶部时的处理if (newOffset < 0)newOffset = 0;if (newOffset > ScrollableHeight)newOffset = ScrollableHeight;AnimateScroll(newOffset);LastLocation = newOffset;//告诉ScrollViewer我们已经完成了滚动e.Handled = true;}private void AnimateScroll(double ToValue){//为了避免重复,先结束掉上一个动画BeginAnimation(ScrollViewerBehavior.VerticalOffsetProperty, null);DoubleAnimation Animation = new DoubleAnimation();Animation.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };Animation.From = VerticalOffset;Animation.To = ToValue;//动画速度Animation.Duration = TimeSpan.FromMilliseconds(800);//考虑到性能,可以降低动画帧数//Timeline.SetDesiredFrameRate(Animation, 40);BeginAnimation(ScrollViewerBehavior.VerticalOffsetProperty, Animation);}}
}
使用方法:直接创建 <ScrollViewerAnimation/>
如果是在ListBox中,可以通过修改模板的方式,把<ScrollViewer/>换成ScrollViewerAnimation即可.
三、ScrollViewerAnimationExample.xaml 代码如下
<wpfdev:ScrollViewerAnimation Width="200" MaxHeight="300"ScrollViewer.VerticalScrollBarVisibility="Hidden"><ItemsControl ItemsSource="{Binding NavigateMenuModelList}"><ItemsControl.ItemTemplate><DataTemplate><Border Background="{StaticResource SuccessSolidColorBrush}"BorderThickness="0,0,0,.3" BorderBrush="{StaticResource WhiteSolidColorBrush}"><TextBlock Text="{Binding Name}" Padding="10" FontSize="{StaticResource NormalFontSize}"Foreground="{StaticResource WhiteSolidColorBrush}"/></Border></DataTemplate></ItemsControl.ItemTemplate><ItemsControl.ItemsPanel><ItemsPanelTemplate><VirtualizingStackPanel/></ItemsPanelTemplate></ItemsControl.ItemsPanel></ItemsControl></wpfdev:ScrollViewerAnimation>
源码地址
github:https://github.com/yanjinhuagood/WPFDevelopers.git
gitee:https://gitee.com/yanjinhua/WPFDevelopers.git
WPF开发者QQ群: 340500857
blogs: https://www.cnblogs.com/yanjinhua
Github:https://github.com/yanjinhuagood
出处:https://www.cnblogs.com/yanjinhua
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
转载请著名作者 出处 https://github.com/yanjinhuagood