WPF menu tab navigation - wpf

I have a view with a menu:
<Menu IsTabStop="False">
<MenuItem
Header="_File"
IsTabStop="True">
<MenuItem
Header="New / Start Over"
IsTabStop="True"
InputGestureText="Ctrl+N"
Command="{x:Static common:Commands.StartOverCommand}" />
<Separator
IsTabStop="False" />
<MenuItem
Header="Log Out"
IsTabStop="True"
InputGestureText="F12"
Click="LogoutMenuItem_Click" />
<MenuItem
Header="E_xit"
IsTabStop="True"
InputGestureText="Alt+F4"
Click="ExitMenuItem_Click" />
</MenuItem>
<MenuItem
Header="_Edit"
IsTabStop="True">
<MenuItem
Header="Undo Edit Field"
IsTabStop="True"
InputGestureText="Ctrl+Z"
Click="_undoMenuItem_Click" />
<MenuItem
Header="Redo Edit Field"
IsTabStop="True"
InputGestureText="Ctrl+Y"
Click="_redoMenuItem_Click" />
</MenuItem>
<MenuItem
Header="_Tools"
IsTabStop="True">
<MenuItem
Header="Comments"
IsTabStop="True"
InputGestureText="Ctrl+M"
Click="_commentsMenuItem_Click" />
</MenuItem>
</Menu>
I would like to be able to navigate through the menus (File, Edit, Tools) by using the right and left arrow keys, which I was able to accomplish by making these MenuItems IsTabStop="True". But since I did this I am able to tab to the menu as I cycle through the other valid fields on a page. When I use Alt+F to put focus on the File menu I want to be able to cycle through the 3 menus with the arrow keys, but I don't want to be able to tab to these menus from the page. How would I accomplish this?

Use the KeyboardNavigation.TabNavigation Attached Property with KeyboardNavigationMode.None on menu.
<Menu KeyboardNavigation.TabNavigation="None">

Related

Command doesn't work on top level MenuItem in MVVM

It works fine if the MenuItem doesn't have a sub MenuItem, like this:
<MenuItem Header="Open" Command="{Binding OpenCommand}"/>
but, when I add a sub MenuItem to it, the Command doesn't work:
<MenuItem Header="Open" Command="{Binding OpenCommand}">
<MenuItem />
</MenuItem>
click event also doesn't work like this:
<MenuItem Header="Open" Click="MenuItem_Click">
<MenuItem />
</MenuItem>
when I try to add the Command to the header:
<MenuItem>
<MenuItem.Header>
<TextBlock>
<TextBlock.InputBindings>
<MouseBinding Gesture="LeftClick" Command="{Binding OpenCommand}"/>
</TextBlock.InputBindings>
Open
</TextBlock>
</MenuItem.Header>
<MenuItem />
</MenuItem>
the Command works but the sub MenuItem doesn't show.
Any help will be appreciate, and forgive my half-baked English.
If you have sub MenuItems the click event is used (and expected by the user) to show the sub-menu. To react upon a submenu opening use the event SubmenuOpened.
If you really want to be able to open a sub menu and click on the "Open", you could use this snipper, but I'd really not advice it:
<MenuItem SubmenuOpened="MenuItem_OnSubmenuOpened"> <!-- handle sub menu opening if desired -->
<MenuItem.Header>
<Button Click="Button_Click">Open V2</Button> <!-- handle click on "Open" if desired; doesn't open sub menu! -->
</MenuItem.Header>
<MenuItem />
</MenuItem>
Note that I have tested this with "Open" not being the top level menu item.

How to create a right-click context menu for a button in WPF

i know how to create a left-click context menu for a button, but I am not too sure how to do it for a right click? (i.e. how to specify that the context menu should appear on a right-click, not a left click).
Many thanks.
Here is a sample:
<Button Content="button" Name="btn" Width="100">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Cut"/>
<MenuItem Header="Copy"/>
<MenuItem Header="Paste"/>
</ContextMenu>
</Button.ContextMenu>
</Button>

XAML and Binding Submenu items in a ContextMenu?

I have a ContextMenu defined on a Datagrid but want to bind submenu items to a collection on my viewmodel. Can anybody suggest how this should be done?
The following is a simple example of what I'm trying to achieve, BUT I want "Test1", "Test2" to come from a collection on my viewmodel, not hardcoded. I know how to bind my collection to the whole ContextMenu, but not how to bind it to just the one submenu...
<ContextMenu>
<MenuItem Header="Add to">
<MenuItem Header="Test1" />
<MenuItem Header="Test2" />
</MenuItem>
<MenuItem Header="Remove from All" />
</ContextMenu>
I'm using 3.5 SP1 and the WPF Toolkit.
Guess I should have experimented more. Turns out this was relatively simple:
<my:DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Add to" ItemsSource="{Binding MyItems}">
<MenuItem.ItemTemplate>
<DataTemplate>
<MenuItem CommandTarget="{Binding}" Click="AddClick">
<MenuItem.Header>
<TextBlock>
<TextBlock.Text><Binding StringFormat="Add to {0}" /></TextBlock.Text>
</TextBlock>
</MenuItem.Header>
</MenuItem>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
<MenuItem Header="Remove from All" />
</ContextMenu>
</my:DataGrid.ContextMenu>
There is a bug when using MenuItem.ItemTemplate. The color when do mouse over on the sub menu make user misunderstand that they can click to select the menu but it doesn't work for all area even if it's highlighted. See the picture
Then I used this code instead and it worked fine for me.
<ContextMenu>
<MenuItem Header="Add to" ItemsSource="{Binding MyItems}"
DisplayMemberPath="{Binding ItemName}">
<MenuItem.ItemContainerStyle>
<Style>
<EventSetter Event="MenuItem.Click" Handler="Menu_Click"/>
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
<MenuItem Header="Remove from All" />
</ContextMenu>

WPF menu item with image

How to define MenuItem.Icon so that the MenuItemHeader text would be placed below the menu item image?Thanks for help!
How something along the lines of:
<ContextMenu>
<MenuItem Header="Reports">
<MenuItem.Icon>
<Image Source="/XSoftArt.WPFengine;component/Images/export32x32xp.png"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
The easy way way is to not use the Icon property but to instead put the icon in the Header:
<Menu>
<MenuItem>
<MenuItem.Header>
<StackPanel>
<Image Width="20" Height="20" Source="/XSoftArt.WPFengine;component/Images/export32x32xp.png" />
<ContentPresenter Content="Reports" />
</StackPanel>
</MenuItem.Header>
</MenuItem>
<MenuItem Header="Export" />
<MenuItem Header="New record" />
</Menu>
For this simple case the <ContentPresenter Content="Reports" /> can be replaced with a <TextBlock Text="Reports" /> because that's what ContentPresenter would use to present the string anyway. For more complex Header=, you could use the ContentPresenter as shown.
In the case of StackPanel use Label and not the TextBlock since only Label will allow you to have the mnemonics on the menu, like _Reports.

How to add Submenus in a Menu

How does one make submenu's in WPF and are their ways to orientate the layout?
For submenus you can add as many MenuItem nested inside.
<Menu>
<MenuItem Header="File">
<MenuItem Header="Open"/>
<MenuItem Header="Close"/>
</MenuItem>
<MenuItem Header="Edit">
<MenuItem Header="Copy"/>
<MenuItem Header="Paste"/>
</MenuItem>
<MenuItem Header="Options"/>
Just redefine the ItemsPanel:
<Menu>
<Menu.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</Menu.ItemsPanel>
<MenuItem Header="Foo"/>
<MenuItem Header="Bar"/>
<MenuItem Header="Baz"/>
...
</Menu>
Note that this will not get rid of the vertical gradient effect in Vista/Win7 menus. If you want that, set Menu.Background property to whatever you want (could even be Transparent).

Resources