如何启用鼠标的水平滚动?
问题的出现原因是用户想要通过鼠标实现水平滚动,但是在没有ScrollViewer的情况下不知道如何添加PreviewMouseWheel事件。
解决方法是通过将PreviewMouseWheel事件添加到ScrollViewer中,并检查Shift键是否按下(或者其他你想要指示水平滚动的方式),然后根据MouseWheelEventArgs的Delta值调用LineLeft或LineRight(或者PageLeft/PageRight)。
用户提出了一个问题,即在没有ScrollViewer的情况下如何添加PreviewMouseWheel事件。其他用户回答说,ListBox的控件模板中应该有一个ScrollViewer,所以像ScrollViewer.VerticalScrollBarVisibility="Disabled"这样的附加属性可以起作用。
然而,问题仍然存在,即如何在不重写控件模板的情况下附加ScrollViewer的PreviewMouseWheel事件(因为这样会破坏自动操作系统相关的主题)。
其他用户猜测可能需要遍历可视化树来找到ScrollViewer(不确定,因为这个答案已经是3年前的了)。
如何使用鼠标启用水平滚动?
问题的出现原因:代码中存在一些bug,例如没有过滤Shift键、同时水平和垂直滚动(运动为对角线)以及无法通过将属性设置为false来禁用该行为。
解决方法:将下面的代码添加到您的代码中,然后在XAML中,在任何包含ScrollViewer的UIElement上将附加属性设置为true。
public static class ScrollViewerHelper { public static readonly DependencyProperty ShiftWheelScrollsHorizontallyProperty = DependencyProperty.RegisterAttached("ShiftWheelScrollsHorizontally", typeof(bool), typeof(ScrollViewerHelper), new PropertyMetadata(false, UseHorizontalScrollingChangedCallback)); private static void UseHorizontalScrollingChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { var element = d as UIElement; if (element == null) throw new Exception("Attached property must be used with UIElement."); if ((bool)e.NewValue) element.PreviewMouseWheel += OnPreviewMouseWheel; else element.PreviewMouseWheel -= OnPreviewMouseWheel; } private static void OnPreviewMouseWheel(object sender, MouseWheelEventArgs args) { var scrollViewer = ((UIElement)sender).FindDescendant(); if (scrollViewer == null) return; if (Keyboard.Modifiers != ModifierKeys.Shift) return; if (args.Delta < 0) scrollViewer.LineRight(); else scrollViewer.LineLeft(); args.Handled = true; } public static void SetShiftWheelScrollsHorizontally(UIElement element, bool value) => element.SetValue(ShiftWheelScrollsHorizontallyProperty, value); public static bool GetShiftWheelScrollsHorizontally(UIElement element) => (bool)element.GetValue(ShiftWheelScrollsHorizontallyProperty); [CanBeNull] private static T FindDescendant ([CanBeNull] this DependencyObject d) where T : DependencyObject { if (d == null) return null; var childCount = VisualTreeHelper.GetChildrenCount(d); for (var i = 0; i < childCount; i++) { var child = VisualTreeHelper.GetChild(d, i); var result = child as T ?? FindDescendant (child); if (result != null) return result; } return null; } }
以上是一种完整的行为。将上述类添加到您的代码中,然后在XAML中,在任何包含ScrollViewer的UIElement上将附加属性设置为true。
在解决方法中还提到了一些问题和修改方法,例如在XAML文件中出现的错误,需要设置一个xmlns,以映射到该类的CLR命名空间。还提到了Get和Set属性的名称错误问题,需要将其更改为"SetShiftWheelScrollsHorizontally"和"GetShiftWheelScrollsHorizontally"。另外还提到了使用"LineRight()"和"LineLeft()"可能会比较慢,可以使用"scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + -args.Delta)"来代替。最后还指出了代码中引用了ItemsControl,但答案中说"将附加属性设置为true的任何包含ScrollViewer的UIElement"。解决方法是将UIElement替换为ItemsControl。
希望以上内容对您有所帮助。