如何在 ListBox 中禁用 ScrollViewer?
Posted
技术标签:
【中文标题】如何在 ListBox 中禁用 ScrollViewer?【英文标题】:How to disable ScrollViewer in ListBox? 【发布时间】: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 的项目容器。但它没有边框,所以我无法设置它的样式。
【问题讨论】:
【参考方案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>
【讨论】:
以上是关于如何在 ListBox 中禁用 ScrollViewer?的主要内容,如果未能解决你的问题,请参考以下文章
如何禁用 PrimeReact ListBox 中的列表项之一?
ListBox 选择时禁用突出显示 - Windows Phone 7