擷取滑鼠滾輪事件的簡單行為

實現行為

當內部事件處於其上限或下限時,此行為將導致內部 ScrollViewer 的滑鼠滾輪事件冒泡到父 ScrollViewer。如果沒有這種行為,事件將永遠不會超出內部的時間。

public class BubbleMouseWheelEvents : Behavior<UIElement>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.PreviewMouseWheel += PreviewMouseWheel;
    }

    protected override void OnDetaching()
    {
        this.AssociatedObject.PreviewMouseWheel -= PreviewMouseWheel;
        base.OnDetaching();
    }

    private void PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        var scrollViewer = AssociatedObject.GetChildOf<ScrollViewer>(includeSelf: true);
        var scrollPos = scrollViewer.ContentVerticalOffset;
        if ((scrollPos == scrollViewer.ScrollableHeight && e.Delta < 0) || (scrollPos == 0 && e.Delta > 0))
        {
            UIElement rerouteTo = AssociatedObject;
            if (ReferenceEquals(scrollViewer, AssociatedObject))
            {
                rerouteTo = (UIElement) VisualTreeHelper.GetParent(AssociatedObject);
            }

            e.Handled = true;
            var e2 = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
            e2.RoutedEvent = UIElement.MouseWheelEvent;
            rerouteTo.RaiseEvent(e2);
        }
    }
}

行為是 Behavior<T> 基類的子類,T 是它能夠附加的控制元件型別,在本例中為 UIElement。當從 XAML 例項化 Behavior 時,呼叫 OnAttached 方法。此方法允許行為掛鉤來自它所附加的控制元件的事件(通過 AssociatedControl)。類似的方法,當需要從關聯元素取消掛鉤行為時,呼叫 OnDetached。應注意刪除任何事件處理程式,或以其他方式清理物件以避免記憶體洩漏。

此行為會掛鉤到 PreviewMouseWheel 事件,該事件會在 ScrollViewer 有機會檢視之前對其進行更改以攔截事件。它檢查位置以檢視是否需要將事件沿可視樹轉發到任何更高層次的層次。如果是這樣,它將 e.Handled 設定為 true 以防止事件的預設操作。然後它提出了一個新的 MouseWheelEvent 路由到 AssociatedObject。否則,事件將正常路由。

將行為附加到 XAML 中的元素

首先,必須先將 interactivity xml-namespace 引入範圍,然後才能在 XAML 中使用它。將以下行新增到 XAML 的名稱空間。

xmlns:interactivity =“ http://schemas.microsoft.com/expression/2010/interactivity

可以像這樣附加行為:

<ScrollViewer>
    <!--...Content...-->
    <ScrollViewer>
        <interactivity:Interaction.Behaviors>
            <behaviors:BubbleMouseWheelEvents />
        </interactivity:Interaction.Behaviors>
        <!--...Content...-->
    </ScrollViewer>
    <!--...Content...-->.
</ScrollViewer>

這將建立一個 Behaviors 集合作為內部 ScrollViewer 上的附加屬性,其中包含 BubbleMouseWheelEvents 行為。

此特定行為也可以附加到包含嵌入式 ScrollViewer 的任何現有控制元件,例如 GridView,並且它仍然可以正常執行。