My application contains a TreeView
which supports a set of commands, but the commands might move around between menus, only appear on some menus and not others, be shared across multiple menus, etc.
I know the set of all commands that I support at compile time, so in theory I can define a <MenuItem>
resource with an x:Key
attribute for each of them in my <TreeView.Resources>
section. However, for any given node that is clicked, which menu items that appear can only be determined at runtime. I can bind ContextMenu.ItemsSource
to something in my application that returns a MenuItem[]
, but in order to build this array, I would then need to access the MenuItems that were defined statically back in the XAML file.
Am I doing this all wrong? Or is there a way to do what I want?
Bind your ContextMenu.ItemsSource not to a MenuItem[] but a ObservableCollection < YourMenuClass >. YourMenuClass should contain the header and other parameters you want to bind to, maybe a command. Then use a template to generate your menuitems.
<ContextMenu ItemsSource="{Binding MenuItemList}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding Path=Name}" Command="{Binding MyCommand}" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
Instead of using an Itemtemplate, provide ItemContainer style for context menu. In this way you can avoid the problem of having a Menu item inside another as mentioned in the above comment.
`<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding Name}"/>
</Style>
</ContextMenu.ItemContainerStyle>`