我有一个 ListView,其中有很多水平排列的项目,如果我按住滚动条然后移动它,我可以滚动 ListView,但我想用鼠标滚轮向上/向下滚动 ListView 以向左/向右滚动。
<Grid>
<ListView
Margin="10,0,10,0"
AllowDrop="True"
DragEnter="ListView_DragEnter"
DragOver="ListView_PreviewDragOver"
Drop="ListView_Drop"
ItemsSource="{Binding Path=Devices}"
KeyUp="ListView_KeyUp"
PreviewMouseLeftButtonDown="ListView_PreviewMouseLeftButtonDown"
PreviewMouseMove="ListView_PreviewMouseMove"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
TouchDown="ListView_TouchDown"
TouchMove="ListView_TouchMove">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</Grid>
鼠标滚轮的水平滚动不起作用。 我想用鼠标滚轮向上/向下滚动 ListView 以向左/向右滚动。
可以通过以下步骤完成。
ScrollViewer.HorizontalOffset
获取当前偏移量。ScrollViewer.ScrollToHorizontalOffset
。对于分隔线,120 将作为起点,因为它是默认的鼠标滚轮单位。
这是带有附加属性的示例。
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
internal static class ListBoxHelper
{
public static int GetHorizontalScrollDivider(DependencyObject obj)
{
return (int)obj.GetValue(HorizontalScrollDividerProperty);
}
public static void SetHorizontalScrollDivider(DependencyObject obj, int value)
{
obj.SetValue(HorizontalScrollDividerProperty, value);
}
public static readonly DependencyProperty HorizontalScrollDividerProperty =
DependencyProperty.RegisterAttached(
"HorizontalScrollDivider",
typeof(int),
typeof(ListBoxHelper),
new PropertyMetadata(
defaultValue: 0,
propertyChangedCallback: (d, e) =>
{
if (d is not ListBox listBox)
return;
switch ((int)e.OldValue, (int)e.NewValue)
{
case (0, not 0):
listBox.PreviewMouseWheel += OnPreviewMouseWheel;
break;
case (_, 0):
listBox.PreviewMouseWheel -= OnPreviewMouseWheel;
break;
}
}));
private static void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
var listBox = (ListBox)sender;
if (!listBox.TryFindDescendant(out ScrollViewer? viewer))
return;
int divider = GetHorizontalScrollDivider(listBox);
double offset = viewer.HorizontalOffset;
offset += e.Delta / (double)divider;
viewer.ScrollToHorizontalOffset(offset);
}
}
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Media;
public static class DependencyObjectExtensions
{
public static bool TryFindDescendant<T>(this DependencyObject reference, [NotNullWhen(true)] out T? descendant) where T : DependencyObject
{
var queue = new Queue<DependencyObject>();
var parent = reference;
while (parent is not null)
{
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
if (child is T buffer)
{
descendant = buffer;
return true;
}
queue.Enqueue(child);
}
parent = (0 < queue.Count) ? queue.Dequeue() : null;
}
descendant = default;
return false;
}
}
然后,就可以像这样在Xaml中使用了
<ListView local:ListBoxHelper.HorizontalScrollDivider="120">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>