如果我们有
<ScrollViewer Name="scroll_viewer" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Canvas Name="canvas" Height="200" Width="200">
<Rectangle Fill="AliceBlue" Width="100" Height="100"/>
</Canvas>
</ScrollViewer>
使用处理程序:
scroll_viewer.PreviewMouseLeftButtonDown
scroll_viewer.MouseLeftButtonDown
canvas.PreviewMouseLeftButtonDown
然后,如果我们点击矩形,我们首先调用scroll_viewer_PreviewMouseLeftButtonDown
然后调用canvas_PreviewMouseLeftButtonDown
,但不调用scroll_viewer_MouseLeftButtonDown
。
我想首先在画布中处理click事件 - 如果单击一个对象我想处理事件(对象拖动)。如果没有单击画布对象,我想在scroll_viewer中处理事件(使用鼠标管理scrollview平移)。
如果管理顺序是我想要的对话并且未调用非perview版本scroll_viewer.MouseLeftButtonDown
,如何管理?
更新:
来自这篇文章:Silverlight forums
((FrameworkElement)scroll_viewer.GetValue(ScrollViewer.ContentProperty)).MouseLeftButtonDown += scroll_viewer_MouseLeftButtonDown;
是否正常工作,即在预览事件后调用 - 有人可以解释为什么需要这种不太明显的语法吗?
答案 0 :(得分:5)
问题是ScrollViewer
已在内部处理MouseLeftButtonDown
事件,如下所示:
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
if (base.Focus())
e.Handled = true;
base.OnMouseLeftButtonDown(e);
}
您可以使用自定义类“修复”此问题,如下所示:
public class MyScrollViewer : ScrollViewer {
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
base.OnMouseLeftButtonDown(e);
e.Handled = false;
}
}
SIDE注意:您应该在XAML中使用x:Name
,而不是Name
。否则,您可能会使用上面的类遇到编译错误。
或者,您可以为所有MouseLeftButtonDown
事件附加处理程序,包括已处理的事件。所以而不是:
this.scroll_viewer.MouseLeftButtonDown += new MouseButtonEventHandler(scroll_viewer_MouseLeftButtonDown);
您将使用:
this.scroll_viewer.AddHandler(ScrollViewer.MouseLeftButtonDownEvent, new MouseButtonEventHandler(this.scroll_viewer_MouseLeftButtonDown), true);
答案 1 :(得分:2)
Preview
事件遵循类似于Tunneling
策略的路由策略,这意味着事件从元素树的顶部开始,然后向下移动。所以它首先会击中你的ScrollViewer,然后是你的Canvas。
非预览事件遵循类似于Bubbling
策略的路由策略,这意味着事件从它们发生的对象开始,然后沿元素树向上移动。在这种情况下,Canvas将首先被击中,然后是ScrollViewer。
您可以详细了解路由策略here
作为旁注,要使Canvas对象对HitTest事件可见,它们需要具有非透明背景。因此,如果你有一个没有指定背景颜色的画布,它将默认为透明,并且对于HitTests不可见。