我有一个ListBox。它有内部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的项容器。但它没有边框,所以我无法设计它。
答案 0 :(得分:46)
您可以通过将其控件模板更改为更简单的方式从ScrollViewer
中删除ListBox
:
<ListBox>
<ListBox.Template>
<ControlTemplate>
<ItemsPresenter />
</ControlTemplate>
</ListBox.Template>
...
</ListBox>
但是,我质疑嵌套ListBoxes的价值。请记住,每个ListBox
都是一个选择器,并且具有“选择”项目的概念。在所选项目内的所选项目中选择项目是否真的有意义?
我建议将“内部”ListBoxes
更改为简单ItemsControls
,以便嵌套列表不能包含所选项目。这将使用户体验更加简单。您可能仍需要以相同的方式重新模拟内部ItemsControls
以删除滚动条,但至少用户不会对哪个项目被“选中”感到困惑。
答案 1 :(得分:3)
您可以通过在XAML中捕捉滚动事件来禁用窃取滚动事件:
<ListBox PreviewMouseWheel="ScrollViewer_PreviewMouseWheel">
并在Code中重新发布它:
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。
我在这里找到了这个解决方案:
答案 2 :(得分:0)
我喜欢为这种事情创建行为。
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);
}
}
答案 3 :(得分: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".../>
答案 4 :(得分:-1)
你可以用这个!没有车轮被盗。
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled" ...
</ListBox>