ListView 中的 WPF 水平滚动条不适用于鼠标滚轮滚动

问题描述 投票:0回答:1

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

c# wpf listview horizontal-scrolling
1个回答
0
投票

可以通过以下步骤完成。

  1. 捕捉 PreviewMouseWheel 事件。
  2. 在 ListView 中获取 ScrollViewer。
  3. ScrollViewer.HorizontalOffset
    获取当前偏移量。
  4. 将鼠标滚轮增量除以某个分隔符添加到偏移量中。
  5. 用偏移量调用
    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>
© www.soinside.com 2019 - 2024. All rights reserved.