ody*_*yth 26 .net c# wpf scrollwheel listbox
我有一个usercontrol,它有一个scrollviewer,然后是一堆子控件,如文本框,单选按钮和列表框等.我可以使用鼠标滚轮滚动父滚动查看器,直到我的鼠标落入列表框,然后,鼠标滚轮事件开始进入列表框.是否有任何方法让列表框将这些事件发送回父控件?从父控件的内侧删除列表框就像这个问题所示(当ScrollViewer的子控件超过时鼠标滚轮不工作)不是一个解决方案.
我试过了
void ListBox_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
e.Handled = true;
}
Run Code Online (Sandbox Code Playgroud)
但那也没有用.
谢谢
Sim*_*Fox 35
您引用的答案正是造成问题的原因,ScrollViewer中的ListBox(由ScrollViewer等组成)捕获MouseWheel事件并处理它,防止它冒泡,因此ScrollViewer不知道事件曾经发生过.
使用以下极其简单的ControlTemplate为ListBox演示(注意它没有ScrollViewer,因此不会捕获MouseWheel事件)ScrollViewer仍然会用鼠标滚动ListBox.
<UserControl.Resources>
<ControlTemplate x:Key="NoScroll">
<ItemsPresenter></ItemsPresenter>
</ControlTemplate>
</UserControl.Resources>
<ScrollViewer>
<SomeContainerControl>
<.... what ever other controls are inside your ScrollViewer>
<ListBox Template="{StaticResource NoScroll}"></ListBox>
<SomeContainerControl>
</ScrollViewer>
Run Code Online (Sandbox Code Playgroud)
您可以选择在鼠标进入ScrollViewer时捕获鼠标,因此它会继续接收所有鼠标事件,直到释放鼠标为止,但是此选项需要您将任何进一步的鼠标事件传递给ScrollViewer中包含的控件(如果您想要一个响应...以下MouseEnter MouseLeave事件处理程序就足够了.
private void ScrollViewerMouseEnter(object sender, MouseEventArgs e)
{
((ScrollViewer)sender).CaptureMouse();
}
private void ScrollViewerMouseLeave(object sender, MouseEventArgs e)
{
((ScrollViewer)sender).ReleaseMouseCapture();
}
Run Code Online (Sandbox Code Playgroud)
我提供的解决方法都不是真的首选,我建议重新考虑你实际上要做的事情.如果你在你的问题中解释你想要实现的目标,我相信你会得到更多的建议......
Ama*_*duh 28
这可以通过附加行为来完成.
http://josheinstein.com/blog/index.php/2010/08/wpf-nested-scrollviewer-listbox-scrolling/
编辑:这是链接的解决方案:
"所以我提出了以下IgnoreMouseWheelBehavior.从技术上讲,它并没有忽略MouseWheel,而是将事件"转发"回来并从ListBox中退出.检查它."
/// <summary>
/// Captures and eats MouseWheel events so that a nested ListBox does not
/// prevent an outer scrollable control from scrolling.
/// </summary>
public sealed class IgnoreMouseWheelBehavior : Behavior<UIElement>
{
protected override void OnAttached( )
{
base.OnAttached( );
AssociatedObject.PreviewMouseWheel += AssociatedObject_PreviewMouseWheel ;
}
protected override void OnDetaching( )
{
AssociatedObject.PreviewMouseWheel -= AssociatedObject_PreviewMouseWheel;
base.OnDetaching( );
}
void AssociatedObject_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
e.Handled = true;
var e2 = new MouseWheelEventArgs(e.MouseDevice,e.Timestamp,e.Delta);
e2.RoutedEvent = UIElement.MouseWheelEvent;
AssociatedObject.RaiseEvent(e2);
}
}
Run Code Online (Sandbox Code Playgroud)
以下是如何在XAML中使用它.
<ScrollViewer Name="IScroll">
<ListBox Name="IDont">
<i:Interaction.Behaviors>
<local:IgnoreMouseWheelBehavior />
</i:Interaction.Behaviors>
</ListBox>
</ScrollViewer>
Run Code Online (Sandbox Code Playgroud)
i命名空间来自Blend:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Run Code Online (Sandbox Code Playgroud)
qua*_*ium 12
我遵循Amanduh的方法来解决滚动查看器中的多个数据网格所遇到的同样问题,但是在WPF中:
public sealed class IgnoreMouseWheelBehavior
{
public static bool GetIgnoreMouseWheel(DataGrid gridItem)
{
return (bool)gridItem.GetValue(IgnoreMouseWheelProperty);
}
public static void SetIgnoreMouseWheel(DataGrid gridItem, bool value)
{
gridItem.SetValue(IgnoreMouseWheelProperty, value);
}
public static readonly DependencyProperty IgnoreMouseWheelProperty =
DependencyProperty.RegisterAttached("IgnoreMouseWheel", typeof(bool),
typeof(IgnoreMouseWheelBehavior), new UIPropertyMetadata(false, OnIgnoreMouseWheelChanged));
static void OnIgnoreMouseWheelChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
var item = depObj as DataGrid;
if (item == null)
return;
if (e.NewValue is bool == false)
return;
if ((bool)e.NewValue)
item.PreviewMouseWheel += OnPreviewMouseWheel;
else
item.PreviewMouseWheel -= OnPreviewMouseWheel;
}
static void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
e.Handled = true;
var e2 = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
{RoutedEvent = UIElement.MouseWheelEvent};
var gv = sender as DataGrid;
if (gv != null) gv.RaiseEvent(e2);
}
}
Run Code Online (Sandbox Code Playgroud)
正如Simon所说,标准ListBox模板中的ScrollViewer正在捕捉事件.要绕过它,您可以提供自己的模板.
<ControlTemplate x:Key="NoWheelScrollListBoxTemplate" TargetType="ListBox">
<Border BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="1,1,1,1" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" Name="Bd" SnapsToDevicePixels="True">
<!-- This is the new control -->
<l:NoWheelScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</l:NoWheelScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsEnabled" Value="False">
<Setter TargetName="Bd" Property="Panel.Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
</Trigger>
<Trigger Property="ItemsControl.IsGrouping" Value="True">
<Setter Property="ScrollViewer.CanContentScroll" Value="False" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Run Code Online (Sandbox Code Playgroud)
NoWheelScrollViewer的实现非常简单.
public class NoWheelScrollViewer : ScrollViewer
{
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
// Do nothing
}
}
Run Code Online (Sandbox Code Playgroud)
然后,只要您希望列表框不处理鼠标滚轮.
<ListBox Template="{StaticResource NoWheelScrollListBoxTemplate}">
Run Code Online (Sandbox Code Playgroud)