Original text: [WPF custom control library] About ScrollViewer and scroll-wheel-hijack (scroll-wheel-hijack)
1. What is scroll wheel hijacking#
This article introduces a very simple control inherited from ScrollViewer:
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);
}
}
There is so much code. This ExtendedScrollViewer is only used to solve the scroll-wheel-hijack problem. The so-called scroll wheel hijacking, in simple terms, is that the mouse enters a scrollable child element during a scrollable page using the mouse wheel to scroll the page, causing only scrolling in this child element and the entire page wants to scroll. .
Look at this example specifically:
I believe that many people have encountered this situation. After the scroll wheel is “hijacked”, it simply drags the scroll bar. Once I encountered a long page with a lot of ScrollViewer embedded, it was really annoying to use, so I used ExtendedScrollViewer to solve this problem. Of course, there are many other cases of scroll wheel hijacking, and there are many solutions. This article only introduces the situation I encountered and my solution.
2. Implementation#
To prevent ScrollViewer from capturing the mouse in WPF For scrolling time, you can rewrite OnMouseWheel
into an empty method:
protected override void OnMouseWheel(MouseWheelEventArgs e span>) {
}
The OnMouseWheel method is used to respond to the mouse wheel event. Reloading it as an empty method means that the mouse rolling event will no longer be processed. Note that e.Handled = true
cannot be used in this case, because our goal is to allow the outer ScrollViewer to receive mouse wheel events, so the Handled of MouseWheelEventArgs cannot be changed.
Of course, we are not satisfied with disabling the mouse wheel without thinking, we should be smarter, let the ScrollViewer scroll to the bottom first, and then let the outer ScrollViewer scroll down. Several attributes are used here:
The Delta in MouseWheelEventArgs represents the amount of change of the mouse wheel. When this value is positive, it means the wheel is up.
ExtentHeight, get the actual height of the ScrollViewer content.
ViewportHeight, get the height of the current viewable area.
VerticalOffset contains the value of the vertical offset of the scrolling content corresponding to the top of the page. The valid value is between 0 and the value obtained by subtracting ViewportHeight from ExtentHeight.
After being familiar with the functions of the above attributes, we can better control the behavior of the mouse wheel. When the mouse is scrolled upwards, we can judge whether it has been rolled to the top. If so, we will not handle the mouse wheel event:
if (VerticalOffset == 0 && e.Delta >= 0 )
return;
When the mouse scrolls down, it needs to be based on ViewportHeight
, VerticalOffset
And ExtentHeight
to determine whether the current scroll is to the end, if it is, the mouse wheel event is not processed:
if (ViewportHeight + VerticalOffset >= ExtentHeight && e.Delta <= 0)
return;
3. Other ScrollViewer solutions span>#
ScrollViewer still has many ways to play, but I don’t use it frequently in my work so I didn’t do it. If you feel unsatisfied, you can also refer to HandyControl’s ScrollViewer, which directly provides a CanMouseWheel
property to control whether to respond to the mouse wheel, and also supports scrolling and other functions.
4. Reference#
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
p>
ScrollViewer.ViewportHeight Property (System.Windows.Controls) Microsoft Docs
ScrollViewer.VerticalOffset Property (System.Windows.Controls) Microsoft Docs
5. Source code#
ExtendedScrollViewer.cs at master
Copy
Copy
Copy
Copy