如何防止 InvokeCommandAction 将事件传播到父元素?

发布于 2024-12-08 00:09:24 字数 886 浏览 1 评论 0原文

我意识到,当使用与 EventTrigger 关联的 InvokeCommandAcction 时,原始事件仍然会路由到父元素,直到被处理。嗯,我想这是一种预期的行为。但我的问题是如何将事件标记为已处理,以便它不会在整个 UI 树中传播?

实际上,当您在命令中处理此事件时,所有内容都将在此命令中处理,因此不需要传播。在我发现的一个极端情况下,它会导致一些不需要的行为。例如,当用户双击某个元素(MouseDoubleClick 事件)时,我打开一个新窗口。问题是,新窗口打开,然后主窗口又回到新窗口前面,因为 MouseDoubleClick 事件刚刚到达 UI 树中的顶部元素。想要的行为是将新窗口保持在前面,但是当 InvokeCommandAction 让事件向上传播时,主窗口收回焦点......

我可以做的是使用 CallMethodAction 资产,但因为我在MVVM 场景,我不想在我的代码中使用 UI 事件参数。即使这会让我隐式地将事件标记为已处理并解决问题。

<UserControl x:Class="..."
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseDoubleClick">
            <i:InvokeCommandAction Command="{Binding Path=DisplayReportCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    ...
</UserControl>

I realised that when using an InvokeCommandAcction associated to an EventTrigger, the original event was still routing up to the parent elements until it is handled. Well, I guess it is an expected behavior. But my question is how I can mark the event as Handled so it does not propagate up through the whole UI tree?

Actually, as you handle this event in a command, everything will be handled in this command, therefore it does not need to propagate. And in one corner case I found, it causes some unwanted behavior. For example, I open a new window when a user double click an element (MouseDoubleClick event). The problem is that the new windows opens and then the main window come back in front of the new one because the MouseDoubleClick event just reached the top element in the UI tree. The wanted behavior would be to keep the new window in front, but as the InvokeCommandAction lets the event propagate up, the main window takes back the focus...

What I could do is to use the CallMethodAction asset instead but as I am in a MVVM scenario, I don't want UI event arguments in my code. Even if this would let me implicitely mark the event as handled and fix the issue.

<UserControl x:Class="..."
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseDoubleClick">
            <i:InvokeCommandAction Command="{Binding Path=DisplayReportCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    ...
</UserControl>

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

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

发布评论

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

评论(3

爱殇璃 2024-12-15 00:09:24

您可以实现自己的 EventTrigger,将事件标记为已处理。

public class HandlingEventTrigger : System.Windows.Interactivity.EventTrigger
{
    protected override void OnEvent(System.EventArgs eventArgs)
    {
        var routedEventArgs = eventArgs as RoutedEventArgs;
        if (routedEventArgs != null)
            routedEventArgs.Handled = true;

        base.OnEvent(eventArgs);
    }
}

然后将 替换为 并添加

xmlns:local="clr-namespace:HandlingEventTrigger's namespace here"

到用户控件的属性中。

You could implement your own EventTrigger that marks events as handled.

public class HandlingEventTrigger : System.Windows.Interactivity.EventTrigger
{
    protected override void OnEvent(System.EventArgs eventArgs)
    {
        var routedEventArgs = eventArgs as RoutedEventArgs;
        if (routedEventArgs != null)
            routedEventArgs.Handled = true;

        base.OnEvent(eventArgs);
    }
}

Then replace <i:EventTrigger EventName="MouseDoubleClick"> with <local:HandlingEventTrigger EventName="MouseDoubleClick"> and add

xmlns:local="clr-namespace:HandlingEventTrigger's namespace here"

to your usercontrol's atributes.

缘字诀 2024-12-15 00:09:24

将附加事件添加到用户控件

              CommandManager.PreviewCanExecute="PreviewCanExecute" 

和事件处理程序中

               e.ContinueRouting = false;

希望这将

Add attached event to user control

              CommandManager.PreviewCanExecute="PreviewCanExecute" 

and in event handler

               e.ContinueRouting = false;

Hope this will help!

秋心╮凉 2024-12-15 00:09:24

MouseDoubleClick 事件 实际上是不是冒泡路由事件,而是直接路由事件。

但是,此事件是沿着元素树引发的,可以使用 Snoop 工具。此外,即使将 MouseDoubleClick 的 Handled 设置为 true,该事件也会沿着元素树发生。

尽管此路由事件(MouseDoubleClick 事件)似乎遵循元素树中的冒泡路由,但它实际上是由每个 UIElement 沿元素树引发的直接路由事件。

如果在 MouseDoubleClick 事件处理程序中将 Handled 属性设置为 true,则沿途的后续 MouseDoubleClick 事件将在 Handled 设置为 false 的情况下发生。这是一个高级事件,适用于希望在用户双击控件时收到通知并在应用程序中处理该事件的控件使用者。 (来自 MSDN

如上所述,您的问题可能不是由您提到的传播引起的。有 Window.ShowActivated 属性,它确定窗口首次显示时是否被激活。您可以在子窗口(xaml)中设置该属性,如下所示,但请注意,虽然 ShowActivated 可以将焦点赋予主窗口,但它不能让主窗口在视觉上保持在子窗口前面。我试图找到解决方案,但直到现在还不知道。

<Window ShowActivated="False" ....>
....
</Window>

MouseDoubleClick Event is actually not a bubbling routed event but a direct routed event.

However, this event is raised along the element tree, which can be checked with Snoop tool. Moreover, even if Handled for MouseDoubleClick is set to true, this event will occur along the element tree.

Although this routed event(MouseDoubleClick Event) seems to follow a bubbling route through an element tree, it actually is a direct routed event that is raised along the element tree by each UIElement.

If you set the Handled property to true in a MouseDoubleClick event handler, subsequent MouseDoubleClick events along the route will occur with Handled set to false. This is a higher-level event for control consumers who want to be notified when the user double-clicks the control and to handle the event in an application. (From MSDN)

As above, your problem may be not caused by the propagating as you mentioned. There is Window.ShowActivated property, which determines whether a window is activated when first shown. You can set the property in a sub window(xaml) as below but please note that though ShowActivated can give the focus to the main window, it cannot let the main window visually keep in front of the sub window. I have tried to find the solution but have no idea until now.

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