[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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM