如何防止 InvokeCommandAction 将事件传播到父元素?
我意识到,当使用与 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以实现自己的 EventTrigger,将事件标记为已处理。
然后将
替换为
并添加到用户控件的属性中。
You could implement your own EventTrigger that marks events as handled.
Then replace
<i:EventTrigger EventName="MouseDoubleClick">
with<local:HandlingEventTrigger EventName="MouseDoubleClick">
and addto your usercontrol's atributes.
将附加事件添加到用户控件
和事件处理程序中
希望这将
Add attached event to user control
and in event handler
Hope this will help!
MouseDoubleClick 事件 实际上是不是冒泡路由事件,而是直接路由事件。
但是,此事件是沿着元素树引发的,可以使用 Snoop 工具。此外,即使将 MouseDoubleClick 的 Handled 设置为 true,该事件也会沿着元素树发生。
如上所述,您的问题可能不是由您提到的传播引起的。有 Window.ShowActivated 属性,它确定窗口首次显示时是否被激活。您可以在子窗口(xaml)中设置该属性,如下所示,但请注意,虽然 ShowActivated 可以将焦点赋予主窗口,但它不能让主窗口在视觉上保持在子窗口前面。我试图找到解决方案,但直到现在还不知道。
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.
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.