Reputation: 11091
I am having trouble write the xaml representation to allow to bind to my background ViewModel for cascading menus
here's the VM:
public class MenuNode
{
public string Header {get;}
public List<MenuNode> Items {get;}
}
the xaml i have is this:
<ContextMenu ItemsSource="{Binding Choices}" >
<ContextMenu.Resources>
<DataTemplate DataType="{x:Type vmi:MenuNode}">
<MenuItem Header="{Binding Header}" ItemsSource="{Binding Items}"/>
</DataTemplate>
</ContextMenu.Resources>
</ContextMenu>
When the menu pops up I get the first-level entries with an arrow(indicating that there should be a sub-menu) but when i hover over the menu it doesn't show the sub-menu items.
Any ideas?
Upvotes: 4
Views: 5158
Reputation: 280
my take on MenuItems and MVVM (it was not easy to put Icons in there)
public class MenuItemVM
{
public string Text { get; set; }
public List<MenuItemVM> Children { get; set; }
public ICommand Command { get; set; }
public ImageSource Icon { get; set; }
}
public IList<MenuItemVM> AddContextMenu { get; set; }
View:
<Image x:Key="MenuItemIcon"
x:Shared="false"
Source="{Binding Icon}"
Height="16px"
Width="16px"/>
<Style x:Key="ContextMenuItemStyle" TargetType="{x:Type MenuItem}">
<Setter Property="MenuItem.Icon" Value="{StaticResource MenuItemIcon}"/>
<Setter Property="MenuItem.Command" Value="{Binding Command}" />
<Style.Triggers>
<!-- insert a null in ItemsSource if you want a separator -->
<DataTrigger Binding="{Binding}" Value="{x:Null}">
<Setter Property="Template" >
<Setter.Value>
<ControlTemplate>
<Separator Style="{StaticResource {x:Static MenuItem.SeparatorStyleKey}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
Add the contextmenu to your UI
<ContextMenu ItemContainerStyle="{StaticResource ContextMenuItemStyle}"
ItemsSource="{Binding AddContextMenu}">
<ContextMenu.Resources>
<HierarchicalDataTemplate DataType="{x:Type vmp:MenuItemVM}"
ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Text}"/>
</HierarchicalDataTemplate>
</ContextMenu.Resources>
</ContextMenu>
Upvotes: 4
Reputation: 14256
OK, here's the issue:
For some reason, the MenuItems
that were generated by your DataTemplate
are getting wrapped inside of another MenuItem
(the result was nested MenuItems
). The sub items were not being opened because the outer MenuItem
had no children.
The solution is to use a HierarchicalDataTemplate
instead:
<ContextMenu ItemsSource="{Binding Choices}" >
<ContextMenu.Resources>
<HierarchicalDataTemplate DataType="{x:Type vmi:MenuNode}" ItemsSource="{Binding Items}">
<TextBlock Text="{Binding Header}"/>
</HierarchicalDataTemplate>
</ContextMenu.Resources>
</ContextMenu>
Upvotes: 5
Reputation: 14256
Try using ObservableCollection<MenuNode>
instead of List<MenuNode>
if you are adding the nodes to the list after the binding is initialized the items collection will not get updated unless you are firing INotifyCollectionChanged
(ObservableCollection
does this).
Upvotes: 1