16

我有一个列表框。它有内部 ScrollViewer,所以我可以用鼠标滚轮滚动 ListBox 内容。在我设置包含另一个 ListBox 的项目模板之前它工作正常(事实上,我有 4 个嵌套的 ListBoxes =))。问题是内部 ListBox 的 ScrollViewer 窃取了滚动事件。有什么简单的方法可以防止这种行为吗?


我有 ListBox 和 ItemContainerStyle 像这样:

<Style x:Key="ListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
    <Setter Property="BorderBrush" Value="Black"/>
     ... 
</Style>
<ListBox ItemContainerStyle="{StaticResource ListBoxItemStyle}" />

如何在这样的资源中为 ItemContainer 的项目边框设置样式?据我所知,ContentPresenter 是 ItemsControl 的项目容器。但它没有边框,所以我无法设置它的样式。

4

6 回答 6

59

您可以通过将其控制模板更改为更简单的东西来ScrollViewer从 a中删除:ListBox

<ListBox>
    <ListBox.Template>
        <ControlTemplate>
            <ItemsPresenter />
        </ControlTemplate>
    </ListBox.Template>
    ...
</ListBox>

但是,我质疑嵌套 ListBox 的价值。请记住,每个ListBox都是一个选择器,并且具有“选择”哪个项目的概念。在选定项目中,在选定项目中包含选定项目真的有意义吗?

我建议将“内部”更改ListBoxes为简单ItemsControls,以便嵌套列表不能包含选定项目。这将使用户体验更加简单。您可能仍然需要以ItemsControls相同的方式重新模板内部以删除滚动条,但至少用户不会对“选择”哪个项目感到困惑。

于 2009-11-15T23:35:52.960 回答
12

您可以通过在 XAML 中捕获滚动事件来禁用窃取滚动事件:

<ListBox PreviewMouseWheel="ScrollViewer_PreviewMouseWheel">

并在后面的代码中重新发布它:

private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        if (sender is ListBox && !e.Handled)
        {
            e.Handled = true;
            var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
            eventArg.RoutedEvent = UIElement.MouseWheelEvent;
            eventArg.Source = sender;
            var parent = ((Control)sender).Parent as UIElement;
            parent.RaiseEvent(eventArg);
        }
    }

该解决方案完全适用于 ListBox,它帮助我使用 ListView。

我在这里找到了这个解决方案:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/3a3bb6b0-e088-494d-8ef2-60814415fd89/swallowing-mouse-scroll?forum=wpf

于 2017-12-30T16:26:08.650 回答
3

我喜欢为这种类型的事物创建一种行为。

xmlns:bhv="http://schemas.microsoft.com/xaml/behaviors"

<ListView ItemsSource="{Binding Items}">
    <bhv:Interaction.Behaviors>
        <bhvs:NoScrollingBehavior/>
    </bhv:Interaction.Behaviors>
</ListView>

行为本身。

public class NoScrollingBehavior : Behavior<UIElement>
{
    public NoScrollingBehavior()
    { }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.PreviewMouseWheel += PreviewMouseWheel;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.PreviewMouseWheel -= PreviewMouseWheel;
        base.OnDetaching();
    }

    private void PreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        e.Handled = true;
        var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
        eventArg.RoutedEvent = UIElement.MouseWheelEvent;
        eventArg.Source = sender;
        var parent = ((Control)sender).Parent as UIElement;
        parent.RaiseEvent(eventArg);
    }
}
于 2020-11-02T19:22:08.223 回答
2

抱歉唤醒了这么老的帖子。实际上,您可以使用 ScrollViewer 的附加属性来禁用 ScrollViewer。

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
         ScrollViewer.VerticalScrollBarVisibility="Disabled" ...
</ListBox>
于 2016-08-16T03:44:49.243 回答
0

这是 DependencyProperty 的变体,如果您不喜欢行为

public class IgnoreScrollingBehavior
{
    public static readonly DependencyProperty IgnoreScrollingProperty =
        DependencyProperty.RegisterAttached("IgnoreScrolling", typeof(bool),
            typeof(IgnoreScrollingBehavior), new UIPropertyMetadata(false, OnIgnoreScrollingChanged));

    public static bool GetIgnoreScrolling(UIElement uIElement)
    {
        return (bool)uIElement.GetValue(IgnoreScrollingProperty);
    }

    public static void SetIgnoreScrolling(UIElement uIElement, bool value)
    {
        uIElement.SetValue(IgnoreScrollingProperty, value);
    }

    private static void OnIgnoreScrollingChanged(DependencyObject depOpj, DependencyPropertyChangedEventArgs e)
    {
        if (depOpj is not UIElement item)
        {
            return;
        }

        if (e.NewValue is bool boolean)
        {
            if (boolean)
            {
                item.PreviewMouseWheel += OnPreviewMouseWheel;
            }
            else
            {
                item.PreviewMouseWheel -= OnPreviewMouseWheel;
            }
        }
    }

    private static void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
    {
        e.Handled = true;
        MouseWheelEventArgs eventArg = new(e.MouseDevice, e.Timestamp, e.Delta)
        {
            RoutedEvent = UIElement.MouseWheelEvent,
            Source = sender
        };
        UIElement parent = ((Control)sender).Parent as UIElement;
        parent.RaiseEvent(eventArg);
    }
}

这就是它的使用方式

<Listbox b:IgnoreScrollingBehavior.IgnoreScrolling="True".../>
于 2021-07-18T08:49:46.557 回答
-1

你可以用这个!没有轮子被盗。

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
     ScrollViewer.VerticalScrollBarVisibility="Disabled" ...
</ListBox>
于 2017-11-24T21:38:40.310 回答