WPF实现ScrollViewer平滑滚动效果

WPF 滚动条控件ScrollViewer的使用及自定义滚动条控件(一) WPF 滚动条控件ScrollViewer的使用及自定义滚动条控件 首先看一下两种空间的运行效果: 左边是自定义滑条控件,右边是自带的滑条控件; **滑条使用方法:**我们在ScrollViewer滑条控件中放一个TextBlock控件,其内容可以自动换行显示,然后设置TextBlock的高度大于ScrollViewer的高度后,右侧就会出现滑条; <ScrollViewer Horizo... 阅读详情

WPF实现滚动条只要在控件外围加上ScrollViewer即可,但是滚动的时候没有动画效果,比较生硬,在滚动的时候添加过渡动画实现平滑滚动能给我们的软件增色不少。

接下来,在上一篇博客(WPF使用FlowDocument加载文本并修改文本样式https://blog.youkuaiyun.com/dnazhd/article/details/89307386)的基础上进行修改,这里只展示垂直滚动效果,水平滚动方式同理。为了更加明显的展示效果,先将协议文本内容添加的更多些。

原始滚动效果:

修改后效果:

 

修改流程:

1.新建SmoothScroll文件夹,并新建SmoothScrollViewer.cs类,继承自ScrollViewer,注册步进长度依赖属性,代码如下:

using System.Windows;
using System.Windows.Controls;

namespace RichTextBoxDemo.SmoothScroll
{
    public class SmoothScrollViewer : ScrollViewer
    {
        /// <summary>
        /// 垂直归一化步进长度
        /// </summary>
        public double VerticalScrollRatio
        {
            get { return (double)GetValue(VerticalScrollRatioProperty); }
            set { SetValue(VerticalScrollRatioProperty, value); }
        }

        //注册VerticalScrollRatio依赖属性
        public static readonly DependencyProperty VerticalScrollRatioProperty =
            DependencyProperty.Register("VerticalScrollRatio", typeof(double), typeof(SmoothScrollViewer), new PropertyMetadata(0.0, new PropertyChangedCallback(V_ScrollRatioChangedCallBack)));

        private static void V_ScrollRatioChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var scrollViewer = (ScrollViewer)(d);
            if (scrollViewer != null)
            {
                scrollViewer.ScrollToVerticalOffset((double)(e.NewValue) * scrollViewer.ScrollableHeight);
            }
        }

        /// <summary>
        /// 水平归一化步进长度
        /// </summary>
        public double HorizontalScrollRatio
        {
            get { return (double)GetValue(HorizontalScrollRatioProperty); }
            set { SetValue(HorizontalScrollRatioProperty, value); }
        }

        //注册HorizontalScrollRatio依赖属性
        public static readonly DependencyProperty HorizontalScrollRatioProperty =
            DependencyProperty.Register("HorizontalScrollRatio", typeof(double), typeof(SmoothScrollViewer), new PropertyMetadata(0.0, new PropertyChangedCallback(H_ScrollRatioChangedCallBack)));

        private static void H_ScrollRatioChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var scrollViewer = (ScrollViewer)(d);
            if (scrollViewer != null)
            {
                scrollViewer.ScrollToHorizontalOffset((double)(e.NewValue) * scrollViewer.ScrollableWidth);
            }
        }
    }
}

2、在SmoothScroll文件夹,新建ScrollViewerExtend.cs类,实现平滑滚动功能,代码如下:

using System;
using System.Windows;
using System.Windows.Media.Animation;

namespace RichTextBoxDemo.SmoothScroll
{
    public static class ScrollViewerExtend
    {
        /// <summary>
        /// 实现ScrollViewer的平滑滚动
        /// </summary>
        /// <param name="scrollViewer"></param>
        /// <param name="ScrollStepRatio">归一化步进长度</param>
        /// <param name="ScrollPositionRatio">归一化位置</param>
        /// <param name="direction">滚动方向</param>
        public static void SmoothScroll(this SmoothScrollViewer scrollViewer, double ScrollStepRatio, double ScrollPositionRatio, ScrollDirection direction)
        {
            if (double.IsNaN(ScrollStepRatio) || double.IsNaN(ScrollPositionRatio))
                return;
            DoubleAnimation Animation = new DoubleAnimation();

            Animation.From = ScrollPositionRatio;
            if (ScrollDirection.Down == direction || ScrollDirection.Right == direction)
            {
                double To = ScrollPositionRatio + ScrollStepRatio;
                Animation.To = To > 0.95 ? 1.0 : To;//向下(右)滚动补偿
            }
            else if (ScrollDirection.Up == direction || ScrollDirection.Left == direction)
            {
                double To = ScrollPositionRatio - ScrollStepRatio;
                Animation.To = To < 0.05 ? 0.0 : To;//向上(左)滚动补偿
            }
            Animation.Duration = new Duration(TimeSpan.FromMilliseconds(500));

            Storyboard storyboard = new Storyboard();
            storyboard.Children.Add(Animation);
            Storyboard.SetTarget(Animation, scrollViewer);
            if (ScrollDirection.Down == direction || ScrollDirection.Up == direction)
                Storyboard.SetTargetProperty(Animation, new PropertyPath(SmoothScrollViewer.VerticalScrollRatioProperty));
            else if (ScrollDirection.Right == direction || ScrollDirection.Left == direction)
                Storyboard.SetTargetProperty(Animation, new PropertyPath(SmoothScrollViewer.HorizontalScrollRatioProperty));
            storyboard.Begin();
        }
    }

    public enum ScrollDirection
    {
        Up, Down, Left, Right
    }
}

3、主界面:

<Window x:Class="RichTextBoxDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:RichTextBoxDemo.SmoothScroll"
        mc:Ignorable="d"
        Title="RichTextBox" Height="600" Width="800" Loaded="Window_Loaded">
    <Grid>
        <local:SmoothScrollViewer x:Name="scrollviewer" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled"
                                  ScrollChanged="scrollviewer_ScrollChanged">
            <RichTextBox x:Name="showInfo" Margin="30" Background="Transparent" IsReadOnly="True" Focusable="False" Cursor="Arrow"></RichTextBox>
        </local:SmoothScrollViewer>
    </Grid>
</Window>

4、交互逻辑:

using RichTextBoxDemo.SmoothScroll;
using System;
using System.IO;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;

namespace RichTextBoxDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        double m_ScrollStepRatio = 0.0;     //滚动条的归一化步进长度
        double m_ScrollPositionRatio = 0.0; //滚动条的归一化位置

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            LoadDocument();
        }

        /// <summary>
        /// 加载txt文本
        /// </summary>
        private void LoadDocument()
        {
            string filePath = AppDomain.CurrentDomain.BaseDirectory + @"Disclaimer\Disclaimer.txt";//文件路径
            if(File.Exists(filePath))
            {
                FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);//以只读方式打开源文件
                try
                {
                    using (StreamReader sr = new StreamReader(fs))
                    {
                        FlowDocument document = new FlowDocument();//承载文件内容
                        string content = sr.ReadToEnd();
                        string[] split = content.Split(new char[2] { '\r', '\n' });
                        foreach (string para in split)
                        {
                            if(para != "")
                            {
                                Paragraph paragraph = new Paragraph(new Run(para));
                                paragraph.FontFamily = new FontFamily("微软雅黑");//修改样式
                                paragraph.Foreground = new SolidColorBrush(Colors.Black);
                                if (para == "免责声明")
                                {
                                    paragraph.FontSize = 26;
                                    paragraph.TextAlignment = TextAlignment.Center;
                                }
                                else
                                    paragraph.FontSize = 20;
                                document.Blocks.Add(paragraph);
                            }
                        }
                        this.showInfo.Document = document;
                    }
                }
                catch (Exception ex)
                {

                }
                finally
                {
                    fs.Close();
                }
            }
        }

        private void scrollviewer_ScrollChanged(object sender, System.Windows.Controls.ScrollChangedEventArgs e)
        {
            m_ScrollStepRatio = scrollviewer.ViewportHeight / (scrollviewer.ExtentHeight - scrollviewer.ViewportHeight);
            m_ScrollPositionRatio = scrollviewer.ContentVerticalOffset / scrollviewer.ScrollableHeight;
            if (e.VerticalChange < 0)
                scrollviewer.SmoothScroll(m_ScrollStepRatio, m_ScrollPositionRatio, ScrollDirection.Up);
            else if (e.VerticalChange > 0)
                scrollviewer.SmoothScroll(m_ScrollStepRatio, m_ScrollPositionRatio, ScrollDirection.Down);
        }
    }
}

 

C#WPF 实现滚动字幕动画 程序设计中有时,如果显示较多的文字,显示不开,这时需要滚动字幕。本文讲解如何实现。 阅读详情

相关推荐

WPF滚动条控件样式

WPF滚动条样式,ScrollViewer控件的使用

WPF效果第一百八十三篇之无缝循环滚动

这不最近一直都在瞎玩Xamarin,渐渐的把WPF给冷落的;假期前突然收到一个着急的模糊不清的需求:图片无缝循环滚动;由于着急我就比较偷懒直接用了很low的方式实现了一版:1、前台就是直接Canvas嵌套StackPanel:<Canvas ClipToBounds="True" x:Name="RootCanvas" Background="#0866AD" He...

dotNET跨平台 1354

WPF listbox 平滑滚动

WPF listbox 平滑滚动

WPF ScrollViewer滚动

使用ScrollChanged事件触发通过偏移量来判断。if (scroll!= null)//当数据不在增加的时候//当数据增加,自动滑动else。

m0_48915942的博客 1730

WPF文字滚动播放效果源码

实现了文字的滚动效果,文字平滑滚入,匆忙退出 其中设计了两种文字,一种是固定文字列表,一种是临时文字列表 在系统闲时循环滚动显示固定文字,当系统有新事件提示信息时按顺序滚动显示临时文字列表 效果还不错,仅供参考

模拟IC设计实战:折叠式共源共栅放大器的参数优化与噪声抑制

本文深入探讨了折叠式共源共栅放大器的核心设计要点。针对低电压下增益与输出摆幅的矛盾,文章详细阐述了从套筒式结构转向折叠式结构的必要性,并重点分析了其参数优化与噪声抑制的实战方法。通过手把手的参数计算流程,指导如何平衡增益、带宽、摆幅与功耗。同时,深入剖析了噪声来源,强调了采用PMOS输入对管以抑制1/f噪声,并提供了针对共栅管及电流镜的噪声优化策略,是模拟IC设计中高性能放大器设计的实用指南。

vv45678的博客 977

WPF中对滚动条进行平滑滚动

11 <Button Content="普通滚动" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" Width="88" Click="Button_Click" Margin="-120,0,0,0"></Button>一开始我想的是通过一个循环,缓动增加Y的位置,这样就达到了动画效果。我们也可以借助WPF的Animation来做,这样效果会更好。7 // 获取选择元素的位置。11 //滚动到指定位置。

【微软MVP】zhaotianff的专栏 1512

超聚变安装银河麒麟服务器系统ky10-server-x86

超聚变-通过BMC口进服务器管理界面如下图为BMC管理口:默认BMC口IP:https://192.168.2.100l浏览器打开网页,输入用户名和密码登陆后,如下图红框处,选择“启动虚拟控制台”——选择“HTML集成远程控制台”系统银河麒麟服务器系统ky10 server x86选择镜像文件X86架构我们一般选择下图2212版本选择启动方式:光驱重启出现安装图形化界面选装安装系统的磁盘系统安装盘选完后如下图,会置灰创建root密码开始安装系统首次进入,有协议界面。

zengliguang的专栏 5958

WPF 如何流畅地滚动ScrollViewer

WPF开发者QQ群:340500857 | 微信群 -> 进入公众号主页加入组织欢迎转发、分享、点赞、在看,谢谢~。前言 看了看原生UWP的ScrollView...

dotNET跨平台 977

fNIRS 公开数据集整理

关注“心仪脑”查看更多脑科学知识的分享。 关键词:数据整理、fNIRS 之前我们向大家推送了 Public Neuroscience Dataset 系列主题的第一期:《EEG公开数据集》,我们同时意识到大家对于神经科学公开数据集的需求。本期是该系列主题的第二期,我们在延续第一期初衷的基础上,整理了功能性近红外光谱(fNIRS)技术的公开数据集。 fNIRS 是一种非侵入性、便携且价格低廉的光学神经成像技术,它具有可观的空间和时间分辨率。因fNIRS技术问世较EEG晚了许多,所以应用此技术开展研究发.

psybrain的博客 4271

python123题目——摩尔斯电码转换

类型:列表元组。

m0_62488776的博客 4414

WPF 控件库——带有惯性的ScrollViewer

一、先看看效果     二、原理   虽然效果很简单,但是网上的一些资料涉及的代码量非常可观,而且效果也不是很理想,滚动的时候没有一个顺滑感。我这里提供的源码一共120多行,就能实现上图的效果。   本质上我们只要接管ScrollViewer的滚动逻辑,并且把这个逻辑替换成带有惯性的即可,那么如何去接管呢?这里的关键是先屏蔽ScrollViewer的鼠标滚轮事件: 1 protected ov...

ahilll的博客 5472

STM32+LoRa模块实战:从环境搭建到数据传输完整指南(附避坑清单)

本文提供STM32与LoRa模块从环境搭建到数据传输的完整实战指南,涵盖硬件连接、开发环境配置、AT指令设置、频段优化及低功耗设计等关键步骤,特别针对常见问题提供解决方案和避坑清单,助力物联网开发者高效实现远距离低功耗通信。

weixin_29168813的博客 289

WPF 使用CompositionTarget.Rendering实现平滑流畅滚动的ScrollViewer,支持滚轮、触控板、触摸屏和笔

为了解决以上问题,本文提出一种新的方案来实现平滑滚动ScrollViewer。该方案在和中直接处理(禁用)了系统的滚动效果,使用事件来驱动滚动动画。并针对滚轮方式和触控“跟手”分别进行优化,使用缓动滚动模型和精确滚动模型来实现平滑滚动。笔的支持得益于库提供的模拟,将笔输入映射为触摸输入。为了最直观和最简单地解决问题,我们将应用场景设置为垂直滚动,水平滚动可以通过类似的方式实现。

weixin_42317730的博客 75

SAP Fiori 会话超时全解析:从 Launchpad 到 Identity Authentication 的统一策略

SAP Fiori会话超时机制解析与配置策略 本文深入探讨SAP Fiori项目中的会话超时机制,分析其对系统安全和用户体验的双重影响。文章系统拆解了SAP Fiori Launchpad与SAP Cloud Identity Services之间的会话超时工作原理,重点介绍了两种超时机制:服务器驱动的超时(通过SESSION_TIMEOUT_STOP_DATA_REFRESH参数控制)和UI驱动的超时(通过SESSION_TIMEOUT_INTERVAL_IN_MINUTES参数控制)。文中结合制造业产线

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 212

HyperLynx(十三)Hyperlynx前放置之对网络的EMC分析

在“Spectrum Analyzer”对话框的“Stimulus”(激励)栏中,设置激励源频率为100MHz,选择“IC modeling”为“Fast-Strong”,并按图所示设置其他选项。显然,在仿真的基频上,它的幅值最大,将鼠标光标置于柱状图上,可以读取其值为64.28mA,这个数值是由选定的驱动芯片决定的。按上图所示的原理图,在接收端增加一个并联的RC负载,再次运行仿真,结果如图所示。在对话框左侧的“Pins”列表中,显示出了已添加电流探针的引脚,可以在此列表中选择所要仿真的目标。...

小幽余生不加糖 4677

在WPF中实现平滑滚动

在WPF中实现平滑滚动 原文:在WPF中实现平滑滚动WPF实现滚动条还是比较方便的,只要在控件外围加上ScrollViewer即可,但美中不足的是:滚动的时候没有动画效果。在滚动的时候添加过渡动画能给我们的软件增色不少,例如Office 2013的滚动的时候支持动画看起来就舒服多了。 之前倒是研究过如何实现这个平滑滚动,不过网上的方案大部分大多...

weixin_30644369的博客 287

修改 Alist 密码时报错?看看这个坑怎么解决!

启动服务后,再修改密码”。以后再遇到类似问题,先检查服务是否正常运行,说不定就能少踩不少坑。如果还有其他 Alist 的问题,欢迎在评论区留言交流~

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1153
上一篇: WPF使用FlowDocument加载文本并修改文本样式
下一篇: C#动态类Dynamic的使用
RunnerDNA
博客等级 码龄14年 575粉丝 97原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RunnerDNA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值