static void InitializeMainSubMenu(MainSubMenuState state) { if (!state.Recreate) return; state.Recreate = state.AlwaysRecreate; var topLevelMenuItem = state.TopLevelMenuItem; // Don't remove the first one or opening the menu from the keyboard (Alt+XXX) won't // highlight the first menu item. for (int i = topLevelMenuItem.Items.Count - 1; i >= 1; i--) topLevelMenuItem.Items.RemoveAt(i); ClearMainSubMenu(state); int cachedIndex = 0; int added = 0; var items = new List<object>(); foreach (var category in state.Groupings) { items.Clear(); foreach (var entry in category) { var menuCmd = entry.Value as IMainMenuCommand; if (menuCmd != null && !menuCmd.IsVisible) continue; var provider = entry.Value as IMenuItemProvider; if (provider != null) { var cached = state.CachedMenuItems[cachedIndex++]; items.AddRange(provider.CreateMenuItems(cached)); // This condition should never be true. The called code should make sure that // the cached menu item is always used if it's the first item in the menu. if (items.Count > 0 && items[0] != cached && added == 0) { Debug.Fail("The first returned menu item is not the cached menu item. It won't be selected when opened with Alt+XXX the first time."); // We can't clear topLevelMenuItem.Items since it must always contain // the first cached menu item (== cached). Just disable it instead. cached.IsEnabled = false; } } else { var menuItem = state.CachedMenuItems[cachedIndex++]; menuItem.Command = CommandWrapper.Unwrap(entry.Value); // We must initialize CommandTarget or the menu items for the standard commands // (Ctrl+C, Ctrl+O etc) will be disabled after we stop debugging. We didn't // need to do this when the menu wasn't in the toolbar. menuItem.CommandTarget = MainWindow.Instance; menuItem.Header = entry.Metadata.MenuHeader; if (!string.IsNullOrEmpty(entry.Metadata.MenuIcon)) CreateMenuItemImage(menuItem, entry.Value, entry.Metadata.MenuIcon, BackgroundType.MainMenuMenuItem); menuItem.InputGestureText = entry.Metadata.MenuInputGestureText; var checkable = entry.Value as IMainMenuCheckableCommand; bool? checkState = checkable == null ? null : checkable.IsChecked; menuItem.IsCheckable = checkState != null; if (checkState != null) { var binding = checkable.Binding; if (binding != null) menuItem.SetBinding(MenuItem.IsCheckedProperty, binding); else menuItem.IsChecked = checkState.Value; } var initMenu = entry.Value as IMainMenuCommandInitialize; if (initMenu != null) initMenu.Initialize(menuItem); items.Add(menuItem); } } if (items.Count > 0) { if (added > 0) topLevelMenuItem.Items.Add(new Separator()); added += items.Count; foreach (var item in items) { // The first one is never removed from the Items collection so don't try to re-add it if (topLevelMenuItem.Items.Count == 0 || topLevelMenuItem.Items[0] != item) topLevelMenuItem.Items.Add(item); } } } }
void InitMainMenu() { foreach (var topLevelMenu in mainMenuCommands.OrderBy(c => c.Metadata.MenuOrder).GroupBy(c => c.Metadata.Menu)) { var topLevelMenuItem = mainMenu.Items.OfType<MenuItem>().FirstOrDefault(m => (m.Header as string) == topLevelMenu.Key); var state = new MainSubMenuState(); if (topLevelMenuItem == null) { topLevelMenuItem = new MenuItem(); topLevelMenuItem.Header = topLevelMenu.Key; mainMenu.Items.Add(topLevelMenuItem); } subMenusDict.Add((string)topLevelMenuItem.Header, state); state.TopLevelMenuItem = topLevelMenuItem; state.Groupings = topLevelMenu.GroupBy(c => c.Metadata.MenuCategory).ToArray(); foreach (var category in state.Groupings) { foreach (var entry in category) state.CachedMenuItems.Add(new MenuItem()); } var stateTmp = state; state.TopLevelMenuItem.SubmenuOpened += (s, e) => InitializeMainSubMenu(stateTmp); state.TopLevelMenuItem.SubmenuClosed += (s, e) => { if (stateTmp.AlwaysRecreate) ClearMainSubMenu(stateTmp); }; // Make sure it's not empty or it will always be empty state.TopLevelMenuItem.Items.Clear(); state.TopLevelMenuItem.Items.Add(state.CachedMenuItems[0]); } }
static void ClearMainSubMenu(MainSubMenuState state) { // Clear all properties that are set by our code foreach (var item in state.CachedMenuItems) { item.ClearValue(MenuItem.CommandProperty); item.ClearValue(MenuItem.CommandTargetProperty); item.ClearValue(MenuItem.HeaderProperty); item.ClearValue(MenuItem.IconProperty); item.ClearValue(MenuItem.IsEnabledProperty); item.ClearValue(MenuItem.InputGestureTextProperty); item.ClearValue(MenuItem.IsCheckableProperty); item.ClearValue(MenuItem.IsCheckedProperty); BindingOperations.ClearBinding(item, MenuItem.IsCheckedProperty); } }