如何禁用ListBox中的ScrollViewer?

发布于 2024-08-11 16:45:37 字数 623 浏览 8 评论 0 原文

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


我有带有 ItemContainerStyle 的 ListBox,如下所示:

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

How can I set style for ItemContainer's item border in resources like this?据我所知 ContentPresenter 是 ItemsControl 的项目容器。但它没有边框,所以我无法设置它的样式。

I have a ListBox. It has internal ScrollViewer, so I can scroll ListBox content with mouse wheel. It works fine until I set item template that contains another ListBox (in fact, I have 4 nested ListBoxes =)). Problem is that internal ListBox's ScrollViewer steals wheeling event. Is there any easy way to prevent this behavior?


I had ListBox with ItemContainerStyle like this:

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

How can I set style for ItemContainer's item border in resources like this? As I know ContentPresenter is item container of ItemsControl. But it hasn't Border, so I can't style it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

咿呀咿呀哟 2024-08-18 16:45:37

您可以通过将控件模板更改为更简单的内容,从 ListBox 中删除 ScrollViewer

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

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

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

You can remove the ScrollViewer from a ListBox by changing its control template to something much simpler:

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

However, I question the value of nesting ListBoxes. Remember that each ListBox is a Selector and has a concept of which item is "selected". Does it really make sense to have a selected item inside a selected item, inside a selected item?

I would suggest changing the "inner" ListBoxes to simple ItemsControls so that the nested lists can't have selected items. That would make for a much simpler user experience. You may still need to retemplate the inner ItemsControls in the same way to remove the scrollbars, but at least the user won't get confused about which item is "selected".

绿阴红影里的.如风往事 2024-08-18 16:45:37

您可以通过在 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

You can disable stealing scroll events by catching scroll event in XAML:

<ListBox PreviewMouseWheel="ScrollViewer_PreviewMouseWheel">

and re-publishing it in Code behind:

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);
        }
    }

The solution is exactly for ListBox, it helped me with ListView.

I found this solution here:

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

岁月流歌 2024-08-18 16:45:37

我喜欢为这类事情创造一种行为。

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);
    }
}

I like to create a behavior for this type of thing.

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

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

The behavior itself.

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);
    }
}
七堇年 2024-08-18 16:45:37

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

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
         ScrollViewer.VerticalScrollBarVisibility="Disabled" ...
</ListBox>

Sorry for waking up such a old post. Actually, you can disable the ScrollViewer by using ScrollViewer's attached property.

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
         ScrollViewer.VerticalScrollBarVisibility="Disabled" ...
</ListBox>
枕梦 2024-08-18 16:45:37

这是 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".../>

Here is a variant with DependencyProperty, if you don't like behaviors

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);
    }
}

This is how it is used

<Listbox b:IgnoreScrollingBehavior.IgnoreScrolling="True".../>
如何视而不见 2024-08-18 16:45:37

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

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
     ScrollViewer.VerticalScrollBarVisibility="Disabled" ...
</ListBox>

You can use this ! No Wheel stolen.

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
     ScrollViewer.VerticalScrollBarVisibility="Disabled" ...
</ListBox>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文