Solved my own question
After spending several hours searching the web, I found lots of examples that work against the WPF's natural intentions but none that worked with it.
Here's how to work with the Menu
control and not against it...
A little Background
WPF's Menu
control will normally auto create MenuItem
objects for you when it is binded to a POCO collection, using the ItemsSource
property.
However, this default behavior can be overridden! Here's how...
The Solution
First, you must create a class that derives from ItemContainerTemplateSelector
. Or use the simple class I've created:
public class MenuItemContainerTemplateSelector : ItemContainerTemplateSelector
{
public override DataTemplate SelectTemplate(object item, ItemsControl parentItemsControl)
{
var key = new DataTemplateKey(item.GetType());
return (DataTemplate) parentItemsControl.FindResource(key);
}
}
Second, you must add a reference to the MenuItemContainerTemplateSelector
class to your Windows resources
object, like so:
<Window.Resources>
<Selectors:MenuItemContainerTemplateSelector x:Key="_menuItemContainerTemplateSelector" />
Third, you must set two properties (UsesItemContainerTemplate
, and ItemContainerTemplateSelector
) on both the Menu
and the MenuItem
(which is defined in the HierarchicalDataTemplate
).
Like so:
<HierarchicalDataTemplate DataType="{x:Type ViewModel:MenuItemViewModel}"
ItemsSource="{Binding Children}">
<MenuItem Header="{Binding Header}"
Command="{Binding Command}"
UsesItemContainerTemplate ="true"
ItemContainerTemplateSelector=
"{StaticResource _menuItemContainerTemplateSelector}"/>
</HierarchicalDataTemplate>
<Menu DockPanel.Dock="Top"
ItemsSource="{Binding MenuItems}"
UsesItemContainerTemplate="True"
ItemContainerTemplateSelector=
"{StaticResource _menuItemContainerTemplateSelector}">
</Menu>
Why it Works
For optimization purposes, the Menu
uses the UsesItemContainerTemplate
flag (which has a default value of false
) to skip the DataTemplate
lookup and just returns a normal MenuItem
object. Therefore, we needed to set this value to true
and then our ItemContainerTemplateSelector
works as expected.
Happy Coding!
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…