I’ve encountered an oddity with a very basic WPF exercise I’ve devised for myself, namely dynamically populating menus from a ViewModel. Given the following main window markup:
<Window x:Class="Demosne.Client.WPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:project="clr-namespace:Demosne.Client.WPF">
<Grid>
<Menu Height="26" Name="menu1" VerticalAlignment="Top" HorizontalAlignment="Stretch" ItemsSource="{Binding MainMenuItems}">
<Menu.ItemTemplate>
<HierarchicalDataTemplate >
<MenuItem Header="{Binding Text, Mode=OneTime}" ItemsSource="{Binding MenuItems}"/>
</HierarchicalDataTemplate>
</Menu.ItemTemplate>
<!--<MenuItem Header="File" />
<MenuItem Header="Edit" />-->
</Menu>
</Grid>
and the ViewModel(s):
public class MainWindowViewModel
{
private IList<MenuItemViewModel> _menuItems = new List<MenuItemViewModel>()
{
new MenuItemViewModel() { Text = "File" },
new MenuItemViewModel() { Text = "Edit" }
};
public IList<MenuItemViewModel> MainMenuItems
{
get
{
return _menuItems;
}
}
}
public class MenuItemViewModel
{
public string Text { get; set; }
public IList<MenuItemViewModel> MenuItems
{
get
{
return _menuItems;
}
}
private IList<MenuItemViewModel> _menuItems = new List<MenuItemViewModel>();
}
I would expect the GUI to exactly reproduce the the result of the two commented-out lines in the markup – two MenuItems called File and Edit.
However, the bound version behaves strangely on mouseover:
Markup version:

Bound version:

Why are they different?
You are getting funny results, because you are not really using the
HierarchicalDataTemplatethe correct way.When you set a itemssource on a Menu, it will create a MenuItem for each object in the collection, and if you also supply a
HierarchicalDataTemplatewith a itemssource set, it will create MenuItems for each of the child objects in that collection as well, down the hierarchy.In your case, you’ve added a MenuItem yourself in the template, which is not needed. The framework creates those items implicitly for you. And this is causing the menu to behave oddly.
So to get a correct result you should do something like this:
Update
By setting a DataTemplate on something, you are telling WPF that you want to control, how each of its items should be displayed.
In this case a
HierarchicalDataTemplateis used, which is a template for generating headered controls. This kind of control contains a header and an items collection.When you apply this kind of template to an object, whatever you have put in the template will be used as the header, and the items collection will be created by applying the template to each of the child objects in the collection set as the ItemsSource on the template. So it will recursively apply the template to all objects in the hierarchy.
In your example, you have a Menu. You could just create it by doing this:
It would work fine, but since you have not applied a template, to tell it how the items in the collection should be displayed, it will just create a MenuItem for each object in the itemssource and call
ToString()on it. This value will then be used as the Header property on the MenuItem.Since that not what you want, you have to apply a template, to tell WPF what you would like to be displayed as the content in the header of the implicitly generated MenuItem.
In my example I simply made a template containing a TextBlock, which binds to the Text property on the viewmodel.
Update 2
If you now want to set properties on the implicitly created menuitems, you have to that by setting the
ItemContainerStyleproperty on theHierarchicalDataTemplate. The styled defined here will be applied to all the generated menuitems.So to bind the Command property of the MenuItem to a Command property on the viewmodel you can do this: