I have Menu in my app. I\'m visualizing it using hierarchical data template:
Seems like I've found solution for part of my problem. Command is not being binding because, it seems like we need to create particular instance of command for each menu item. The core problem is that, allmost all my menuitems execute the same command and differences are only in value of command parameter. So I should do so:
sample menuitem class:
public class RMyMenuItem
{
public string Name { get; set; }
public string InputGesture { get; set; }
public ICommand ItemCommand
{ get; set; }
public List<RMyMenuItem> ChildrenItems { get; set; }
}
property in ViewModel:
public ObservableCollection<RMyMenuItem> ApplicationMenu
{
get
{
//RApplicationMainMenu menu = new RApplicationMainMenu(0);
//return new ObservableCollection<RMenuItem>(menu.Items);
return new ObservableCollection<RMyMenuItem>()
{
new RMyMenuItem()
{
Name = "item1",
ItemCommand = new DelegateCommand((param) => RunOperationExecute(param)),
ChildrenItems = new List<RMyMenuItem>()
{
new RMyMenuItem()
{
Name = "item2",
ItemCommand = new DelegateCommand((param) => RunOperationExecute(param))
}
}
}
};
}
And XAML:
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding Name}" />
<Setter Property="MenuItem.Command" Value="{Binding ItemCommand}"/>
<Setter Property="MenuItem.CommandParameter" Value="123"/>
<Setter Property="ItemsSource" Value="{Binding ChildrenItems}" />
</Style>
</Menu.ItemContainerStyle>
}
Continue digging this problem. I've tried other way using ItemsContainer Style, described there link text, because DataTemplate creates MenuItem within another MenuItem, which is not pretty good and it also adds some artefacts to clicking behavior.
<Menu Height="23" DockPanel.Dock="Top" ItemsSource="{Binding ApplicationMenu}" >
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding Name}" />
<Setter Property="Command" Value="{Binding RunOperationCommand}"/>
<Setter Property="CommandParameter" Value="123"/>
<Setter Property="ItemsSource" Value="{Binding ChildrenItems}" />
</Style>
</Menu.ItemContainerStyle>
<!--<MenuItem />-->
</Menu>
I've forgotten to mention that ApplicationMenu is an observable collection of my custom RMenuItem class. So this way also works, but commands don't work either!!! BUT I've noticed interesting feature - command binding don't works if we setting Menu's source via ItemsSource, if we add MenuItems statically (just uncommenting last line) - command binding defined in ItemContainerStyle works!!! -(( Why it happens so???? But it is not my ending aim - I'd like to make mechanism of building menu based on some collection with ability of assigning RoutedCommand (in order to have hot-key for menuitem). The situation is being complicated by using MVVM approach: my collection of menuitems resides in ViewModel layer, while RoutedCommands is a View's feature, while I'm using simple ICommands in my ViewModel. So there is a food for thought ... -))
The difference between the first and the second example in your question is that in the second code snippet you are binding MenuItem.Command
to the parent's data context, which has the RunOperationCommand
defined. Whereas in the first example with the HierarchicalDataTemplate
you are binding to the "local" DataContext, which is a menu item. It doesn't have the appropriate property, so the binding fails.
You have several options:
<MenuItem Header="Main menu" ItemsSource="{Binding ApplicationMenu}" >
<MenuItem.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type tm:RMenuItem}"
ItemsSource="{Binding Path=ChildrenItems}">
<MenuItem Header="{Binding Name}"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.RunOperationCommand}"
/>
</HierarchicalDataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
<Window.Resources>
<coreView:CommandReference x:Key="RunOperationCommand"
Command="{Binding RunOperationCommand}" />
</Window.Resources>
<MenuItem Header="Main menu" ItemsSource="{Binding ApplicationMenu}" >
<MenuItem.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type tm:RMenuItem}"
ItemsSource="{Binding Path=ChildrenItems}">
<MenuItem Header="{Binding Name}"
Command="{StaticResource RunOperationCommand}"
/>
</HierarchicalDataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>