using System.Windows; using System.Windows.Controls; using System.Windows.Input; using PropertyMetadata = System.Windows.PropertyMetadata; namespace YY.Admin.Core.Helper { /// /// ScrollViewer 辅助类: /// 解决 ScrollViewer 包裹 TreeView / ListBox 等控件时, /// 鼠标滚轮在内部控件上无法触发外层 ScrollViewer 滚动的问题。 /// public static class ScrollViewerHelper { /// /// 附加属性:是否启用鼠标滚轮事件向上传递 /// public static readonly DependencyProperty EnableMouseWheelPropagationProperty = DependencyProperty.RegisterAttached( "EnableMouseWheelPropagation", // 属性名 typeof(bool), // 属性类型 typeof(ScrollViewerHelper), // 所属类型 new PropertyMetadata(false, OnEnableMouseWheelPropagationChanged)); // 默认值+回调 /// /// 获取附加属性值(XAML 绑定/读取) /// public static bool GetEnableMouseWheelPropagation(DependencyObject obj) => (bool)obj.GetValue(EnableMouseWheelPropagationProperty); /// /// 设置附加属性值(XAML 设置) /// public static void SetEnableMouseWheelPropagation(DependencyObject obj, bool value) => obj.SetValue(EnableMouseWheelPropagationProperty, value); /// /// 当附加属性值发生变化时触发 /// private static void OnEnableMouseWheelPropagationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is UIElement element) { // 如果启用,则订阅 PreviewMouseWheel 事件 if ((bool)e.NewValue) element.PreviewMouseWheel += Element_PreviewMouseWheel; else // 否则移除事件 element.PreviewMouseWheel -= Element_PreviewMouseWheel; } } /// /// 当鼠标滚轮在目标控件上滚动时触发, /// 将事件手动冒泡到上层(如 ScrollViewer)以实现滚动。 /// private static void Element_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { // 若事件已被处理,则直接返回 if (e.Handled) return; // 标记事件已处理,防止重复触发 e.Handled = true; // 构造一个新的 MouseWheelEventArgs,用于向父级转发 var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta) { RoutedEvent = UIElement.MouseWheelEvent, // 指定为标准鼠标滚轮事件 Source = sender // 来源设为当前控件 }; // 获取父元素,并将事件重新抛出 if (sender is Control control) { var parent = control.Parent as UIElement; parent?.RaiseEvent(eventArg); } } } }