M. *_*ley 54 wpf listview scroll event-bubbling
在我的WPF应用程序我有一个ListView其ScrollViewer.VerticalScrollBarVisibility设置为Disabled.它包含在一个ScrollViewer.当我尝试使用鼠标滚轮时ListView,外部ScrollViewer不会滚动,因为它ListView正在捕获滚动事件.
如何强制ListView允许滚动事件冒泡到ScrollViewer?
key*_*yle 82
您需要在内部列表视图中捕获预览鼠标滚轮事件
ctl.PreviewMouseWheel += PreviewMouseWheel;
Run Code Online (Sandbox Code Playgroud)
然后停止滚动listview并在父列表视图中引发事件.
private static void PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
if (!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);
}
}
Run Code Online (Sandbox Code Playgroud)
几个月前,@ robert-wagner为我解决了这个问题.
mak*_*akc 37
使用附加行为的另一个好方案.我喜欢它,因为它破坏了Control的解决方案.
创建一个无滚动行为,它将捕获PreviewMouseWheel(Tunneling)事件并引发一个新的MouseWheelEvent(冒泡)
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)
然后将行为附加到具有嵌套ScrollViewers案例的任何UIElement
<ListBox Name="ForwardScrolling">
<i:Interaction.Behaviors>
<local:IgnoreMouseWheelBehavior />
</i:Interaction.Behaviors>
</ListBox>
Run Code Online (Sandbox Code Playgroud)
所有归功于约什爱因斯坦博客
如果你来这里寻找一个解决方案,只有当孩子在顶部并向上滚动或向下滚动并向下滚动时才能使事件冒泡,这是一个解决方案.我只使用DataGrid对此进行了测试,但它也应该与其他控件一起使用.
public class ScrollParentWhenAtMax : Behavior<FrameworkElement>
{
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.PreviewMouseWheel += PreviewMouseWheel;
}
protected override void OnDetaching()
{
this.AssociatedObject.PreviewMouseWheel -= PreviewMouseWheel;
base.OnDetaching();
}
private void PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
var scrollViewer = GetVisualChild<ScrollViewer>(this.AssociatedObject);
var scrollPos = scrollViewer.ContentVerticalOffset;
if ((scrollPos == scrollViewer.ScrollableHeight && e.Delta < 0)
|| (scrollPos == 0 && e.Delta > 0))
{
e.Handled = true;
var e2 = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
e2.RoutedEvent = UIElement.MouseWheelEvent;
AssociatedObject.RaiseEvent(e2);
}
}
private static T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
}
Run Code Online (Sandbox Code Playgroud)
要附加此行为,请将以下XMLNS和XAML添加到您的元素:
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<i:Interaction.Behaviors>
<shared:ScrollParentWhenAtMax />
</i:Interaction.Behaviors>
Run Code Online (Sandbox Code Playgroud)
小智 5
根据您的具体情况,有不同的方法,但我发现这种方法效果很好。假设你的基本情况是这样的:
<Window Height="200" Width="200">
<Grid>
<ScrollViewer Name="sViewer">
<StackPanel>
<Label Content="Scroll works here" Margin="10" />
<ListView Name="listTest" Margin="10"
PreviewMouseWheel="listTest_PreviewMouseWheel"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListView.ItemsSource>
<Int32Collection>
1,2,3,4,5,6,7,8,9,10
</Int32Collection>
</ListView.ItemsSource>
<ListView.View>
<GridView>
<GridViewColumn Header="Column 1" />
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</ScrollViewer>
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
在 PreviewMouseWheel 期间自行引发 MouseWheelEvent 似乎会强制 ScrollViewer 工作。我希望我知道为什么,这似乎非常违反直觉。
private void listTest_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
e.Handled = true;
MouseWheelEventArgs e2 = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
e2.RoutedEvent = UIElement.MouseWheelEvent;
listTest.RaiseEvent(e2);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
18099 次 |
| 最近记录: |