Bound WPF Menu using MVVM - Find the error
I'm trying to implement Menu in a Window using MVVM pattern. So I have created a MainWindow and bound it to MainWindowViewModel. MainWindowViewModel contains MainWindowMenuViewModel which is a VM specially designed for Menu. It's a hierarchical structure of MenuItemViewModels. All seems to be simple but I have a problem - when I run the application the menu is not rendered properly - it seems Header property is not set. The menu is there in top left corner but without any text displayed. I can click it and it opens but all MenuItems are blank. What's strange: bound ICommands work! But no Header is displayed. Here is my resources
<Style x:Key="MenuItemStyle" TargetType="{x:Type MenuItem}" >
<Style.Setters>
<Setter Property="Header" Value="{Binding Path=Title}" />
<Setter Property="Command" Value="{Binding Path=Command}" />
</Style.Setters>
</Style>
<HierarchicalDataTemplate
x:Key="MenuDataTemplate"
DataType="{x:Type vw:MenuItemViewModel}"
ItemsSource="{Binding Path=SubMenuItems}"
ItemContainerStyle="{StaticResource ResourceKey=MenuItemStyle}"
>
</HierarchicalDataTemplate>
MainWindow.xaml contains menu:
<DockPanel>
<Menu
DockPanel.Dock="Top"
ItemsSource="{Binding Path=Menu.MenuItems}"
ItemTemplate="{StaticResource ResourceKey=MenuDataTemplate}"
/>
</DockPanel>
MenuItemView is:
using System.Collections.Generic;
using System开发者_如何学C.Windows.Input;
namespace WpfMvvmMenu.ViewModel
{
public class MenuItemViewModel
{
public MenuItemViewModel(string title, ICommand command)
{
this.Title = title;
this.Command = command;
this.SubMenuItems = new List<MenuItemViewModel>();
}
public string Title { get; private set; }
public ICommand Command { get; private set; }
public IList<MenuItemViewModel> SubMenuItems { get; private set; }
}
}
I saw all MVVM - Menu articles here, but they all say my DataTemplate is OK, so there must be something else.
Thank you.
I think that when you use HierarchicalDataTemplate
, you set the Content
of the templated MenuItem
to the content of the template, even if you leave it empty. This code works:
<Style x:Key="MenuItemStyle" TargetType="{x:Type MenuItem}">
<Style.Setters>
<Setter Property="Command" Value="{Binding Path=Command}" />
</Style.Setters>
</Style>
<HierarchicalDataTemplate
x:Key="MenuDataTemplate"
DataType="{x:Type vw:MenuItemViewModel}"
ItemsSource="{Binding Path=SubMenuItems}"
ItemContainerStyle="{StaticResource MenuItemStyle}"
>
<ContentPresenter Content="{Binding Title}" />
</HierarchicalDataTemplate>
On the other hand, you don't need the template at all. You can set ItemContainerStyle="{StaticResource MenuItemStyle}"
directly on the menu while using the following style:
<Style x:Key="MenuItemStyle" TargetType="{x:Type MenuItem}">
<Style.Setters>
<Setter Property="Header" Value="{Binding Path=Title}" />
<Setter Property="Command" Value="{Binding Path=Command}" />
<Setter Property="ItemsSource" Value="{Binding SubMenuItems}" />
</Style.Setters>
</Style>
精彩评论