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

发布于 2024-12-12 07:01:38 字数 1149 浏览 0 评论 0原文

如果我们有

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

确实有效,即预览活动后确实会被调用 -有人可以解释为什么需要这种不太明显的语法吗?

If we have

<ScrollViewer Name="scroll_viewer" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <Canvas Name="canvas" Height="200" Width="200">
        <Rectangle Fill="AliceBlue" Width="100" Height="100"/>  
    </Canvas>
</ScrollViewer> 

with handlers for:

scroll_viewer.PreviewMouseLeftButtonDown
scroll_viewer.MouseLeftButtonDown
canvas.PreviewMouseLeftButtonDown

Then if we click in the Rectangle we get scroll_viewer_PreviewMouseLeftButtonDown called first then canvas_PreviewMouseLeftButtonDown but scroll_viewer_MouseLeftButtonDown is not called.
I want to handle the click event first in the canvas - if an object is clicked I want to handled the event (for object drag). If no canvas object is clicked I want to handle event in scroll_viewer (to manage scrollview panning with the mouse).
How to manage this given that the call order is the oposite of what i want and that the non perview version scroll_viewer.MouseLeftButtonDown is not called?

UPDATE:
From this post: Silverlight forums

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

DOES work ie does get called after the preview events - can some explain why this less than obvious syntax is required?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小嗷兮 2024-12-19 07:01:39

问题是 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);

The problem is that the ScrollViewer already handles the MouseLeftButtonDown event internally, like so:

protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
    if (base.Focus())
        e.Handled = true;
    base.OnMouseLeftButtonDown(e);
}

You can "fix" this using a custom class, like so:

public class MyScrollViewer : ScrollViewer {

    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) {
        base.OnMouseLeftButtonDown(e);
        e.Handled = false;
    }
}

SIDE NOTE: You should use x:Name in XAML, not Name. Otherwise you may run into compilation errors using the above class.

Alternatively, you could attach your handler for all MouseLeftButtonDown events, including handled ones. So instead of:

this.scroll_viewer.MouseLeftButtonDown += new MouseButtonEventHandler(scroll_viewer_MouseLeftButtonDown);

You'd use:

this.scroll_viewer.AddHandler(ScrollViewer.MouseLeftButtonDownEvent, new MouseButtonEventHandler(this.scroll_viewer_MouseLeftButtonDown), true);
眼角的笑意。 2024-12-19 07:01:39

Preview 事件遵循与Tunneling 策略类似的路由策略,这意味着事件从元素树的顶部开始,然后向下传播。因此它会首先到达您的 ScrollViewer,然后到达您的 Canvas。

非预览事件遵循类似于冒泡策略的路由策略,这意味着事件从它们发生的对象开始,并沿元素树向上传播。在这种情况下,Canvas 将首先受到攻击,然后是 ScrollViewer。

路由策略的更多信息

您可以在此处阅读有关 要使 Canvas 对象对 HitTest 事件可见,它们需要具有不透明的背景。因此,如果您有一个未指定背景颜色的画布,它将默认为透明,并且对 HitTest 不可见。

The Preview events follow a routing strategy similar to the Tunneling strategy, meaning that the event starts at the top of the element tree, and travels down it. So it would hit your ScrollViewer first, then your Canvas.

The non-Preview events follow a routing strategy similar to the Bubbling strategy, meaning that events start on the object they occurred on, and travel up the element tree. In this case, the Canvas would get hit first, then the ScrollViewer.

You can read more about the Routing strategies here

As a side note, for Canvas objects to be visible for HitTest events, they need to have a non-transparent background. So if you have a Canvas with no background color specified, it will default to Transparent and not be visible for HitTests.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文