前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[WPF自定义控件库] 关于ScrollViewr和滚动轮劫持(scroll-wheel-hijack)

[WPF自定义控件库] 关于ScrollViewr和滚动轮劫持(scroll-wheel-hijack)

作者头像
dino.c
发布2019-08-30 14:32:58
1.2K0
发布2019-08-30 14:32:58
举报
文章被收录于专栏:dino.c的专栏dino.c的专栏

1. 什么是滚动轮劫持

这篇文章介绍一个很简单的继承自ScrollViewer的控件:

代码语言:javascript
复制
public class ExtendedScrollViewer : ScrollViewer
{
    protected override void OnMouseWheel(MouseWheelEventArgs e)
    {
        if (ViewportHeight + VerticalOffset >= ExtentHeight && e.Delta <= 0)
            return;

        if (VerticalOffset == 0 && e.Delta >= 0)
            return;

        base.OnMouseWheel(e);
    }
}

所有代码就这么多,这个ExtendedScrollViewer 只是用来解决滚动轮劫持(scroll-wheel-hijack)的问题。所谓的滚动轮劫持,简单来说即是在一个可以滚动的页面使用鼠标滚轮滚动页面的过程中鼠标进入某个可以滚动的子元素导致只在这个子元素中滚动而整个页面想滚滚不动了。

具体看看这个例子:

这个情况相信很多人都遇到过,滚轮被“劫持”后索性去拖动滚动条。有次我遇到个内嵌了很多ScrollViewer的长页面,使用起来真的很恼人,所以我使用ExtendedScrollViewer 解决了这个问题。当然还有另外很多种情况的滚动轮劫持,也有很多解决方案,这篇文章只介绍我遇到的情况和我的解决方案。

2. 实现

在WPF中要禁止ScrollViewer捕获鼠标滚动时间,可以重写OnMouseWheel成一个空的方法:

代码语言:javascript
复制
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
}

OnMouseWheel方法用于响应鼠标滚轮的事件,将它重载成空方法即不再处理鼠标滚利事件。注意在这种情况下不可以使用e.Handled = true,因为我们的目标是让外层的ScrollViewer可以接收到鼠标滚轮事件,所以不能更改MouseWheelEventArgs 的Handled。

当然我们不满足于无脑禁用鼠标滚轮,我们应该更智能些,先让ScrollViewer滚到底,再交由外层的ScrollViewer滚下去。这里面用到几个属性:

MouseWheelEventArgs中的Delta表示鼠标滚轮的变更量,当这个值为正数时表示滚轮向上。

ExtentHeight,获取ScrollViewer内容的实际高度。

ViewportHeight,获取当前可视区域的高度。

VerticalOffset,包含滚动内容对应于页首的垂直偏移量的值,有效值介于 0 与 ExtentHeight 减去 ViewportHeight 所得的数值之间。

熟悉了上面几个属性的作用后我们可以更好地控制鼠标滚轮的行为,当鼠标向上滚动时,判断现在是否已经滚到顶了,如果是就不处理鼠标滚轮事件:

代码语言:javascript
复制
if (VerticalOffset == 0 && e.Delta >= 0)
    return;

而当鼠标向下滚动时,需要根据ViewportHeightVerticalOffsetExtentHeight判断当前是否已经滚动到底,如果是就不处理鼠标滚轮事件:

代码语言:javascript
复制
if (ViewportHeight + VerticalOffset >= ExtentHeight && e.Delta <= 0)
    return;

3. 其他ScrollViewer方案

ScrollViewer还有很多中玩法,但我工作中不常用到所以就没做。如果觉得不满足还可以参考HandyControl的ScrollViewer,它直接提供了一个CanMouseWheel属性用于控制是否响应鼠标滚轮,另外还支持了滚动等功能。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-08-27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 什么是滚动轮劫持
  • 2. 实现
  • 3. 其他ScrollViewer方案
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档