1

I have a databound hierarchical menu in WPF. All items are displayed, but the commands only fire for the leafs of the menu, not the items that have children. I'm guessing the command is overriden by expanding the child menu... How do I get the command to execute even for the menu items with children?

What I have now is

<UserControl ...>
    <WrapPanel>
        <Menu>
            <Menu.Resources>
                <Style x:Key="MenuItemStyle" TargetType="MenuItem" d:DataContext="{d:DesignInstance local:TreeItem}">
                    <Setter Property="Command" Value="{Binding DataContext.AddColumnCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
                    <Setter Property="CommandParameter" Value="{Binding}"/>
                </Style>
            </Menu.Resources>
            <MenuItem Header="Add ▼" ItemsSource="{Binding AvailableFields}">
                <MenuItem.ItemTemplate>
                    <HierarchicalDataTemplate DataType="{x:Type local:TreeItem}" ItemsSource="{Binding NestedItems}" ItemContainerStyle="{StaticResource MenuItemStyle}">
                        <ContentPresenter Content="{Binding Annotation}"/>
                    </HierarchicalDataTemplate>
                </MenuItem.ItemTemplate>
            </MenuItem>
        </Menu>
    </WrapPanel>
</UserControl>

I found a question with a similar name, but the situation is different and it doesn't have a good answer anyway.

Community
  • 1
  • 1
voidengine
  • 2,504
  • 1
  • 17
  • 29

1 Answers1

0

All items are displayed, but the commands only fire for the leafs of the menu, not the items that have children.

Yes, this is the expected behaviour since clicking on a MenuItem with children is supposed to expand the submenu of child items. It doesn't execute a command.

If you want to expand the child items and execute the command you could handle the PreviewMouseLeftButtonDown event of the MenuItem:

<Style TargetType="{x:Type MenuItem}">
    <Setter Property="Command" Value="{Binding DataContext.AddColumnCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
    <EventSetter Event="PreviewMouseLeftButtonDown" Handler="OnMouseDown" />
</Style>

-

private void OnMouseDown(object sender, MouseButtonEventArgs e)
{
    MenuItem mi = sender as MenuItem;
    if (mi != null && mi.Command != null && mi.HasItems)
         mi.Command.Execute(mi.CommandParameter);
}

Note that handling the event in the code-behind of the view doesn't really break the MVVM pattern here since you are just invoking the command of the view model from the code-behind instead of invoking it from the XAML markup of the same view. But if you don't like this approach you could use an attached behaviour: https://www.codeproject.com/articles/28959/introduction-to-attached-behaviors-in-wpf

mm8
  • 163,881
  • 10
  • 57
  • 88