ScrollViewer 中的 Canvas(预览版)MouseButtonDown 事件顺序

4
如果我们拥有
<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
我想首先在画布中处理单击事件 - 如果单击了对象,则要处理事件(用于对象拖动)。如果没有单击画布对象,则要在 scroll_viewer 中处理事件(用于使用鼠标管理滚动视图平移)。
考虑到调用顺序与我的要求相反,并且不会调用非预览版 scroll_viewer.MouseLeftButtonDown,该如何处理?

更新:
来自此贴子:Silverlight 论坛

((FrameworkElement)scroll_viewer.GetValue(ScrollViewer.ContentProperty)).MouseLeftButtonDown += scroll_viewer_MouseLeftButtonDown;

当预览事件调用后,确实起作用 - 有人能解释一下为什么需要这种不太明显的语法吗?

2个回答

6
问题在于,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;
    }
}

小提示:在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);

2
Preview事件遵循与Tunneling策略类似的路由策略,意味着事件从元素树的顶部开始并向下传递。因此,它会首先触发你的ScrollViewer,然后是Canvas。
非预览事件遵循与Bubbling策略类似的路由策略,意味着事件从它们发生的对象开始,并沿元素树向上传递。在这种情况下,Canvas将首先被触发,然后是ScrollViewer。
你可以在这里了解更多有关路由策略的信息。
另外需要注意的是,对于要进行HitTest事件检测的Canvas对象,它们需要具有不透明的背景。因此,如果Canvas未指定背景颜色,它将默认为透明,并且不会在HitTests中可见。

+1 对于透明/命中测试的支持 - 我注意到在默认画布中,如果没有对象可点击,则不会调用任何事件。 - Ricibob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接