多次调用 MenuItem 事件

MenuItem event called multiple times

我读 xml 到 class:

public class MenuItem
{
  public string Header{get;set;}
  public List<MenuItem> ChildMenuItems{get;set;}
}

所以我得到

然后在MenuViewModel中设置列表

 MenuItems = new ObservableCollection<MenuItem>(Service.GetMenu());

并在 UserControl 中为 caliburn Message.Attach 和 Action.TargetWithoutContext

设置属性
<Setter Property="cal:Message.Attach" Value="[Event Click] = [Action MenuClick($originalsourcecontext)]" />
<Setter Property="cal:Action.TargetWithoutContext" Value="{Binding Path=DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />

方法 "MenuClick" 有时被调用的次数比预期的要多:

如果我点击 Menu 1 -> MenuClick 执行 1 次
如果我点击 Menu 1.1 -> MenuClick 执行 2 次
如果我点击 Menu 1.2.1 -> MenuClick 被执行了 3 次

但我希望 Menu 1.1 和 Menu 1.2.1 事件只被调用一次。
有什么想法吗?

不确定为什么会发生这种情况,但可能与事件冒泡有关。

当您单击顶部菜单项时,不会发送操作消息。只有当菜单关闭时才会触发操作消息。

如果您想避免这种情况,只需查看 RoutedEventArgs 并检查 OriginalSource 是否匹配 ActionExecutionContext.Source.

例如

public void MenuClick(ActionExecutionContext context)
{
    var routed = context.EventArgs as RoutedEventArgs;

    if(routed == null)
        throw new Exception("No routed event");

    if (routed.OriginalSource == context.Source)
    {
        MessageBox.Show(((MenuItem)context.Source).Header.ToString());
    }
}

免责声明:可能有更简单的方法

更新:

好的,将路由事件标记为已处理会阻止它冒泡,所以它与冒泡有关 - 我只是使用下面的代码来阻止事件在树上进一步传播

public void MenuClick(ActionExecutionContext context)
{
    var routed = context.EventArgs as RoutedEventArgs;

    if (routed != null)
        routed.Handled = true;

     MessageBox.Show(((MenuItem) context.Source).Header.ToString());
}