ScrollViewer中的画布(预览)MouseButtonDown事件顺序

时间:2011-10-28 12:40:25

标签: wpf scrollviewer mouseleftbuttondown

如果我们有

<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;

是否正常工作,即在预览事件后调用 - 有人可以解释为什么需要这种不太明显的语法吗?

2 个答案:

答案 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不可见。