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

Wpf 如何防止InvokeCommandAction将事件传播到父元素?,wpf,mvvm,command,invoke-command,event-routing,Wpf,Mvvm,Command,Invoke Command,Event Routing,我意识到,当使用与EventTrigger关联的InvokeCommandaccion时,原始事件仍然向上路由到父元素,直到它被处理为止。嗯,我想这是意料之中的行为。但我的问题是如何将事件标记为已处理,这样它就不会在整个UI树中向上传播 实际上,当您在命令中处理此事件时,所有内容都将在此命令中处理,因此它不需要传播。在我发现的一个案例中,它导致了一些不必要的行为。例如,当用户双击一个元素时,我打开了一个新窗口(MouseDoubleClick事件)。问题是新窗口打开,然后主窗口回到新窗口的前面,

我意识到,当使用与EventTrigger关联的InvokeCommandaccion时,原始事件仍然向上路由到父元素,直到它被处理为止。嗯,我想这是意料之中的行为。但我的问题是如何将事件标记为已处理,这样它就不会在整个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>

...

您可以实现自己的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"

添加到用户控件的属性。

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

              CommandManager.PreviewCanExecute="PreviewCanExecute" 
和在事件处理程序中

               e.ContinueRouting = false;
希望这会成功

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

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

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

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

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

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

....

这似乎是个不错的主意。我会等待更多的答案。谢谢。我选择这个答案是因为它是我在MVVM场景中可以使用的最干净的解决方案。对于Windows Phone,使用GestureEventArgs而不是RoutedEventArgs。