Search code examples
wpfcontextmenumenuitem

WPF Context Menu, MenuItem Child of Bound MenuItem not showing


I have a ContextMenu with a MenuItem bound to a list. It is supposed to list out the items (which it does). But under each item I am attempting to show another sub-MenuItem with the header "Remove".

Everything works properly except the 'Remove' sub-MenuItem is not showing....

Is there something obvious that I'm missing?

MODEL

public class MockModel
    {
        public string Name { get; set; }
        public MockModel(string name)
        {
            Name = name;
        }
    }

VIEWMODEL

public class MockVm
    {
        public ObservableCollection<MockModel> MockModels { get; set; } = new();

        public MockVm()
        {
            MockModels.Add(new MockModel("Item1"));
            MockModels.Add(new MockModel("Item2"));
            MockModels.Add(new MockModel("Item3"));
        }
    }

CODE BEHIND

public MainWindow()
        {
            InitializeComponent();
            DataContext = new MockVm();
        }

XAML

<Grid>
        <Label Content="XXXXXXXXXXX">
            <Label.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="ItemCollection" ItemsSource="{Binding Path=MockModels}">
                        <MenuItem.ItemTemplate>
                            <DataTemplate>
                                <MenuItem Header="{Binding Path=Name}">

                                    <!--Everything Else works except for this part.-->
                                    <MenuItem Header="Remove"/>

                                </MenuItem>
                            </DataTemplate>
                        </MenuItem.ItemTemplate>
                    </MenuItem>

                </ContextMenu>
            </Label.ContextMenu>
        </Label>
    </Grid>

This is the output, but no sub-item comes up


Solution

  • The ItemTemplate should not contain a MenuItem element.

    Extend your model with a child collection:

    public class MockModel
    {
        public string Name { get; set; }
    
        public MockModel(string name)
        {
            Name = name;
            ChildItems = new MockModel[1] { new MockModel() };
        }
    
        private MockModel()
        {
            Name = "Remove";
        }
    
        public IEnumerable<MockModel> ChildItems { get; }
    }
    

    And use an HierarchicalDataTemplate in the view:

    <Label Content="XXXXXXXXXXX">
        <Label.ContextMenu>
            <ContextMenu>
                <MenuItem Header="ItemCollection" ItemsSource="{Binding Path=MockModels}">
                    <MenuItem.ItemTemplate>
                        <HierarchicalDataTemplate ItemsSource="{Binding ChildItems}">
                            <TextBlock Text="{Binding Name}" />
                        </HierarchicalDataTemplate>
                    </MenuItem.ItemTemplate>
                </MenuItem>
    
            </ContextMenu>
        </Label.ContextMenu>
    </Label>