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

Uco*_*dia 14 wpf command mvvm event-routing invoke-command

我意识到当使用与EventTrigger关联的InvokeCommandAcction时,原始事件仍然会路由到父元素,直到它被处理.好吧,我想这是一种预期的行为.但我的问题是如何将事件标记为Handled,以便它不会在整个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>
Run Code Online (Sandbox Code Playgroud)

Jen*_*ens 21

您可以实现自己的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后替换<i:EventTrigger EventName="MouseDoubleClick"><local:HandlingEventTrigger EventName="MouseDoubleClick">,并添加

xmlns:local="clr-namespace:HandlingEventTrigger's namespace here"
Run Code Online (Sandbox Code Playgroud)

到你的usercontrol的属性.

  • 我选择这个答案是因为它是我可以在 MVVM 场景中使用的最干净的解决方案。 (2认同)