专栏首页dino.c的专栏[WPF]使用附加属性处理 ScrollViewer 的滚动轮劫持问题

[WPF]使用附加属性处理 ScrollViewer 的滚动轮劫持问题

之前写过一篇博客 关于 ScrollViewer 和滚动轮劫持(scroll-wheel-hijack),里面介绍了 ScrollViewer 的滚动轮劫持问题,以及如果解决。当时的做法是继承 ScrollViewer 并重写 OnMouseWheel,全部代码如下:

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

最近有人提到能不能使用附加属性处理,所以我就试试。暂时发现简单地用附加属性处理,除非查找 VisualTree 上的父节点 ScrollView 并调用它的 LineUp 和 LineDown ,全部代码如下:

public class ScrollViewerService
{


    /// <summary>
    /// 从指定元素获取 CanScrollOuter 依赖项属性的值。
    /// </summary>
    /// <param name="obj">从中读取属性值的元素。</param>
    /// <returns>从属性存储获取的属性值。</returns>
    public static bool GetCanScrollOuter(DependencyObject obj) => (bool)obj.GetValue(CanScrollOuterProperty);

    /// <summary>
    /// 将 CanScrollOuter 依赖项属性的值设置为指定元素。
    /// </summary>
    /// <param name="obj">对其设置属性值的元素。</param>
    /// <param name="value">要设置的值。</param>
    public static void SetCanScrollOuter(DependencyObject obj, bool value) => obj.SetValue(CanScrollOuterProperty, value);

    /// <summary>
    /// 标识 CanScrollOuter 依赖项属性。
    /// </summary>
    public static readonly DependencyProperty CanScrollOuterProperty =
        DependencyProperty.RegisterAttached("CanScrollOuter", typeof(bool), typeof(ScrollViewerService), new PropertyMetadata(default(bool), OnCanScrollOuterChanged));


    private static void OnCanScrollOuterChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        var oldValue = (bool)args.OldValue;
        var newValue = (bool)args.NewValue;
        if (newValue == false)
            return;

        var target = obj as ScrollViewer;
        target.PreviewMouseWheel += (s, e) =>
          {
              if (target.ViewportHeight + target.VerticalOffset >= target.ExtentHeight && e.Delta <= 0
              || target.VerticalOffset == 0 && e.Delta >= 0)
              {
                  var parent = target.GetVisualAncestors().OfType<ScrollViewer>().FirstOrDefault();

                  if (parent == null)
                      return;

                  if (e.Delta < 0)
                      parent.LineDown();
                  else
                      parent.LineUp();
              }
          };
    }

}

处理不够优雅,但将就着用吧。

参考

[UWP]附加属性1:概述

ScrollViewer.OnMouseWheel(MouseWheelEventArgs) Method (System.Windows.Controls) Microsoft Docs

MouseWheelEventArgs.Delta Property (System.Windows.Input) Microsoft Docs

ScrollViewer.ExtentHeight Property (System.Windows.Controls) Microsoft Docs

ScrollViewer.ViewportHeight Property (System.Windows.Controls) Microsoft Docs

ScrollViewer.VerticalOffset Property (System.Windows.Controls) Microsoft Docs

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 重温《单元测试的艺术》,总结常用知识点

    前几个月重温了单元测试的艺术。毕竟是14年的书内容有点旧,于是试着结合书中的内容和一些新的知识点写进这篇文章,希望对自己及各位读者有帮助。

    dino.c
  • [UWP]如何使用代码创建DataTemplate(或者ControlTemplate)

    在UWP中DataTemplate是一个十分重要的功能,并且几乎无处不在,例如DataGrid中的DataGridTemplateColumn:

    dino.c
  • [Silverlight]简单实现DataGrid使用CheckBox选择行

    以前写过几个方法实现这个功能,但最终还是选择了不继承DataGrid,所以再重新发布出来。

    dino.c
  • Android中的Handler机制中的问题总结

    Handler是如何实现定时唤醒的,其实也就是通过epoll中的timeout来进行阻塞唤醒的.

    None_Ling
  • python pyqt5 QTreeWidget 点击事件

    from PyQt5.QtWidgets import * import sys

    用户5760343
  • [JDK] SynchronousQueue 源码阅读【1】

    架构探险之道
  • 使用Python+OpenCV进行图像处理(二)| 视觉入门

    【前言】图像预处理对于整个图像处理任务来讲特别重要。如果我们没有进行恰当的预处理,无论我们有多么好的数据也很难得到理想的结果。

    磐创AI
  • cv2.cvtColor

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    于小勇
  • Kafka源码系列之使用要点总结及重要错误解决

    1,创建一个topic bin/kafka-topics.sh --create --zookeeper localhost:2181 --replicatio...

    Spark学习技巧
  • 如何结合网络情况有效实现智慧工地视频监控平台的多方案需求

    因这位用户现场网络情况复杂,现需要将两套支持不同协议的流媒体服务器和一套视频云管理平台部署在内网同一网段下,其中国标的流媒体服务器和视频云管理平台需要发布到公网...

    EasyNVR

扫码关注云+社区

领取腾讯云代金券