ListView中的WPF水平滚动条在鼠标滚轮滚动时不起作用

nc1teljy  于 2023-04-22  发布在  其他
关注(0)|答案(1)|浏览(454)

我有一个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以向左/向右滚动。

dced5bon

dced5bon1#

它可以通过以下步骤完成。
1.捕获PreviewMouseWheel事件。
1.在ListView中获取ScrollViewer。
1.从ScrollViewer.HorizontalOffset获取当前偏移。
1.将鼠标滚轮增量除以某个分隔符添加到偏移量中。
1.使用偏移量调用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>

相关问题