我意识到当使用与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>
答案 0 :(得分:20)
您可以实现自己的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"
到你的usercontrol的属性。
答案 1 :(得分:1)
将附加事件添加到用户控件
CommandManager.PreviewCanExecute="PreviewCanExecute"
和事件处理程序
e.ContinueRouting = false;
希望这会help!
答案 2 :(得分:0)
MouseDoubleClick Event实际上不是冒泡路由事件,而是直接路由事件。
但是,此事件是在元素树中引发的,可以使用Snoop工具进行检查。此外,即使Handled for MouseDoubleClick设置为true,此事件也将沿元素树发生。
虽然此路由事件(MouseDoubleClick事件)似乎遵循通过元素树的冒泡路径,但它实际上是每个UIElement沿元素树引发的直接路由事件。
如果在MouseDoubleClick事件处理程序中将Handled属性设置为true,则沿着路径的后续MouseDoubleClick事件将在Handled设置为false的情况下发生。对于希望在用户双击控件并在应用程序中处理事件时收到通知的控制使用者,这是一个更高级别的事件。 (来自MSDN)
如上所述,您的问题可能不是由您提到的传播引起的。有Window.ShowActivated属性,用于确定首次显示时是否激活窗口。您可以在子窗口(xaml)中设置属性,如下所示,但请注意,尽管ShowActivated可以将焦点提供给主窗口,但它不能让主窗口直观地保留在子窗口的前面。我试图找到解决方案,但直到现在才知道。
<Window ShowActivated="False" ....>
....
</Window>