I have a ContextMenu with some sub-menus that have items (MenuItem) that can be selected. When the ContextMenu is opened, I want to recursively open the currently selected item. So, I have the following code:
protected override void OnOpened( RoutedEventArgs e ) {
base.OnOpened( e );
OpenCurrentSubMenu( Items );
}
private static bool OpenCurrentSubMenu( ItemCollection itemCollection ) {
foreach (MenuItem item in itemCollection) {
if (item.IsChecked) {
return true;
}
else if( OpenCurrentSubMenu( item.Items ) ) {
item.IsSubmenuOpen = true;
return true;
}
}
return false;
}
I also have some other code that ensures that only one item is checked.
This seems to work great the first time I select an item in a sub-menu. When I re-open the ContextMenu, the open sub-menus cascade open to the selected item:
However, when I leave the context menu, and re-open it a second time, the selected menu does NOT open:
Does anyone know why and how to fix it?
Three things to try:
When the context menu is opened, recurse over the entire hierarchy and set IsSubmenuOpen = false before you try to open any submenus. It may be that the previously open submenu is remembered and thus you're trying to tell it to have two open submenus at the same level.
Recurse to find the submenus that need to be opened and store them in a list. Then iterate through the list and set them so that the topmost menu is set open before its child submenu is set open. (It may be that trying to open the child when its parent is not yet open won't always work reliably).
Nasty brute force approach: Delete and recreate the context menu each time it is opened. It's not nice, but if you're opening a context menu you're likely to be worried about the performance implications. And it appears that it works the first time, so make every time the first time.
Good tips. I have tried several variations: I tried Scott Rippey's method. I also tried setting IsSubmenuOpen = false on Close, to no avail. Your second bullet is interesting, but does not explain why the cascade works the first time, but none of the following times. Brute force is always an option :)
It seems that the second option does the trick, though it still does not explain why the cascade works the first time. !@*$# MS .NET
It is likely that some information is uncached on the first attempt so it works whichever order you set the menus open, but on subsequent attempts the menu system "knows more" about the hierarchy or state of the existing menu items, and thus gets confused by your attempts to change things.