15

我意识到,当使用与 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>
4

3 回答 3

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

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

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

到您的用户控件的属性。

于 2011-10-07T13:54:20.133 回答
1

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

              CommandManager.PreviewCanExecute="PreviewCanExecute" 

并在事件处理程序中

               e.ContinueRouting = false;

希望这会有所帮助

于 2011-10-08T11:59:01.380 回答
0

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

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

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

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

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

<Window ShowActivated="False" ....>
....
</Window>
于 2011-10-08T16:46:32.550 回答