Reputation: 14098
In a WPF menu that is data bound to a collection, I can style everything correctly, but navigation with the keyboard no longer works as expected.
Consider the XAML below (you can paste it in a tool like KaXaml).
Two things:
Opening a menu and navigating to the right with the arrow keys will by default select the first item in the opened menu item. For example:
Navigating the subitems doesn't work. When pressing the right arrow, the next top-level menu item is opened, instead of drilling down into the subitem
How can I ensure the 'default' menu behavior when navigating with the keys?
This is the XAML you can test it with:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Menu VerticalAlignment="Top">
<MenuItem Header="One">
<MenuItem Header="A">
<MenuItem Header="I" />
<MenuItem Header="II" />
<MenuItem Header="III" />
</MenuItem>
<MenuItem Header="B"/>
<MenuItem Header="C"/>
</MenuItem>
<MenuItem Header="Two">
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<MenuItem>
<MenuItem.HeaderTemplate>
<DataTemplate>
<TextBlock>
<Run Text="Bound property" />
</TextBlock>
</DataTemplate>
</MenuItem.HeaderTemplate>
<MenuItem Header="Something"/>
<MenuItem Header="Something else"/>
</MenuItem>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</MenuItem.ItemContainerStyle>
<MenuItem Header="A"/>
<MenuItem Header="B"/>
<MenuItem Header="C"/>
</MenuItem>
<MenuItem Header="Three">
<MenuItem Header="A">
<MenuItem Header="I" />
<MenuItem Header="II" />
<MenuItem Header="III" />
</MenuItem>
<MenuItem Header="B"/>
<MenuItem Header="C"/>
</MenuItem>
</Menu>
</Grid>
</Page>
Update
The special thing is that the sub MenuItems in my ControlTemplate should be added for each DataBound MenuItem. This is because I have an ObservableCollection with which I will build up the MenuItems inside MenuItem "Two". For each of these MenuItems, I need the same sub MenuItems. They will be bound to a Command that is the same for each of the MenuItems, except for the CommandParameter.
So what I want in the end is:
Two
Bound property 1
Something
Something else
Bound property 2
Something
Something else
Bound property 3
Something
Something else
Upvotes: 1
Views: 722
Reputation: 13669
I did restyle the menu item Two
while keeping your desired needs
<MenuItem Header="Two">
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header"
Value="Bound property" />
<Setter Property="ItemsSource">
<Setter.Value>
<!--binding sub menu items to a collection-->
<x:ArrayExtension Type="sys:String"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sys:String>Something</sys:String>
<sys:String>Something else</sys:String>
</x:ArrayExtension>
</Setter.Value>
</Setter>
</Style>
</MenuItem.ItemContainerStyle>
<MenuItem />
<MenuItem />
<MenuItem />
</MenuItem>
example above solves the navigation issue while keeping the binding to child items as desired. give it a try and see how close it is.
Upvotes: 1
Reputation: 2154
You should not create MenuItem
elements inside the template of your MenuItem
. You should style your items so they have the bound content.
I've added XML as a source for your menu items, so "Two" item has content bound to XML (you can replace it with your collection). For this solution you should have a collection for your submenu items (one for all top items, not per a single top item). The keyboard navigation works correct in the example below.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<XmlDataProvider x:Key="MenuProvider" XPath="Items">
<x:XData>
<Items xmlns="">
<Item Title="Bound property 1" Parameter="1" />
<Item Title="Bound property 2" Parameter="2" />
<Item Title="Bound property 3" Parameter="3" />
</Items>
</x:XData>
</XmlDataProvider>
<XmlDataProvider x:Key="SubMenuProvider" XPath="Items">
<x:XData>
<Items xmlns="">
<Item Title="Something" />
<Item Title="Something else" />
</Items>
</x:XData>
</XmlDataProvider>
</Page.Resources>
<Grid>
<Menu VerticalAlignment="Top">
<MenuItem Header="One">
<MenuItem Header="A">
<MenuItem Header="I" />
<MenuItem Header="II" />
<MenuItem Header="III" />
</MenuItem>
<MenuItem Header="B" />
<MenuItem Header="C" />
</MenuItem>
<MenuItem Header="Two" ItemsSource="{Binding Source={StaticResource MenuProvider}, XPath=*}">
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding XPath=@Title}" />
<Setter Property="ItemsSource" Value="{Binding Source={StaticResource SubMenuProvider}, XPath=*}" />
<Setter Property="Tag" Value="{Binding XPath=@Parameter}" />
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding XPath=@Title}" />
<Setter Property="CommandParameter" Value="{Binding Path=Tag, RelativeSource={RelativeSource AncestorType=MenuItem}}" />
</Style>
</Setter.Value>
</Setter>
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
<MenuItem Header="Three">
<MenuItem Header="A">
<MenuItem Header="I" />
<MenuItem Header="II" />
<MenuItem Header="III" />
</MenuItem>
<MenuItem Header="B" />
<MenuItem Header="C" />
</MenuItem>
</Menu>
</Grid>
</Page>
Upvotes: 2