【问题标题】:How to disable ScrollViewer in ListBox?如何在 ListBox 中禁用 ScrollViewer?
【发布时间】:2010-12-16 21:20:09
【问题描述】:

我有一个列表框。它有内部 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 的项目容器。但它没有边框,所以我无法设置它的样式。

【问题讨论】:

    标签: wpf xaml listbox scrollviewer


    【解决方案1】:

    您可以将ListBox 中的ScrollViewer 更改为更简单的控件模板,从而将其删除:

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

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

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

    【讨论】:

    • 在选定项中,在选定项中包含选定项真的有意义吗? 是的。否则您将如何从列表中的列表中的列表中选择项目?
    • 这也会从列表框中删除许多其他内容,例如丢弃事件
    • @wotanii 您是否找到了不删除丢弃事件的解决方案? (我使用触摸滚动)
    • 从列表中的列表中选择项目?这不是 Treeviews 的用途吗?
    【解决方案2】:

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

    【讨论】:

    • 谢谢!现在已经找了很久了。它有效!
    • 如果您使用触摸滚动而不是鼠标滚轮,您将如何解决这个问题?
    • 我没有现成的解决方案,无法对其进行测试,但我会开始寻找与触摸屏相关的类似事件并重新发布它们,就像我重新发布的解决方案一样。
    【解决方案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);
        }
    }
    

    【讨论】:

    • 谢谢,我正在寻找使用 MVVM 的解决方案!
    【解决方案4】:

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

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

    【讨论】:

    • 这似乎仍然在窃取轮回事件
    【解决方案5】:

    这里有一个 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".../>
    

    【讨论】:

      【解决方案6】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-17
        • 1970-01-01
        • 1970-01-01
        • 2012-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多