前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[WPF]使用附加属性处理 ScrollViewer 的滚动轮劫持问题

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

作者头像
dino.c
发布2020-06-10 10:35:30
9280
发布2020-06-10 10:35:30
举报
文章被收录于专栏:dino.c的专栏dino.c的专栏

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

代码语言: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);
    }
}

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

代码语言:javascript
复制
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

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档