110 lines
2.6 KiB
C#
110 lines
2.6 KiB
C#
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
|
|
namespace WxOrder.Framework.Commons
|
|
{
|
|
/// <summary>
|
|
/// 让页面级 ScrollViewer 在鼠标悬停在子控件(如 DataGrid、图表等)上时也能随鼠标滚轮滚动。
|
|
/// 用法:在 ScrollViewer 上设置 common:ScrollViewerBehavior.FixMouseWheel="True"。
|
|
/// </summary>
|
|
public static class ScrollViewerBehavior
|
|
{
|
|
public static readonly DependencyProperty FixMouseWheelProperty =
|
|
DependencyProperty.RegisterAttached(
|
|
"FixMouseWheel",
|
|
typeof(bool),
|
|
typeof(ScrollViewerBehavior),
|
|
new PropertyMetadata(false, OnFixMouseWheelChanged));
|
|
|
|
public static bool GetFixMouseWheel(DependencyObject obj)
|
|
=> (bool)obj.GetValue(FixMouseWheelProperty);
|
|
|
|
public static void SetFixMouseWheel(DependencyObject obj, bool value)
|
|
=> obj.SetValue(FixMouseWheelProperty, value);
|
|
|
|
private static void OnFixMouseWheelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
if (!(d is ScrollViewer scrollViewer))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ((bool)e.NewValue)
|
|
{
|
|
scrollViewer.PreviewMouseWheel += OnPreviewMouseWheel;
|
|
}
|
|
else
|
|
{
|
|
scrollViewer.PreviewMouseWheel -= OnPreviewMouseWheel;
|
|
}
|
|
}
|
|
|
|
private static void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
|
|
{
|
|
if (e.Handled || !(sender is ScrollViewer scrollViewer) || scrollViewer.ScrollableHeight <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!(e.OriginalSource is DependencyObject original))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 从鼠标所在控件向上查找,确认它属于当前 ScrollViewer
|
|
var current = original;
|
|
var inside = false;
|
|
while (current != null)
|
|
{
|
|
if (ReferenceEquals(current, scrollViewer))
|
|
{
|
|
inside = true;
|
|
break;
|
|
}
|
|
|
|
// 若鼠标位于一个能自行纵向滚动的内部 ScrollViewer 上(例如下拉列表、
|
|
// 启用了滚动的表格),则交给内部处理,避免抢走它的滚动。
|
|
if (current is ScrollViewer inner &&
|
|
inner.ComputedVerticalScrollBarVisibility == Visibility.Visible &&
|
|
inner.ScrollableHeight > 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
current = VisualTreeHelper.GetParent(current);
|
|
}
|
|
|
|
if (!inside)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 按系统默认的滚轮行数滚动当前页面
|
|
var lines = (int)(e.Delta / Mouse.MouseWheelDeltaForOneLine * SystemParameters.WheelScrollLines);
|
|
if (lines == 0)
|
|
{
|
|
lines = e.Delta > 0 ? 1 : -1;
|
|
}
|
|
|
|
if (lines < 0)
|
|
{
|
|
for (var i = 0; i < -lines; i++)
|
|
{
|
|
scrollViewer.LineDown();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (var i = 0; i < lines; i++)
|
|
{
|
|
scrollViewer.LineUp();
|
|
}
|
|
}
|
|
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
}
|