0

I read xml to class:

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

So I get

  • Menu 1
    • Menu 1.1
    • Menu 1.2
      • Menu 1.2.1
      • Menu 1.2.2
  • Menu 2
    • Menu 2.1
    • Menu 2.2

Then set list in MenuViewModel

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

And in UserControl set properites for caliburn Message.Attach and 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}}" />

Method "MenuClick" is sometimes called more times then expected:

If I Click Menu 1 -> MenuClick is executed 1 time
If I Click Menu 1.1 -> MenuClick is executed 2 times
If I Click Menu 1.2.1 -> MenuClick is executed 3 times

But I would like that Menu 1.1 and Menu 1.2.1 events are called only once.
Any idea?

Tomislav
  • 153
  • 3
  • 15

1 Answers1

1

Not sure why this happens but it's probably something to do with event bubbling.

When you click on the top menu item the action message isn't dispatched. It's only when the menu closes that the action message fires.

If you want to avoid this, you can simply look at the RoutedEventArgs and check that the OriginalSource matches ActionExecutionContext.Source.

e.g.

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

Disclaimer: There may be a much easier way of doing this

Update:

Ok marking the routed event as handled stops it bubbling so it is something to do with bubbling - I'd just use the below code to stop the event propagating any further up the tree

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

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

     MessageBox.Show(((MenuItem) context.Source).Header.ToString());
}
Charleh
  • 13,749
  • 3
  • 37
  • 57