Selaa lähdekoodia

Fixes #3700. ContextMenu pollutes Toplevel.MenuBar's key bindings

BDisp 11 kuukautta sitten
vanhempi
commit
02a98f3fc2

+ 12 - 12
Terminal.Gui/Views/FileDialog.cs

@@ -1207,19 +1207,19 @@ public class FileDialog : Dialog
 
 
         var contextMenu = new ContextMenu
         var contextMenu = new ContextMenu
         {
         {
-            Position = new Point (e.MouseEvent.Position.X + 1, e.MouseEvent.Position.Y + 1),
-            MenuItems = new MenuBarItem (
+            Position = new Point (e.MouseEvent.Position.X + 1, e.MouseEvent.Position.Y + 1)
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                          [
                                              new MenuItem (Strings.fdCtxNew, string.Empty, New),
                                              new MenuItem (Strings.fdCtxNew, string.Empty, New),
                                              new MenuItem (Strings.fdCtxRename, string.Empty, Rename),
                                              new MenuItem (Strings.fdCtxRename, string.Empty, Rename),
                                              new MenuItem (Strings.fdCtxDelete, string.Empty, Delete)
                                              new MenuItem (Strings.fdCtxDelete, string.Empty, Delete)
                                          ]
                                          ]
-                                        )
-        };
-
+                                        );
         _tableView.SetSelection (clickedCell.Value.X, clickedCell.Value.Y, false);
         _tableView.SetSelection (clickedCell.Value.X, clickedCell.Value.Y, false);
 
 
-        contextMenu.Show ();
+        contextMenu.Show (menuItems);
     }
     }
 
 
     private void ShowHeaderContextMenu (int clickedCol, MouseEventEventArgs e)
     private void ShowHeaderContextMenu (int clickedCol, MouseEventEventArgs e)
@@ -1228,8 +1228,10 @@ public class FileDialog : Dialog
 
 
         var contextMenu = new ContextMenu
         var contextMenu = new ContextMenu
         {
         {
-            Position = new Point (e.MouseEvent.Position.X + 1, e.MouseEvent.Position.Y + 1),
-            MenuItems = new MenuBarItem (
+            Position = new Point (e.MouseEvent.Position.X + 1, e.MouseEvent.Position.Y + 1)
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                          [
                                              new MenuItem (
                                              new MenuItem (
                                                            string.Format (
                                                            string.Format (
@@ -1244,10 +1246,8 @@ public class FileDialog : Dialog
                                                            string.Empty,
                                                            string.Empty,
                                                            () => SortColumn (clickedCol, isAsc))
                                                            () => SortColumn (clickedCol, isAsc))
                                          ]
                                          ]
-                                        )
-        };
-
-        contextMenu.Show ();
+                                        );
+        contextMenu.Show (menuItems);
     }
     }
 
 
     private void SortColumn (int clickedCol)
     private void SortColumn (int clickedCol)

+ 58 - 26
Terminal.Gui/Views/Menu/ContextMenu.cs

@@ -1,4 +1,6 @@
-namespace Terminal.Gui;
+#nullable enable
+
+namespace Terminal.Gui;
 
 
 /// <summary>
 /// <summary>
 ///     ContextMenu provides a pop-up menu that can be positioned anywhere within a <see cref="View"/>. ContextMenu is
 ///     ContextMenu provides a pop-up menu that can be positioned anywhere within a <see cref="View"/>. ContextMenu is
@@ -16,15 +18,15 @@
 ///     </para>
 ///     </para>
 ///     <para>
 ///     <para>
 ///         Callers can cause the ContextMenu to be activated on a right-mouse click (or other interaction) by calling
 ///         Callers can cause the ContextMenu to be activated on a right-mouse click (or other interaction) by calling
-///         <see cref="Show()"/>.
+///         <see cref="Show"/>.
 ///     </para>
 ///     </para>
 ///     <para>ContextMenus are located using screen coordinates and appear above all other Views.</para>
 ///     <para>ContextMenus are located using screen coordinates and appear above all other Views.</para>
 /// </summary>
 /// </summary>
 public sealed class ContextMenu : IDisposable
 public sealed class ContextMenu : IDisposable
 {
 {
-    private static MenuBar _menuBar;
+    private static MenuBar? _menuBar;
 
 
-    private Toplevel _container;
+    private Toplevel? _container;
     private Key _key = DefaultKey;
     private Key _key = DefaultKey;
     private MouseFlags _mouseFlags = MouseFlags.Button3Clicked;
     private MouseFlags _mouseFlags = MouseFlags.Button3Clicked;
 
 
@@ -33,15 +35,9 @@ public sealed class ContextMenu : IDisposable
     {
     {
         if (IsShow)
         if (IsShow)
         {
         {
-            if (_menuBar.SuperView is { })
-            {
-                Hide ();
-            }
-
+            Hide ();
             IsShow = false;
             IsShow = false;
         }
         }
-
-        MenuItems = new MenuBarItem ();
     }
     }
 
 
     /// <summary>The default shortcut key for activating the context menu.</summary>
     /// <summary>The default shortcut key for activating the context menu.</summary>
@@ -56,13 +52,13 @@ public sealed class ContextMenu : IDisposable
     public bool ForceMinimumPosToZero { get; set; } = true;
     public bool ForceMinimumPosToZero { get; set; } = true;
 
 
     /// <summary>The host <see cref="View "/> which position will be used, otherwise if it's null the container will be used.</summary>
     /// <summary>The host <see cref="View "/> which position will be used, otherwise if it's null the container will be used.</summary>
-    public View Host { get; set; }
+    public View? Host { get; set; }
 
 
     /// <summary>Gets whether the ContextMenu is showing or not.</summary>
     /// <summary>Gets whether the ContextMenu is showing or not.</summary>
     public static bool IsShow { get; private set; }
     public static bool IsShow { get; private set; }
 
 
     /// <summary>Specifies the key that will activate the context menu.</summary>
     /// <summary>Specifies the key that will activate the context menu.</summary>
-    public Key Key
+    public new Key Key
     {
     {
         get => _key;
         get => _key;
         set
         set
@@ -74,10 +70,10 @@ public sealed class ContextMenu : IDisposable
     }
     }
 
 
     /// <summary>Gets the <see cref="MenuBar"/> that is hosting this context menu.</summary>
     /// <summary>Gets the <see cref="MenuBar"/> that is hosting this context menu.</summary>
-    public MenuBar MenuBar => _menuBar;
+    public MenuBar? MenuBar => _menuBar;
 
 
     /// <summary>Gets or sets the menu items for this context menu.</summary>
     /// <summary>Gets or sets the menu items for this context menu.</summary>
-    public MenuBarItem MenuItems { get; set; }
+    public MenuBarItem? MenuItems { get; private set; }
 
 
     /// <summary><see cref="Gui.MouseFlags"/> specifies the mouse action used to activate the context menu by mouse.</summary>
     /// <summary><see cref="Gui.MouseFlags"/> specifies the mouse action used to activate the context menu by mouse.</summary>
     public MouseFlags MouseFlags
     public MouseFlags MouseFlags
@@ -105,11 +101,10 @@ public sealed class ContextMenu : IDisposable
     /// <summary>Disposes the context menu object.</summary>
     /// <summary>Disposes the context menu object.</summary>
     public void Dispose ()
     public void Dispose ()
     {
     {
-        if (_menuBar is null)
+        if (_menuBar is { })
         {
         {
-            return;
+            _menuBar.MenuAllClosed -= MenuBar_MenuAllClosed;
         }
         }
-        _menuBar.MenuAllClosed -= MenuBar_MenuAllClosed;
         Application.UngrabMouse ();
         Application.UngrabMouse ();
         _menuBar?.Dispose ();
         _menuBar?.Dispose ();
         _menuBar = null;
         _menuBar = null;
@@ -126,18 +121,49 @@ public sealed class ContextMenu : IDisposable
     /// <summary>Hides (closes) the ContextMenu.</summary>
     /// <summary>Hides (closes) the ContextMenu.</summary>
     public void Hide ()
     public void Hide ()
     {
     {
+        RemoveKeyBindings (MenuItems);
         _menuBar?.CleanUp ();
         _menuBar?.CleanUp ();
         IsShow = false;
         IsShow = false;
     }
     }
 
 
+    private void RemoveKeyBindings (MenuBarItem? menuBarItem)
+    {
+        if (menuBarItem is null)
+        {
+            return;
+        }
+
+        foreach (var menuItem in menuBarItem.Children!)
+        {
+            // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
+            if (menuItem is null)
+            {
+                continue;
+            }
+
+            if (menuItem is MenuBarItem barItem)
+            {
+                RemoveKeyBindings (barItem);
+            }
+            else
+            {
+                if (menuItem.ShortcutKey != Key.Empty)
+                {
+                    // Remove an existent ShortcutKey
+                    _menuBar?.KeyBindings.Remove (menuItem.ShortcutKey);
+                }
+            }
+        }
+    }
+
     /// <summary>Event invoked when the <see cref="ContextMenu.Key"/> is changed.</summary>
     /// <summary>Event invoked when the <see cref="ContextMenu.Key"/> is changed.</summary>
-    public event EventHandler<KeyChangedEventArgs> KeyChanged;
+    public event EventHandler<KeyChangedEventArgs>? KeyChanged;
 
 
     /// <summary>Event invoked when the <see cref="ContextMenu.MouseFlags"/> is changed.</summary>
     /// <summary>Event invoked when the <see cref="ContextMenu.MouseFlags"/> is changed.</summary>
-    public event EventHandler<MouseFlagsChangedEventArgs> MouseFlagsChanged;
+    public event EventHandler<MouseFlagsChangedEventArgs>? MouseFlagsChanged;
 
 
     /// <summary>Shows (opens) the ContextMenu, displaying the <see cref="MenuItem"/>s it contains.</summary>
     /// <summary>Shows (opens) the ContextMenu, displaying the <see cref="MenuItem"/>s it contains.</summary>
-    public void Show ()
+    public void Show (MenuBarItem? menuItems)
     {
     {
         if (_menuBar is { })
         if (_menuBar is { })
         {
         {
@@ -145,6 +171,12 @@ public sealed class ContextMenu : IDisposable
             Dispose ();
             Dispose ();
         }
         }
 
 
+        if (menuItems is null || menuItems.Children.Length == 0)
+        {
+            return;
+        }
+
+        MenuItems = menuItems;
         _container = Application.Current;
         _container = Application.Current;
         _container!.Closing += Container_Closing;
         _container!.Closing += Container_Closing;
         _container.Deactivate += Container_Deactivate;
         _container.Deactivate += Container_Deactivate;
@@ -155,7 +187,7 @@ public sealed class ContextMenu : IDisposable
         if (Host is { })
         if (Host is { })
         {
         {
             Point pos = Host.ViewportToScreen (frame).Location;
             Point pos = Host.ViewportToScreen (frame).Location;
-            pos.Y += Host.Frame.Height - 1;
+            pos.Y += Host.Frame.Height > 0 ? Host.Frame.Height - 1 : 0;
 
 
             if (position != pos)
             if (position != pos)
             {
             {
@@ -224,9 +256,9 @@ public sealed class ContextMenu : IDisposable
         _menuBar.OpenMenu ();
         _menuBar.OpenMenu ();
     }
     }
 
 
-    private void Container_Closing (object sender, ToplevelClosingEventArgs obj) { Hide (); }
-    private void Container_Deactivate (object sender, ToplevelEventArgs e) { Hide (); }
-    private void Container_Disposing (object sender, EventArgs e) { Dispose (); }
+    private void Container_Closing (object? sender, ToplevelClosingEventArgs obj) { Hide (); }
+    private void Container_Deactivate (object? sender, ToplevelEventArgs e) { Hide (); }
+    private void Container_Disposing (object? sender, EventArgs e) { Dispose (); }
 
 
-    private void MenuBar_MenuAllClosed (object sender, EventArgs e) { Hide (); }
+    private void MenuBar_MenuAllClosed (object? sender, EventArgs e) { Hide (); }
 }
 }

+ 38 - 17
Terminal.Gui/Views/Menu/Menu.cs

@@ -1,3 +1,5 @@
+#nullable enable
+
 namespace Terminal.Gui;
 namespace Terminal.Gui;
 
 
 /// <summary>
 /// <summary>
@@ -11,7 +13,7 @@ internal sealed class Menu : View
     internal int _currentChild;
     internal int _currentChild;
     internal View _previousSubFocused;
     internal View _previousSubFocused;
 
 
-    internal static Rectangle MakeFrame (int x, int y, MenuItem [] items, Menu parent = null)
+    internal static Rectangle MakeFrame (int x, int y, MenuItem [] items, Menu? parent = null)
     {
     {
         if (items is null || items.Length == 0)
         if (items is null || items.Length == 0)
         {
         {
@@ -68,6 +70,25 @@ internal sealed class Menu : View
 
 
         Frame = MakeFrame (Frame.X, Frame.Y, _barItems?.Children, Parent);
         Frame = MakeFrame (Frame.X, Frame.Y, _barItems?.Children, Parent);
 
 
+        if (_barItems?.Children is { })
+        {
+            foreach (MenuItem menuItem in _barItems!.Children)
+            {
+                if (menuItem is { })
+                {
+                    menuItem._menuBar = Host;
+
+                    if (menuItem.ShortcutKey != Key.Empty)
+                    {
+                        KeyBinding keyBinding = new ([Command.Select], KeyBindingScope.HotKey, menuItem);
+                        // Remove an existent ShortcutKey
+                        menuItem._menuBar?.KeyBindings.Remove (menuItem.ShortcutKey);
+                        menuItem._menuBar?.KeyBindings.Add (menuItem.ShortcutKey, keyBinding);
+                    }
+                }
+            }
+        }
+
         if (_barItems is { IsTopLevel: true })
         if (_barItems is { IsTopLevel: true })
         {
         {
             // This is a standalone MenuItem on a MenuBar
             // This is a standalone MenuItem on a MenuBar
@@ -166,9 +187,9 @@ internal sealed class Menu : View
                         return true;
                         return true;
                     }
                     }
                    );
                    );
-        AddCommand (Command.Select, ctx => _host?.SelectItem (ctx.KeyBinding?.Context as MenuItem));
-        AddCommand (Command.ToggleExpandCollapse, ctx => ExpandCollapse (ctx.KeyBinding?.Context as MenuItem));
-        AddCommand (Command.HotKey, ctx => _host?.SelectItem (ctx.KeyBinding?.Context as MenuItem));
+        AddCommand (Command.Select, ctx => _host?.SelectItem ((ctx.KeyBinding?.Context as MenuItem)!));
+        AddCommand (Command.ToggleExpandCollapse, ctx => ExpandCollapse ((ctx.KeyBinding?.Context as MenuItem)!));
+        AddCommand (Command.HotKey, ctx => _host?.SelectItem ((ctx.KeyBinding?.Context as MenuItem)!));
 
 
         // Default key bindings for this view
         // Default key bindings for this view
         KeyBindings.Add (Key.CursorUp, Command.LineUp);
         KeyBindings.Add (Key.CursorUp, Command.LineUp);
@@ -179,7 +200,7 @@ internal sealed class Menu : View
         KeyBindings.Add (Key.Enter, Command.Accept);
         KeyBindings.Add (Key.Enter, Command.Accept);
     }
     }
 
 
-    private void AddKeyBindingsHotKey (MenuBarItem menuBarItem)
+    private void AddKeyBindingsHotKey (MenuBarItem? menuBarItem)
     {
     {
         if (menuBarItem is null || menuBarItem.Children is null)
         if (menuBarItem is null || menuBarItem.Children is null)
         {
         {
@@ -200,7 +221,7 @@ internal sealed class Menu : View
         }
         }
     }
     }
 
 
-    private void RemoveKeyBindingsHotKey (MenuBarItem menuBarItem)
+    private void RemoveKeyBindingsHotKey (MenuBarItem? menuBarItem)
     {
     {
         if (menuBarItem is null || menuBarItem.Children is null)
         if (menuBarItem is null || menuBarItem.Children is null)
         {
         {
@@ -219,7 +240,7 @@ internal sealed class Menu : View
 
 
     /// <summary>Called when a key bound to Command.ToggleExpandCollapse is pressed. This means a hot key was pressed.</summary>
     /// <summary>Called when a key bound to Command.ToggleExpandCollapse is pressed. This means a hot key was pressed.</summary>
     /// <returns></returns>
     /// <returns></returns>
-    private bool ExpandCollapse (MenuItem menuItem)
+    private bool ExpandCollapse (MenuItem? menuItem)
     {
     {
         if (!IsInitialized || !Visible)
         if (!IsInitialized || !Visible)
         {
         {
@@ -243,7 +264,7 @@ internal sealed class Menu : View
 
 
             if (m?.Children?.Length > 0)
             if (m?.Children?.Length > 0)
             {
             {
-                MenuItem item = _barItems.Children [_currentChild];
+                MenuItem? item = _barItems.Children [_currentChild];
 
 
                 if (item is null)
                 if (item is null)
                 {
                 {
@@ -297,7 +318,7 @@ internal sealed class Menu : View
         return _host.OnInvokingKeyBindings (keyEvent, scope);
         return _host.OnInvokingKeyBindings (keyEvent, scope);
     }
     }
 
 
-    private void Current_TerminalResized (object sender, SizeChangedEventArgs e)
+    private void Current_TerminalResized (object? sender, SizeChangedEventArgs e)
     {
     {
         if (_host.IsMenuOpen)
         if (_host.IsMenuOpen)
         {
         {
@@ -320,7 +341,7 @@ internal sealed class Menu : View
         }
         }
     }
     }
 
 
-    private void Application_RootMouseEvent (object sender, MouseEvent a)
+    private void Application_RootMouseEvent (object? sender, MouseEvent a)
     {
     {
         if (a.View is { } and (MenuBar or not Menu))
         if (a.View is { } and (MenuBar or not Menu))
         {
         {
@@ -350,7 +371,7 @@ internal sealed class Menu : View
         }
         }
     }
     }
 
 
-    internal Attribute DetermineColorSchemeFor (MenuItem item, int index)
+    internal Attribute DetermineColorSchemeFor (MenuItem? item, int index)
     {
     {
         if (item is null)
         if (item is null)
         {
         {
@@ -456,7 +477,7 @@ internal sealed class Menu : View
                 continue;
                 continue;
             }
             }
 
 
-            string textToDraw = null;
+            string? textToDraw = null;
             Rune nullCheckedChar = Glyphs.CheckStateNone;
             Rune nullCheckedChar = Glyphs.CheckStateNone;
             Rune checkChar = Glyphs.Selected;
             Rune checkChar = Glyphs.Selected;
             Rune uncheckedChar = Glyphs.UnSelected;
             Rune uncheckedChar = Glyphs.UnSelected;
@@ -468,7 +489,7 @@ internal sealed class Menu : View
             }
             }
 
 
             // Support Checked even though CheckType wasn't set
             // Support Checked even though CheckType wasn't set
-            if (item.CheckType == MenuItemCheckStyle.Checked && item.Checked is null)
+            if (item is { CheckType: MenuItemCheckStyle.Checked, Checked: null })
             {
             {
                 textToDraw = $"{nullCheckedChar} {item.Title}";
                 textToDraw = $"{nullCheckedChar} {item.Title}";
             }
             }
@@ -548,7 +569,7 @@ internal sealed class Menu : View
         // PositionCursor ();
         // PositionCursor ();
     }
     }
 
 
-    private void Current_DrawContentComplete (object sender, DrawEventArgs e)
+    private void Current_DrawContentComplete (object? sender, DrawEventArgs e)
     {
     {
         if (Visible)
         if (Visible)
         {
         {
@@ -573,9 +594,9 @@ internal sealed class Menu : View
         return _host?.PositionCursor ();
         return _host?.PositionCursor ();
     }
     }
 
 
-    public void Run (Action action)
+    public void Run (Action? action)
     {
     {
-        if (action is null || _host is null)
+        if (action is null)
         {
         {
             return;
             return;
         }
         }
@@ -900,7 +921,7 @@ internal sealed class Menu : View
 
 
             if (pos == -1
             if (pos == -1
                 && this != _host.OpenCurrentMenu
                 && this != _host.OpenCurrentMenu
-                && subMenu.Children != _host.OpenCurrentMenu._barItems.Children
+                && subMenu.Children != _host.OpenCurrentMenu!._barItems.Children
                 && !_host.CloseMenu (false, true))
                 && !_host.CloseMenu (false, true))
             {
             {
                 return false;
                 return false;

+ 65 - 63
Terminal.Gui/Views/Menu/MenuBar.cs

@@ -1,3 +1,5 @@
+#nullable enable
+
 namespace Terminal.Gui;
 namespace Terminal.Gui;
 
 
 /// <summary>
 /// <summary>
@@ -50,14 +52,14 @@ public class MenuBar : View, IDesignable
     internal bool _isMenuClosing;
     internal bool _isMenuClosing;
     internal bool _isMenuOpening;
     internal bool _isMenuOpening;
 
 
-    internal Menu _openMenu;
-    internal List<Menu> _openSubMenu;
+    internal Menu? _openMenu;
+    internal List<Menu>? _openSubMenu;
     internal int _selected;
     internal int _selected;
     internal int _selectedSub;
     internal int _selectedSub;
 
 
     private bool _initialCanFocus;
     private bool _initialCanFocus;
     private bool _isCleaning;
     private bool _isCleaning;
-    private View _lastFocused;
+    private View? _lastFocused;
     private Menu _ocm;
     private Menu _ocm;
     private View _previousFocused;
     private View _previousFocused;
     private bool _reopen;
     private bool _reopen;
@@ -66,8 +68,6 @@ public class MenuBar : View, IDesignable
     /// <summary>Initializes a new instance of the <see cref="MenuBar"/>.</summary>
     /// <summary>Initializes a new instance of the <see cref="MenuBar"/>.</summary>
     public MenuBar ()
     public MenuBar ()
     {
     {
-        MenuItem._menuBar = this;
-
         TabStop = TabBehavior.NoStop;
         TabStop = TabBehavior.NoStop;
         X = 0;
         X = 0;
         Y = 0;
         Y = 0;
@@ -125,7 +125,13 @@ public class MenuBar : View, IDesignable
                     }
                     }
                    );
                    );
         AddCommand (Command.ToggleExpandCollapse, ctx => Select (Menus.IndexOf (ctx.KeyBinding?.Context)));
         AddCommand (Command.ToggleExpandCollapse, ctx => Select (Menus.IndexOf (ctx.KeyBinding?.Context)));
-        AddCommand (Command.Select, ctx => Run ((ctx.KeyBinding?.Context as MenuItem)?.Action));
+        AddCommand (Command.Select, ctx =>
+                                    {
+                                        var res =  Run ((ctx.KeyBinding?.Context as MenuItem)?.Action!);
+                                        CloseAllMenus ();
+
+                                        return res;
+                                    });
 
 
         // Default key bindings for this view
         // Default key bindings for this view
         KeyBindings.Add (Key.CursorLeft, Command.Left);
         KeyBindings.Add (Key.CursorLeft, Command.Left);
@@ -150,7 +156,7 @@ public class MenuBar : View, IDesignable
     public bool IsMenuOpen { get; protected set; }
     public bool IsMenuOpen { get; protected set; }
 
 
     /// <summary>Gets the view that was last focused before opening the menu.</summary>
     /// <summary>Gets the view that was last focused before opening the menu.</summary>
-    public View LastFocused { get; private set; }
+    public View? LastFocused { get; private set; }
 
 
     /// <summary>
     /// <summary>
     ///     Gets or sets the array of <see cref="MenuBarItem"/>s for the menu. Only set this after the
     ///     Gets or sets the array of <see cref="MenuBarItem"/>s for the menu. Only set this after the
@@ -164,7 +170,7 @@ public class MenuBar : View, IDesignable
         {
         {
             _menus = value;
             _menus = value;
 
 
-            if (Menus is null)
+            if (Menus is [])
             {
             {
                 return;
                 return;
             }
             }
@@ -244,7 +250,7 @@ public class MenuBar : View, IDesignable
         }
         }
     }
     }
 
 
-    internal Menu OpenCurrentMenu
+    internal Menu? OpenCurrentMenu
     {
     {
         get => _ocm;
         get => _ocm;
         set
         set
@@ -376,12 +382,9 @@ public class MenuBar : View, IDesignable
     /// <summary>Opens the Menu programatically, as though the F9 key were pressed.</summary>
     /// <summary>Opens the Menu programatically, as though the F9 key were pressed.</summary>
     public void OpenMenu ()
     public void OpenMenu ()
     {
     {
-        MenuBar mbar = GetMouseGrabViewInstance (this);
+        MenuBar? mbar = GetMouseGrabViewInstance (this);
 
 
-        if (mbar is { })
-        {
-            mbar.CleanUp ();
-        }
+        mbar?.CleanUp ();
 
 
         if (!Enabled || _openMenu is { })
         if (!Enabled || _openMenu is { })
         {
         {
@@ -391,11 +394,11 @@ public class MenuBar : View, IDesignable
         _selected = 0;
         _selected = 0;
         SetNeedsDisplay ();
         SetNeedsDisplay ();
 
 
-        _previousFocused = SuperView is null ? Application.Current?.Focused : SuperView.Focused;
+        _previousFocused = (SuperView is null ? Application.Current?.Focused : SuperView.Focused)!;
         OpenMenu (_selected);
         OpenMenu (_selected);
 
 
         if (!SelectEnabledItem (
         if (!SelectEnabledItem (
-                                OpenCurrentMenu.BarItems.Children,
+                                OpenCurrentMenu!.BarItems.Children,
                                 OpenCurrentMenu._currentChild,
                                 OpenCurrentMenu._currentChild,
                                 out OpenCurrentMenu._currentChild
                                 out OpenCurrentMenu._currentChild
                                )
                                )
@@ -523,11 +526,18 @@ public class MenuBar : View, IDesignable
         IsMenuOpen = false;
         IsMenuOpen = false;
         _openedByAltKey = false;
         _openedByAltKey = false;
         OnMenuAllClosed ();
         OnMenuAllClosed ();
+
+        if (Application.Current is { })
+        {
+            // Close others menu bar opened
+            View? cm = Application.Current!.Subviews.FirstOrDefault (v => v is Menu cm && cm.Host != this && cm.Host.IsMenuOpen);
+            ((Menu)cm!)?.Host.CleanUp ();
+        }
     }
     }
 
 
-    internal bool CloseMenu (bool reopen = false, bool isSubMenu = false, bool ignoreUseSubMenusSingleFrame = false)
+    internal bool CloseMenu (bool reopen, bool isSubMenu, bool ignoreUseSubMenusSingleFrame = false)
     {
     {
-        MenuBarItem mbi = isSubMenu ? OpenCurrentMenu.BarItems : _openMenu?.BarItems;
+        MenuBarItem? mbi = isSubMenu ? OpenCurrentMenu!.BarItems : _openMenu?.BarItems;
 
 
         if (UseSubMenusSingleFrame && mbi is { } && !ignoreUseSubMenusSingleFrame && mbi.Parent is { })
         if (UseSubMenusSingleFrame && mbi is { } && !ignoreUseSubMenusSingleFrame && mbi.Parent is { })
         {
         {
@@ -615,7 +625,7 @@ public class MenuBar : View, IDesignable
                 _selectedSub = -1;
                 _selectedSub = -1;
                 SetNeedsDisplay ();
                 SetNeedsDisplay ();
                 RemoveAllOpensSubMenus ();
                 RemoveAllOpensSubMenus ();
-                OpenCurrentMenu._previousSubFocused.SetFocus ();
+                OpenCurrentMenu!._previousSubFocused.SetFocus ();
                 _openSubMenu = null;
                 _openSubMenu = null;
                 IsMenuOpen = true;
                 IsMenuOpen = true;
 
 
@@ -637,8 +647,8 @@ public class MenuBar : View, IDesignable
             return Point.Empty;
             return Point.Empty;
         }
         }
 
 
-        Rectangle superViewFrame = SuperView is null ? Application.Screen : SuperView.Frame;
-        View sv = SuperView is null ? Application.Current : SuperView;
+        Rectangle superViewFrame = SuperView?.Frame ?? Application.Screen;
+        View? sv = SuperView ?? Application.Current;
 
 
         if (sv is null)
         if (sv is null)
         {
         {
@@ -680,7 +690,7 @@ public class MenuBar : View, IDesignable
                 OpenMenu (_selected);
                 OpenMenu (_selected);
 
 
                 SelectEnabledItem (
                 SelectEnabledItem (
-                                   OpenCurrentMenu.BarItems.Children,
+                                   OpenCurrentMenu!.BarItems.Children,
                                    OpenCurrentMenu._currentChild,
                                    OpenCurrentMenu._currentChild,
                                    out OpenCurrentMenu._currentChild
                                    out OpenCurrentMenu._currentChild
                                   );
                                   );
@@ -696,7 +706,7 @@ public class MenuBar : View, IDesignable
                 }
                 }
                 else
                 else
                 {
                 {
-                    MenuBarItem subMenu = OpenCurrentMenu._currentChild > -1 && OpenCurrentMenu.BarItems.Children.Length > 0
+                    MenuBarItem? subMenu = OpenCurrentMenu!._currentChild > -1 && OpenCurrentMenu.BarItems.Children.Length > 0
                                               ? OpenCurrentMenu.BarItems.SubMenu (
                                               ? OpenCurrentMenu.BarItems.SubMenu (
                                                                                   OpenCurrentMenu.BarItems.Children [OpenCurrentMenu._currentChild]
                                                                                   OpenCurrentMenu.BarItems.Children [OpenCurrentMenu._currentChild]
                                                                                  )
                                                                                  )
@@ -837,7 +847,7 @@ public class MenuBar : View, IDesignable
                 }
                 }
                 else
                 else
                 {
                 {
-                    Menu last = _openSubMenu.Count > 0 ? _openSubMenu.Last () : _openMenu;
+                    Menu? last = _openSubMenu.Count > 0 ? _openSubMenu.Last () : _openMenu;
 
 
                     if (!UseSubMenusSingleFrame)
                     if (!UseSubMenusSingleFrame)
                     {
                     {
@@ -854,10 +864,10 @@ public class MenuBar : View, IDesignable
                     }
                     }
                     else
                     else
                     {
                     {
-                        Menu first = _openSubMenu.Count > 0 ? _openSubMenu.First () : _openMenu;
+                        Menu? first = _openSubMenu.Count > 0 ? _openSubMenu.First () : _openMenu;
 
 
                         // 2 is for the parent and the separator
                         // 2 is for the parent and the separator
-                        MenuItem [] mbi = new MenuItem [2 + subMenu.Children.Length];
+                        MenuItem? [] mbi = new MenuItem [2 + subMenu.Children.Length];
                         mbi [0] = new () { Title = subMenu.Title, Parent = subMenu };
                         mbi [0] = new () { Title = subMenu.Title, Parent = subMenu };
                         mbi [1] = null;
                         mbi [1] = null;
 
 
@@ -870,7 +880,7 @@ public class MenuBar : View, IDesignable
 
 
                         OpenCurrentMenu = new ()
                         OpenCurrentMenu = new ()
                         {
                         {
-                            Host = this, X = first.Frame.Left, Y = first.Frame.Top, BarItems = newSubMenu
+                            Host = this, X = first!.Frame.Left, Y = first.Frame.Top, BarItems = newSubMenu
                         };
                         };
                         last.Visible = false;
                         last.Visible = false;
                         Application.GrabMouse (OpenCurrentMenu);
                         Application.GrabMouse (OpenCurrentMenu);
@@ -892,7 +902,7 @@ public class MenuBar : View, IDesignable
 
 
                 if (_selectedSub > -1
                 if (_selectedSub > -1
                     && SelectEnabledItem (
                     && SelectEnabledItem (
-                                          OpenCurrentMenu.BarItems.Children,
+                                          OpenCurrentMenu!.BarItems.Children,
                                           OpenCurrentMenu._currentChild,
                                           OpenCurrentMenu._currentChild,
                                           out OpenCurrentMenu._currentChild
                                           out OpenCurrentMenu._currentChild
                                          ))
                                          ))
@@ -929,7 +939,7 @@ public class MenuBar : View, IDesignable
                 OpenMenu (_selected);
                 OpenMenu (_selected);
 
 
                 if (!SelectEnabledItem (
                 if (!SelectEnabledItem (
-                                        OpenCurrentMenu.BarItems.Children,
+                                        OpenCurrentMenu!.BarItems.Children,
                                         OpenCurrentMenu._currentChild,
                                         OpenCurrentMenu._currentChild,
                                         out OpenCurrentMenu._currentChild,
                                         out OpenCurrentMenu._currentChild,
                                         false
                                         false
@@ -961,7 +971,7 @@ public class MenuBar : View, IDesignable
         {
         {
             foreach (Menu item in _openSubMenu)
             foreach (Menu item in _openSubMenu)
             {
             {
-                Application.Current.Remove (item);
+                Application.Current!.Remove (item);
                 item.Dispose ();
                 item.Dispose ();
             }
             }
         }
         }
@@ -974,20 +984,20 @@ public class MenuBar : View, IDesignable
             return false;
             return false;
         }
         }
 
 
-        Application.MainLoop.AddIdle (
-                                      () =>
-                                      {
-                                          action ();
+        Application.MainLoop!.AddIdle (
+                                       () =>
+                                       {
+                                           action ();
 
 
-                                          return false;
-                                      }
-                                     );
+                                           return false;
+                                       }
+                                      );
 
 
         return true;
         return true;
     }
     }
 
 
     internal bool SelectEnabledItem (
     internal bool SelectEnabledItem (
-        IEnumerable<MenuItem> children,
+        IEnumerable<MenuItem>? children,
         int current,
         int current,
         out int newCurrent,
         out int newCurrent,
         bool forward = true
         bool forward = true
@@ -1099,7 +1109,7 @@ public class MenuBar : View, IDesignable
         return new (-2, 0);
         return new (-2, 0);
     }
     }
 
 
-    private void MenuBar_Added (object sender, SuperViewChangedEventArgs e)
+    private void MenuBar_Added (object? sender, SuperViewChangedEventArgs e)
     {
     {
         _initialCanFocus = CanFocus;
         _initialCanFocus = CanFocus;
         Added -= MenuBar_Added;
         Added -= MenuBar_Added;
@@ -1146,7 +1156,7 @@ public class MenuBar : View, IDesignable
             OpenMenu (i);
             OpenMenu (i);
 
 
             if (!SelectEnabledItem (
             if (!SelectEnabledItem (
-                                    OpenCurrentMenu.BarItems.Children,
+                                    OpenCurrentMenu!.BarItems.Children,
                                     OpenCurrentMenu._currentChild,
                                     OpenCurrentMenu._currentChild,
                                     out OpenCurrentMenu._currentChild
                                     out OpenCurrentMenu._currentChild
                                    )
                                    )
@@ -1177,7 +1187,7 @@ public class MenuBar : View, IDesignable
         for (int i = _openSubMenu.Count - 1; i > index; i--)
         for (int i = _openSubMenu.Count - 1; i > index; i--)
         {
         {
             _isMenuClosing = true;
             _isMenuClosing = true;
-            Menu menu;
+            Menu? menu;
 
 
             if (_openSubMenu.Count - 1 > 0)
             if (_openSubMenu.Count - 1 > 0)
             {
             {
@@ -1188,7 +1198,7 @@ public class MenuBar : View, IDesignable
                 menu = _openMenu;
                 menu = _openMenu;
             }
             }
 
 
-            if (!menu.Visible)
+            if (!menu!.Visible)
             {
             {
                 menu.Visible = true;
                 menu.Visible = true;
             }
             }
@@ -1199,7 +1209,7 @@ public class MenuBar : View, IDesignable
             if (_openSubMenu is { })
             if (_openSubMenu is { })
             {
             {
                 menu = _openSubMenu [i];
                 menu = _openSubMenu [i];
-                Application.Current.Remove (menu);
+                Application.Current!.Remove (menu);
                 _openSubMenu.Remove (menu);
                 _openSubMenu.Remove (menu);
 
 
                 if (Application.MouseGrabView == menu)
                 if (Application.MouseGrabView == menu)
@@ -1213,7 +1223,7 @@ public class MenuBar : View, IDesignable
             RemoveSubMenu (i, ignoreUseSubMenusSingleFrame);
             RemoveSubMenu (i, ignoreUseSubMenusSingleFrame);
         }
         }
 
 
-        if (_openSubMenu.Count > 0)
+        if (_openSubMenu!.Count > 0)
         {
         {
             OpenCurrentMenu = _openSubMenu.Last ();
             OpenCurrentMenu = _openSubMenu.Last ();
         }
         }
@@ -1310,7 +1320,7 @@ public class MenuBar : View, IDesignable
                     continue;
                     continue;
                 }
                 }
 
 
-                if (open == OpenCurrentMenu.BarItems && i == index)
+                if (open == OpenCurrentMenu!.BarItems && i == index)
                 {
                 {
                     CloseAllMenus ();
                     CloseAllMenus ();
                     return true;
                     return true;
@@ -1411,7 +1421,7 @@ public class MenuBar : View, IDesignable
                     else if (_selected != i
                     else if (_selected != i
                              && _selected > -1
                              && _selected > -1
                              && (me.Flags == MouseFlags.ReportMousePosition
                              && (me.Flags == MouseFlags.ReportMousePosition
-                                 || (me.Flags == MouseFlags.Button1Pressed && me.Flags == MouseFlags.ReportMousePosition)))
+                                 || (me.Flags is MouseFlags.Button1Pressed && me.Flags == MouseFlags.ReportMousePosition)))
                     {
                     {
                         if (IsMenuOpen)
                         if (IsMenuOpen)
                         {
                         {
@@ -1463,9 +1473,9 @@ public class MenuBar : View, IDesignable
     {
     {
         if (Application.MouseGrabView is { })
         if (Application.MouseGrabView is { })
         {
         {
-            if (me.View is MenuBar || me.View is Menu)
+            if (me.View is MenuBar or Menu)
             {
             {
-                MenuBar mbar = GetMouseGrabViewInstance (me.View);
+                MenuBar? mbar = GetMouseGrabViewInstance (me.View);
 
 
                 if (mbar is { })
                 if (mbar is { })
                 {
                 {
@@ -1563,14 +1573,14 @@ public class MenuBar : View, IDesignable
         return true;
         return true;
     }
     }
 
 
-    private MenuBar GetMouseGrabViewInstance (View view)
+    private MenuBar? GetMouseGrabViewInstance (View? view)
     {
     {
         if (view is null || Application.MouseGrabView is null)
         if (view is null || Application.MouseGrabView is null)
         {
         {
             return null;
             return null;
         }
         }
 
 
-        MenuBar hostView = null;
+        MenuBar? hostView = null;
 
 
         if (view is MenuBar)
         if (view is MenuBar)
         {
         {
@@ -1582,15 +1592,15 @@ public class MenuBar : View, IDesignable
         }
         }
 
 
         View grabView = Application.MouseGrabView;
         View grabView = Application.MouseGrabView;
-        MenuBar hostGrabView = null;
+        MenuBar? hostGrabView = null;
 
 
-        if (grabView is MenuBar)
+        if (grabView is MenuBar bar)
         {
         {
-            hostGrabView = (MenuBar)grabView;
+            hostGrabView = bar;
         }
         }
-        else if (grabView is Menu)
+        else if (grabView is Menu menu)
         {
         {
-            hostGrabView = ((Menu)grabView).Host;
+            hostGrabView = menu.Host;
         }
         }
 
 
         return hostView != hostGrabView ? hostGrabView : null;
         return hostView != hostGrabView ? hostGrabView : null;
@@ -1770,12 +1780,4 @@ public class MenuBar : View, IDesignable
         ];
         ];
         return true;
         return true;
     }
     }
-
-    /// <inheritdoc />
-    protected override void Dispose (bool disposing)
-    {
-        MenuItem._menuBar = null;
-
-        base.Dispose (disposing);
-    }
 }
 }

+ 18 - 11
Terminal.Gui/Views/Menu/MenuBarItem.cs

@@ -1,3 +1,5 @@
+#nullable enable
+
 namespace Terminal.Gui;
 namespace Terminal.Gui;
 
 
 /// <summary>
 /// <summary>
@@ -16,8 +18,8 @@ public class MenuBarItem : MenuItem
         string title,
         string title,
         string help,
         string help,
         Action action,
         Action action,
-        Func<bool> canExecute = null,
-        MenuItem parent = null
+        Func<bool>? canExecute = null,
+        MenuItem? parent = null
     ) : base (title, help, action, canExecute, parent)
     ) : base (title, help, action, canExecute, parent)
     {
     {
         SetInitialProperties (title, null, null, true);
         SetInitialProperties (title, null, null, true);
@@ -27,13 +29,13 @@ public class MenuBarItem : MenuItem
     /// <param name="title">Title for the menu item.</param>
     /// <param name="title">Title for the menu item.</param>
     /// <param name="children">The items in the current menu.</param>
     /// <param name="children">The items in the current menu.</param>
     /// <param name="parent">The parent <see cref="MenuItem"/> of this if any.</param>
     /// <param name="parent">The parent <see cref="MenuItem"/> of this if any.</param>
-    public MenuBarItem (string title, MenuItem [] children, MenuItem parent = null) { SetInitialProperties (title, children, parent); }
+    public MenuBarItem (string title, MenuItem [] children, MenuItem? parent = null) { SetInitialProperties (title, children, parent); }
 
 
     /// <summary>Initializes a new <see cref="MenuBarItem"/> with separate list of items.</summary>
     /// <summary>Initializes a new <see cref="MenuBarItem"/> with separate list of items.</summary>
     /// <param name="title">Title for the menu item.</param>
     /// <param name="title">Title for the menu item.</param>
     /// <param name="children">The list of items in the current menu.</param>
     /// <param name="children">The list of items in the current menu.</param>
     /// <param name="parent">The parent <see cref="MenuItem"/> of this if any.</param>
     /// <param name="parent">The parent <see cref="MenuItem"/> of this if any.</param>
-    public MenuBarItem (string title, List<MenuItem []> children, MenuItem parent = null) { SetInitialProperties (title, children, parent); }
+    public MenuBarItem (string title, List<MenuItem []> children, MenuItem? parent = null) { SetInitialProperties (title, children, parent); }
 
 
     /// <summary>Initializes a new <see cref="MenuBarItem"/>.</summary>
     /// <summary>Initializes a new <see cref="MenuBarItem"/>.</summary>
     /// <param name="children">The items in the current menu.</param>
     /// <param name="children">The items in the current menu.</param>
@@ -47,7 +49,7 @@ public class MenuBarItem : MenuItem
     ///     <see cref="MenuBarItem"/>
     ///     <see cref="MenuBarItem"/>
     /// </summary>
     /// </summary>
     /// <value>The children.</value>
     /// <value>The children.</value>
-    public MenuItem [] Children { get; set; }
+    public MenuItem []? Children { get; set; }
 
 
     internal bool IsTopLevel => Parent is null && (Children is null || Children.Length == 0) && Action != null;
     internal bool IsTopLevel => Parent is null && (Children is null || Children.Length == 0) && Action != null;
 
 
@@ -81,13 +83,13 @@ public class MenuBarItem : MenuItem
     /// <returns>Returns <c>true</c> if it is a submenu. <c>false</c> otherwise.</returns>
     /// <returns>Returns <c>true</c> if it is a submenu. <c>false</c> otherwise.</returns>
     public bool IsSubMenuOf (MenuItem menuItem)
     public bool IsSubMenuOf (MenuItem menuItem)
     {
     {
-        return Children.Any (child => child == menuItem && child.Parent == menuItem.Parent);
+        return Children!.Any (child => child == menuItem && child.Parent == menuItem.Parent);
     }
     }
 
 
     /// <summary>Check if a <see cref="MenuItem"/> is a <see cref="MenuBarItem"/>.</summary>
     /// <summary>Check if a <see cref="MenuItem"/> is a <see cref="MenuBarItem"/>.</summary>
     /// <param name="menuItem"></param>
     /// <param name="menuItem"></param>
     /// <returns>Returns a <see cref="MenuBarItem"/> or null otherwise.</returns>
     /// <returns>Returns a <see cref="MenuBarItem"/> or null otherwise.</returns>
-    public MenuBarItem SubMenu (MenuItem menuItem) { return menuItem as MenuBarItem; }
+    public MenuBarItem SubMenu (MenuItem menuItem) { return (menuItem as MenuBarItem)!; }
 
 
     internal void AddShortcutKeyBindings (MenuBar menuBar)
     internal void AddShortcutKeyBindings (MenuBar menuBar)
     {
     {
@@ -96,20 +98,24 @@ public class MenuBarItem : MenuItem
             return;
             return;
         }
         }
 
 
+        _menuBar = menuBar;
+
+        // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
         foreach (MenuItem menuItem in Children.Where (m => m is { }))
         foreach (MenuItem menuItem in Children.Where (m => m is { }))
         {
         {
             // For MenuBar only add shortcuts for submenus
             // For MenuBar only add shortcuts for submenus
 
 
             if (menuItem.ShortcutKey != Key.Empty)
             if (menuItem.ShortcutKey != Key.Empty)
             {
             {
-                menuItem.UpdateShortcutKeyBinding (Key.Empty);
+                menuItem._menuBar = menuBar;
+                menuItem.UpdateShortcutKeyBinding (menuItem._menuBar, Key.Empty);
             }
             }
 
 
             SubMenu (menuItem)?.AddShortcutKeyBindings (menuBar);
             SubMenu (menuItem)?.AddShortcutKeyBindings (menuBar);
         }
         }
     }
     }
 
 
-    private void SetInitialProperties (string title, object children, MenuItem parent = null, bool isTopLevel = false)
+    private void SetInitialProperties (string title, object? children, MenuItem? parent = null, bool isTopLevel = false)
     {
     {
         if (!isTopLevel && children is null)
         if (!isTopLevel && children is null)
         {
         {
@@ -179,7 +185,7 @@ public class MenuBarItem : MenuItem
     /// Add a <see cref="MenuBarItem"/> dynamically into the <see cref="MenuBar"/><c>.Menus</c>.
     /// Add a <see cref="MenuBarItem"/> dynamically into the <see cref="MenuBar"/><c>.Menus</c>.
     /// </summary>
     /// </summary>
     /// <param name="menuItem"></param>
     /// <param name="menuItem"></param>
-    public void AddMenuBarItem (MenuItem menuItem = null)
+    public void AddMenuBarItem (MenuItem? menuItem = null)
     {
     {
         if (menuItem is null)
         if (menuItem is null)
         {
         {
@@ -227,13 +233,14 @@ public class MenuBarItem : MenuItem
                 _menuBar?.KeyBindings.Remove (HotKey.WithAlt);
                 _menuBar?.KeyBindings.Remove (HotKey.WithAlt);
             }
             }
 
 
-            _menuBar!.Menus [index] = null;
+            _menuBar!.Menus [index] = null!;
         }
         }
 
 
         var i = 0;
         var i = 0;
 
 
         foreach (MenuBarItem m in _menuBar.Menus)
         foreach (MenuBarItem m in _menuBar.Menus)
         {
         {
+            // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
             if (m != null)
             if (m != null)
             {
             {
                 _menuBar.Menus [i] = m;
                 _menuBar.Menus [i] = m;

+ 18 - 14
Terminal.Gui/Views/Menu/MenuItem.cs

@@ -1,3 +1,5 @@
+#nullable enable
+
 namespace Terminal.Gui;
 namespace Terminal.Gui;
 
 
 /// <summary>
 /// <summary>
@@ -6,10 +8,10 @@ namespace Terminal.Gui;
 /// </summary>
 /// </summary>
 public class MenuItem
 public class MenuItem
 {
 {
-    internal static MenuBar _menuBar;
+    internal MenuBar _menuBar;
 
 
     /// <summary>Initializes a new instance of <see cref="MenuItem"/></summary>
     /// <summary>Initializes a new instance of <see cref="MenuItem"/></summary>
-    public MenuItem (Key shortcutKey = null) : this ("", "", null, null, null, shortcutKey) { }
+    public MenuItem (Key? shortcutKey = null) : this ("", "", null, null, null, shortcutKey) { }
 
 
     /// <summary>Initializes a new instance of <see cref="MenuItem"/>.</summary>
     /// <summary>Initializes a new instance of <see cref="MenuItem"/>.</summary>
     /// <param name="title">Title for the menu item.</param>
     /// <param name="title">Title for the menu item.</param>
@@ -21,24 +23,24 @@ public class MenuItem
     public MenuItem (
     public MenuItem (
         string title,
         string title,
         string help,
         string help,
-        Action action,
-        Func<bool> canExecute = null,
-        MenuItem parent = null,
-        Key shortcutKey = null
+        Action? action,
+        Func<bool>? canExecute = null,
+        MenuItem? parent = null,
+        Key? shortcutKey = null
     )
     )
     {
     {
         Title = title ?? "";
         Title = title ?? "";
         Help = help ?? "";
         Help = help ?? "";
-        Action = action;
-        CanExecute = canExecute;
-        Parent = parent;
+        Action = action!;
+        CanExecute = canExecute!;
+        Parent = parent!;
 
 
         if (Parent is { } && Parent.ShortcutKey != Key.Empty)
         if (Parent is { } && Parent.ShortcutKey != Key.Empty)
         {
         {
             Parent.ShortcutKey = Key.Empty;
             Parent.ShortcutKey = Key.Empty;
         }
         }
         // Setter will ensure Key.Empty if it's null
         // Setter will ensure Key.Empty if it's null
-        ShortcutKey = shortcutKey;
+        ShortcutKey = shortcutKey!;
     }
     }
 
 
     private bool _allowNullChecked;
     private bool _allowNullChecked;
@@ -112,7 +114,7 @@ public class MenuItem
 
 
     /// <summary>Gets the parent for this <see cref="MenuItem"/>.</summary>
     /// <summary>Gets the parent for this <see cref="MenuItem"/>.</summary>
     /// <value>The parent.</value>
     /// <value>The parent.</value>
-    public MenuItem Parent { get; set; }
+    public MenuItem? Parent { get; set; }
 
 
     /// <summary>Gets or sets the title of the menu item .</summary>
     /// <summary>Gets or sets the title of the menu item .</summary>
     /// <value>The title.</value>
     /// <value>The title.</value>
@@ -267,7 +269,7 @@ public class MenuItem
         {
         {
             var oldKey = _shortcutKey ?? Key.Empty;
             var oldKey = _shortcutKey ?? Key.Empty;
             _shortcutKey = value ?? Key.Empty;
             _shortcutKey = value ?? Key.Empty;
-            UpdateShortcutKeyBinding (oldKey);
+            UpdateShortcutKeyBinding (_menuBar, oldKey);
         }
         }
     }
     }
 
 
@@ -304,8 +306,10 @@ public class MenuItem
         }
         }
     }
     }
 
 
-    internal void UpdateShortcutKeyBinding (Key oldKey)
+    internal void UpdateShortcutKeyBinding (MenuBar menuBar, Key oldKey)
     {
     {
+        _menuBar ??= menuBar;
+
         if (_menuBar is null)
         if (_menuBar is null)
         {
         {
             return;
             return;
@@ -334,7 +338,7 @@ public class MenuItem
     {
     {
         if (Parent is { })
         if (Parent is { })
         {
         {
-            MenuItem [] childrens = ((MenuBarItem)Parent).Children;
+            MenuItem []? childrens = ((MenuBarItem)Parent).Children;
             var i = 0;
             var i = 0;
 
 
             foreach (MenuItem c in childrens)
             foreach (MenuItem c in childrens)

+ 3 - 5
Terminal.Gui/Views/TextField.cs

@@ -405,7 +405,7 @@ public class TextField : View
 
 
         _currentCulture = Thread.CurrentThread.CurrentUICulture;
         _currentCulture = Thread.CurrentThread.CurrentUICulture;
 
 
-        ContextMenu = new ContextMenu { Host = this, MenuItems = BuildContextMenuBarItem () };
+        ContextMenu = new ContextMenu { Host = this };
         ContextMenu.KeyChanged += ContextMenu_KeyChanged;
         ContextMenu.KeyChanged += ContextMenu_KeyChanged;
 
 
         KeyBindings.Add (ContextMenu.Key, KeyBindingScope.HotKey, Command.ShowContextMenu);
         KeyBindings.Add (ContextMenu.Key, KeyBindingScope.HotKey, Command.ShowContextMenu);
@@ -1853,14 +1853,12 @@ public class TextField : View
 
 
     private void ShowContextMenu ()
     private void ShowContextMenu ()
     {
     {
-        if (_currentCulture != Thread.CurrentThread.CurrentUICulture)
+        if (!Equals (_currentCulture, Thread.CurrentThread.CurrentUICulture))
         {
         {
             _currentCulture = Thread.CurrentThread.CurrentUICulture;
             _currentCulture = Thread.CurrentThread.CurrentUICulture;
-
-            ContextMenu.MenuItems = BuildContextMenuBarItem ();
         }
         }
 
 
-        ContextMenu.Show ();
+        ContextMenu.Show (BuildContextMenuBarItem ());
     }
     }
 
 
     private void TextField_Added (object sender, SuperViewChangedEventArgs e)
     private void TextField_Added (object sender, SuperViewChangedEventArgs e)

+ 5 - 7
Terminal.Gui/Views/TextView.cs

@@ -2498,7 +2498,7 @@ public class TextView : View
 
 
         _currentCulture = Thread.CurrentThread.CurrentUICulture;
         _currentCulture = Thread.CurrentThread.CurrentUICulture;
 
 
-        ContextMenu = new () { MenuItems = BuildContextMenuBarItem () };
+        ContextMenu = new ();
         ContextMenu.KeyChanged += ContextMenu_KeyChanged!;
         ContextMenu.KeyChanged += ContextMenu_KeyChanged!;
 
 
         KeyBindings.Add ((KeyCode)ContextMenu.Key, KeyBindingScope.HotKey, Command.ShowContextMenu);
         KeyBindings.Add ((KeyCode)ContextMenu.Key, KeyBindingScope.HotKey, Command.ShowContextMenu);
@@ -3494,7 +3494,7 @@ public class TextView : View
         }
         }
         else if (ev.Flags == ContextMenu!.MouseFlags)
         else if (ev.Flags == ContextMenu!.MouseFlags)
         {
         {
-            ContextMenu.Position = new (ev.Position.X + 2, ev.Position.Y + 2);
+            ContextMenu.Position = ViewportToScreen ((Viewport with { X = ev.Position.X, Y = ev.Position.Y }).Location);
             ShowContextMenu ();
             ShowContextMenu ();
         }
         }
 
 
@@ -4131,7 +4131,7 @@ public class TextView : View
 
 
     private void AppendClipboard (string text) { Clipboard.Contents += text; }
     private void AppendClipboard (string text) { Clipboard.Contents += text; }
 
 
-    private MenuBarItem BuildContextMenuBarItem ()
+    private MenuBarItem? BuildContextMenuBarItem ()
     {
     {
         return new (
         return new (
                     new MenuItem []
                     new MenuItem []
@@ -6289,14 +6289,12 @@ public class TextView : View
 
 
     private void ShowContextMenu ()
     private void ShowContextMenu ()
     {
     {
-        if (_currentCulture != Thread.CurrentThread.CurrentUICulture)
+        if (!Equals (_currentCulture, Thread.CurrentThread.CurrentUICulture))
         {
         {
             _currentCulture = Thread.CurrentThread.CurrentUICulture;
             _currentCulture = Thread.CurrentThread.CurrentUICulture;
-
-            ContextMenu!.MenuItems = BuildContextMenuBarItem ();
         }
         }
 
 
-        ContextMenu!.Show ();
+        ContextMenu!.Show (BuildContextMenuBarItem ());
     }
     }
 
 
     private void StartSelecting ()
     private void StartSelecting ()

+ 25 - 24
UICatalog/Scenarios/CharacterMap.cs

@@ -902,31 +902,32 @@ internal class CharMap : View
 
 
             _contextMenu = new ()
             _contextMenu = new ()
             {
             {
-                Position = new (me.Position.X + 1, me.Position.Y + 1),
-                MenuItems = new (
-                                 new MenuItem []
-                                 {
-                                     new (
-                                          "_Copy Glyph",
-                                          "",
-                                          CopyGlyph,
-                                          null,
-                                          null,
-                                          (KeyCode)Key.C.WithCtrl
-                                         ),
-                                     new (
-                                          "Copy Code _Point",
-                                          "",
-                                          CopyCodePoint,
-                                          null,
-                                          null,
-                                          (KeyCode)Key.C.WithCtrl
-                                                      .WithShift
-                                         )
-                                 }
-                                )
+                Position = new (me.Position.X + 1, me.Position.Y + 1)
             };
             };
-            _contextMenu.Show ();
+
+            MenuBarItem menuItems = new (
+                                         new MenuItem []
+                                         {
+                                             new (
+                                                  "_Copy Glyph",
+                                                  "",
+                                                  CopyGlyph,
+                                                  null,
+                                                  null,
+                                                  (KeyCode)Key.C.WithCtrl
+                                                 ),
+                                             new (
+                                                  "Copy Code _Point",
+                                                  "",
+                                                  CopyCodePoint,
+                                                  null,
+                                                  null,
+                                                  (KeyCode)Key.C.WithCtrl
+                                                              .WithShift
+                                                 )
+                                         }
+                                        );
+            _contextMenu.Show (menuItems);
         }
         }
     }
     }
 
 

+ 118 - 118
UICatalog/Scenarios/ContextMenus.cs

@@ -163,133 +163,133 @@ public class ContextMenus : Scenario
         _contextMenu = new()
         _contextMenu = new()
         {
         {
             Position = new (x, y),
             Position = new (x, y),
-            MenuItems = new (
-                             new []
-                             {
-                                 new (
-                                      "_Configuration",
-                                      "Show configuration",
-                                      () => MessageBox.Query (
-                                                              50,
-                                                              5,
-                                                              "Info",
-                                                              "This would open settings dialog",
-                                                              "Ok"
-                                                             )
-                                     ),
-                                 new MenuBarItem (
-                                                  "More options",
-                                                  new MenuItem []
-                                                  {
-                                                      new (
-                                                           "_Setup",
-                                                           "Change settings",
-                                                           () => MessageBox
-                                                               .Query (
-                                                                       50,
-                                                                       5,
-                                                                       "Info",
-                                                                       "This would open setup dialog",
-                                                                       "Ok"
-                                                                      ),
-                                                           shortcutKey: KeyCode.T
-                                                                     | KeyCode
-                                                                         .CtrlMask
-                                                          ),
-                                                      new (
-                                                           "_Maintenance",
-                                                           "Maintenance mode",
-                                                           () => MessageBox
-                                                               .Query (
-                                                                       50,
-                                                                       5,
-                                                                       "Info",
-                                                                       "This would open maintenance dialog",
-                                                                       "Ok"
-                                                                      )
-                                                          )
-                                                  }
-                                                 ),
-                                 new MenuBarItem (
-                                                  "_Languages",
-                                                  GetSupportedCultures ()
-                                                 ),
-                                 _miForceMinimumPosToZero =
-                                     new (
-                                          "ForceMinimumPosToZero",
-                                          "",
-                                          () =>
-                                          {
-                                              _miForceMinimumPosToZero
-                                                      .Checked =
-                                                  _forceMinimumPosToZero =
-                                                      !_forceMinimumPosToZero;
-
-                                              _tfTopLeft.ContextMenu
-                                                        .ForceMinimumPosToZero =
-                                                  _forceMinimumPosToZero;
-
-                                              _tfTopRight.ContextMenu
-                                                         .ForceMinimumPosToZero =
-                                                  _forceMinimumPosToZero;
-
-                                              _tfMiddle.ContextMenu
-                                                       .ForceMinimumPosToZero =
-                                                  _forceMinimumPosToZero;
-
-                                              _tfBottomLeft.ContextMenu
-                                                           .ForceMinimumPosToZero =
-                                                  _forceMinimumPosToZero;
-
-                                              _tfBottomRight
-                                                      .ContextMenu
-                                                      .ForceMinimumPosToZero =
-                                                  _forceMinimumPosToZero;
-                                          }
-                                         )
-                                     {
-                                         CheckType =
-                                             MenuItemCheckStyle
-                                                 .Checked,
-                                         Checked =
-                                             _forceMinimumPosToZero
-                                     },
-                                 _miUseSubMenusSingleFrame =
-                                     new (
-                                          "Use_SubMenusSingleFrame",
-                                          "",
-                                          () => _contextMenu
-                                                        .UseSubMenusSingleFrame =
-                                                    (bool)
-                                                    (_miUseSubMenusSingleFrame
-                                                             .Checked =
-                                                         _useSubMenusSingleFrame =
-                                                             !_useSubMenusSingleFrame)
-                                         )
-                                     {
-                                         CheckType = MenuItemCheckStyle
-                                             .Checked,
-                                         Checked =
-                                             _useSubMenusSingleFrame
-                                     },
-                                 null,
-                                 new (
-                                      "_Quit",
-                                      "",
-                                      () => Application.RequestStop ()
-                                     )
-                             }
-                            ),
             ForceMinimumPosToZero = _forceMinimumPosToZero,
             ForceMinimumPosToZero = _forceMinimumPosToZero,
             UseSubMenusSingleFrame = _useSubMenusSingleFrame
             UseSubMenusSingleFrame = _useSubMenusSingleFrame
         };
         };
 
 
+        MenuBarItem menuItems = new (
+                                     new []
+                                     {
+                                         new (
+                                              "_Configuration",
+                                              "Show configuration",
+                                              () => MessageBox.Query (
+                                                                      50,
+                                                                      5,
+                                                                      "Info",
+                                                                      "This would open settings dialog",
+                                                                      "Ok"
+                                                                     )
+                                             ),
+                                         new MenuBarItem (
+                                                          "More options",
+                                                          new MenuItem []
+                                                          {
+                                                              new (
+                                                                   "_Setup",
+                                                                   "Change settings",
+                                                                   () => MessageBox
+                                                                       .Query (
+                                                                               50,
+                                                                               5,
+                                                                               "Info",
+                                                                               "This would open setup dialog",
+                                                                               "Ok"
+                                                                              ),
+                                                                   shortcutKey: KeyCode.T
+                                                                                | KeyCode
+                                                                                    .CtrlMask
+                                                                  ),
+                                                              new (
+                                                                   "_Maintenance",
+                                                                   "Maintenance mode",
+                                                                   () => MessageBox
+                                                                       .Query (
+                                                                               50,
+                                                                               5,
+                                                                               "Info",
+                                                                               "This would open maintenance dialog",
+                                                                               "Ok"
+                                                                              )
+                                                                  )
+                                                          }
+                                                         ),
+                                         new MenuBarItem (
+                                                          "_Languages",
+                                                          GetSupportedCultures ()
+                                                         ),
+                                         _miForceMinimumPosToZero =
+                                             new (
+                                                  "ForceMinimumPosToZero",
+                                                  "",
+                                                  () =>
+                                                  {
+                                                      _miForceMinimumPosToZero
+                                                              .Checked =
+                                                          _forceMinimumPosToZero =
+                                                              !_forceMinimumPosToZero;
+
+                                                      _tfTopLeft.ContextMenu
+                                                                .ForceMinimumPosToZero =
+                                                          _forceMinimumPosToZero;
+
+                                                      _tfTopRight.ContextMenu
+                                                                 .ForceMinimumPosToZero =
+                                                          _forceMinimumPosToZero;
+
+                                                      _tfMiddle.ContextMenu
+                                                               .ForceMinimumPosToZero =
+                                                          _forceMinimumPosToZero;
+
+                                                      _tfBottomLeft.ContextMenu
+                                                                   .ForceMinimumPosToZero =
+                                                          _forceMinimumPosToZero;
+
+                                                      _tfBottomRight
+                                                              .ContextMenu
+                                                              .ForceMinimumPosToZero =
+                                                          _forceMinimumPosToZero;
+                                                  }
+                                                 )
+                                             {
+                                                 CheckType =
+                                                     MenuItemCheckStyle
+                                                         .Checked,
+                                                 Checked =
+                                                     _forceMinimumPosToZero
+                                             },
+                                         _miUseSubMenusSingleFrame =
+                                             new (
+                                                  "Use_SubMenusSingleFrame",
+                                                  "",
+                                                  () => _contextMenu
+                                                                .UseSubMenusSingleFrame =
+                                                            (bool)
+                                                            (_miUseSubMenusSingleFrame
+                                                                     .Checked =
+                                                                 _useSubMenusSingleFrame =
+                                                                     !_useSubMenusSingleFrame)
+                                                 )
+                                             {
+                                                 CheckType = MenuItemCheckStyle
+                                                     .Checked,
+                                                 Checked =
+                                                     _useSubMenusSingleFrame
+                                             },
+                                         null,
+                                         new (
+                                              "_Quit",
+                                              "",
+                                              () => Application.RequestStop ()
+                                             )
+                                     }
+                                    );
         _tfTopLeft.ContextMenu.ForceMinimumPosToZero = _forceMinimumPosToZero;
         _tfTopLeft.ContextMenu.ForceMinimumPosToZero = _forceMinimumPosToZero;
         _tfTopRight.ContextMenu.ForceMinimumPosToZero = _forceMinimumPosToZero;
         _tfTopRight.ContextMenu.ForceMinimumPosToZero = _forceMinimumPosToZero;
         _tfMiddle.ContextMenu.ForceMinimumPosToZero = _forceMinimumPosToZero;
         _tfMiddle.ContextMenu.ForceMinimumPosToZero = _forceMinimumPosToZero;
         _tfBottomLeft.ContextMenu.ForceMinimumPosToZero = _forceMinimumPosToZero;
         _tfBottomLeft.ContextMenu.ForceMinimumPosToZero = _forceMinimumPosToZero;
         _tfBottomRight.ContextMenu.ForceMinimumPosToZero = _forceMinimumPosToZero;
         _tfBottomRight.ContextMenu.ForceMinimumPosToZero = _forceMinimumPosToZero;
 
 
-        _contextMenu.Show ();
+        _contextMenu.Show (menuItems);
     }
     }
 }
 }

+ 2 - 2
UICatalog/Scenarios/Notepad.cs

@@ -362,9 +362,9 @@ public class Notepad : Scenario
 
 
         var screen = ((View)sender).ViewportToScreen (e.MouseEvent.Position);
         var screen = ((View)sender).ViewportToScreen (e.MouseEvent.Position);
 
 
-        var contextMenu = new ContextMenu { Position = screen, MenuItems = items };
+        var contextMenu = new ContextMenu { Position = screen };
 
 
-        contextMenu.Show ();
+        contextMenu.Show (items);
         e.MouseEvent.Handled = true;
         e.MouseEvent.Handled = true;
     }
     }
 
 

+ 20 - 20
UICatalog/Scenarios/TableEditor.cs

@@ -1266,28 +1266,28 @@ public class TableEditor : Scenario
 
 
         var contextMenu = new ContextMenu
         var contextMenu = new ContextMenu
         {
         {
-            Position = new (e.MouseEvent.Position.X + 1, e.MouseEvent.Position.Y + 1),
-            MenuItems = new (
-                             [
-                                 new (
-                                      $"Hide {TrimArrows (colName)}",
-                                      "",
-                                      () => HideColumn (clickedCol)
-                                     ),
-                                 new (
-                                      $"Sort {StripArrows (sort)}",
-                                      "",
-                                      () => SortColumn (
-                                                        clickedCol,
-                                                        sort,
-                                                        isAsc
-                                                       )
-                                     )
-                             ]
-                            )
+            Position = new (e.MouseEvent.Position.X + 1, e.MouseEvent.Position.Y + 1)
         };
         };
 
 
-        contextMenu.Show ();
+        MenuBarItem menuItems = new (
+                                     [
+                                         new (
+                                              $"Hide {TrimArrows (colName)}",
+                                              "",
+                                              () => HideColumn (clickedCol)
+                                             ),
+                                         new (
+                                              $"Sort {StripArrows (sort)}",
+                                              "",
+                                              () => SortColumn (
+                                                                clickedCol,
+                                                                sort,
+                                                                isAsc
+                                                               )
+                                             )
+                                     ]
+                                    );
+        contextMenu.Show (menuItems);
     }
     }
 
 
     private void SortColumn (int clickedCol)
     private void SortColumn (int clickedCol)

+ 6 - 7
UICatalog/Scenarios/TreeViewFileSystem.cs

@@ -415,21 +415,20 @@ public class TreeViewFileSystem : Scenario
 
 
     private void ShowContextMenu (Point screenPoint, IFileSystemInfo forObject)
     private void ShowContextMenu (Point screenPoint, IFileSystemInfo forObject)
     {
     {
-        var menu = new ContextMenu ();
-        menu.Position = screenPoint;
+        var menu = new ContextMenu { Position = screenPoint };
 
 
-        menu.MenuItems = new MenuBarItem (
-                                          new [] { new MenuItem ("Properties", null, () => ShowPropertiesOf (forObject)) }
-                                         );
+        var menuItems = new MenuBarItem (
+                                         new [] { new MenuItem ("Properties", null, () => ShowPropertiesOf (forObject)) }
+                                        );
 
 
-        Application.Invoke (menu.Show);
+        Application.Invoke (() => menu.Show (menuItems));
     }
     }
 
 
     private void ShowLines ()
     private void ShowLines ()
     {
     {
         _miShowLines.Checked = !_miShowLines.Checked;
         _miShowLines.Checked = !_miShowLines.Checked;
 
 
-        _treeViewFiles.Style.ShowBranchLines = (bool)_miShowLines.Checked;
+        _treeViewFiles.Style.ShowBranchLines = (bool)_miShowLines.Checked!;
         _treeViewFiles.SetNeedsDisplay ();
         _treeViewFiles.SetNeedsDisplay ();
     }
     }
 
 

+ 378 - 132
UnitTests/Views/ContextMenuTests.cs

@@ -10,42 +10,53 @@ public class ContextMenuTests (ITestOutputHelper output)
     public void ContextMenu_Constructors ()
     public void ContextMenu_Constructors ()
     {
     {
         var cm = new ContextMenu ();
         var cm = new ContextMenu ();
+        var top = new Toplevel ();
+        Application.Begin (top);
+
         Assert.Equal (Point.Empty, cm.Position);
         Assert.Equal (Point.Empty, cm.Position);
-        Assert.Empty (cm.MenuItems.Children);
+        Assert.Null (cm.MenuItems);
         Assert.Null (cm.Host);
         Assert.Null (cm.Host);
         cm.Position = new Point (20, 10);
         cm.Position = new Point (20, 10);
 
 
-        cm.MenuItems = new MenuBarItem (
+        var menuItems = new MenuBarItem (
                                         [
                                         [
                                             new MenuItem ("First", "", null)
                                             new MenuItem ("First", "", null)
                                         ]
                                         ]
                                        );
                                        );
+        cm.Show (menuItems);
         Assert.Equal (new Point (20, 10), cm.Position);
         Assert.Equal (new Point (20, 10), cm.Position);
-        Assert.Single (cm.MenuItems.Children);
+        Assert.Single (cm.MenuItems!.Children);
 
 
         cm = new ContextMenu
         cm = new ContextMenu
         {
         {
-            Position = new Point (5, 10),
-            MenuItems = new MenuBarItem (
-                                         new [] { new MenuItem ("One", "", null), new MenuItem ("Two", "", null) }
-                                        )
+            Position = new Point (5, 10)
         };
         };
+
+        menuItems = new MenuBarItem (
+                                     new [] { new MenuItem ("One", "", null), new MenuItem ("Two", "", null) }
+                                    );
+        cm.Show (menuItems);
         Assert.Equal (new Point (5, 10), cm.Position);
         Assert.Equal (new Point (5, 10), cm.Position);
-        Assert.Equal (2, cm.MenuItems.Children.Length);
+        Assert.Equal (2, cm.MenuItems!.Children.Length);
         Assert.Null (cm.Host);
         Assert.Null (cm.Host);
 
 
+        var view = new View { X = 5, Y = 10 };
+        top.Add (view);
         cm = new ContextMenu
         cm = new ContextMenu
         {
         {
-            Host = new View { X = 5, Y = 10 },
-            Position = new Point (5, 10),
-            MenuItems = new MenuBarItem (
-                                         new [] { new MenuItem ("One", "", null), new MenuItem ("Two", "", null) }
-                                        )
+            Host = view,
+            Position = new Point (5, 10)
         };
         };
 
 
+        menuItems = new MenuBarItem (
+                                     new [] { new MenuItem ("One", "", null), new MenuItem ("Two", "", null) }
+                                    );
+        cm.Show (menuItems);
         Assert.Equal (new Point (5, 10), cm.Position);
         Assert.Equal (new Point (5, 10), cm.Position);
         Assert.Equal (2, cm.MenuItems.Children.Length);
         Assert.Equal (2, cm.MenuItems.Children.Length);
         Assert.NotNull (cm.Host);
         Assert.NotNull (cm.Host);
+
+        top.Dispose ();
     }
     }
 
 
     [Fact]
     [Fact]
@@ -54,15 +65,15 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
     {
         var cm = new ContextMenu
         var cm = new ContextMenu
         {
         {
-            Position = new Point (10, 5),
-            MenuItems = new MenuBarItem (
+            Position = new Point (10, 5)
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("Two", "", null)
                                              new MenuItem ("Two", "", null)
                                          ]
                                          ]
-                                        )
-        };
-
+                                        );
         var menu = new MenuBar
         var menu = new MenuBar
         {
         {
             Menus =
             Menus =
@@ -78,7 +89,7 @@ public class ContextMenuTests (ITestOutputHelper output)
 
 
         Assert.Null (Application.MouseGrabView);
         Assert.Null (Application.MouseGrabView);
 
 
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.True (ContextMenu.IsShow);
         Assert.True (ContextMenu.IsShow);
         Assert.Equal (cm.MenuBar, Application.MouseGrabView);
         Assert.Equal (cm.MenuBar, Application.MouseGrabView);
         Assert.False (menu.IsMenuOpen);
         Assert.False (menu.IsMenuOpen);
@@ -87,7 +98,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.Equal (menu, Application.MouseGrabView);
         Assert.Equal (menu, Application.MouseGrabView);
         Assert.True (menu.IsMenuOpen);
         Assert.True (menu.IsMenuOpen);
 
 
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.True (ContextMenu.IsShow);
         Assert.True (ContextMenu.IsShow);
         Assert.Equal (cm.MenuBar, Application.MouseGrabView);
         Assert.Equal (cm.MenuBar, Application.MouseGrabView);
         Assert.False (menu.IsMenuOpen);
         Assert.False (menu.IsMenuOpen);
@@ -98,7 +109,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.True (menu.IsMenuOpen);
         Assert.True (menu.IsMenuOpen);
 #endif
 #endif
 
 
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.True (ContextMenu.IsShow);
         Assert.True (ContextMenu.IsShow);
         Assert.Equal (cm.MenuBar, Application.MouseGrabView);
         Assert.Equal (cm.MenuBar, Application.MouseGrabView);
         Assert.False (menu.IsMenuOpen);
         Assert.False (menu.IsMenuOpen);
@@ -305,21 +316,21 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
     {
         var cm = new ContextMenu
         var cm = new ContextMenu
         {
         {
-            Position = new Point (-1, -2),
-            MenuItems = new MenuBarItem (
+            Position = new Point (-1, -2)
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("Two", "", null)
                                              new MenuItem ("Two", "", null)
                                          ]
                                          ]
-                                        )
-        };
-
+                                        );
         Assert.Equal (new Point (-1, -2), cm.Position);
         Assert.Equal (new Point (-1, -2), cm.Position);
-        
+
         Toplevel top = new ();
         Toplevel top = new ();
         Application.Begin (top);
         Application.Begin (top);
 
 
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.Equal (new Point (-1, -2), cm.Position);
         Assert.Equal (new Point (-1, -2), cm.Position);
         Application.Refresh ();
         Application.Refresh ();
 
 
@@ -334,7 +345,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.Equal (new Rectangle (0, 1, 8, 4), pos);
         Assert.Equal (new Rectangle (0, 1, 8, 4), pos);
 
 
         cm.ForceMinimumPosToZero = false;
         cm.ForceMinimumPosToZero = false;
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.Equal (new Point (-1, -2), cm.Position);
         Assert.Equal (new Point (-1, -2), cm.Position);
         Application.Refresh ();
         Application.Refresh ();
 
 
@@ -355,22 +366,22 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
     {
         var cm = new ContextMenu
         var cm = new ContextMenu
         {
         {
-            Position = new Point (80, 25),
-            MenuItems = new MenuBarItem (
+            Position = new Point (80, 25)
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("Two", "", null)
                                              new MenuItem ("Two", "", null)
                                          ]
                                          ]
-                                        )
-        };
-
+                                        );
         Toplevel top = new ();
         Toplevel top = new ();
         Application.Begin (top);
         Application.Begin (top);
         top.Running = true;
         top.Running = true;
 
 
         Assert.False (ContextMenu.IsShow);
         Assert.False (ContextMenu.IsShow);
 
 
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.True (ContextMenu.IsShow);
         Assert.True (ContextMenu.IsShow);
 
 
         top.RequestStop ();
         top.RequestStop ();
@@ -388,7 +399,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         Application.Begin (top);
         Application.Begin (top);
 
 
         Assert.True (Application.OnKeyDown (ContextMenu.DefaultKey));
         Assert.True (Application.OnKeyDown (ContextMenu.DefaultKey));
-        Assert.True (tf.ContextMenu.MenuBar.IsMenuOpen);
+        Assert.True (tf.ContextMenu.MenuBar!.IsMenuOpen);
         Assert.True (Application.OnKeyDown (ContextMenu.DefaultKey));
         Assert.True (Application.OnKeyDown (ContextMenu.DefaultKey));
         // The last context menu bar opened is always preserved
         // The last context menu bar opened is always preserved
         Assert.NotNull (tf.ContextMenu.MenuBar);
         Assert.NotNull (tf.ContextMenu.MenuBar);
@@ -415,18 +426,18 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
     {
         var cm = new ContextMenu
         var cm = new ContextMenu
         {
         {
-            Position = new Point (10, 5),
-            MenuItems = new MenuBarItem (
+            Position = new Point (10, 5)
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("Two", "", null)
                                              new MenuItem ("Two", "", null)
                                          ]
                                          ]
-                                        )
-        };
-
+                                        );
         Toplevel top = new ();
         Toplevel top = new ();
         Application.Begin (top);
         Application.Begin (top);
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
         Application.Refresh ();
 
 
         var expected = @"
         var expected = @"
@@ -438,15 +449,15 @@ public class ContextMenuTests (ITestOutputHelper output)
 
 
         TestHelpers.AssertDriverContentsAre (expected, output);
         TestHelpers.AssertDriverContentsAre (expected, output);
 
 
-        cm.MenuItems = new MenuBarItem (
-                                        [
-                                            new MenuItem ("First", "", null),
-                                            new MenuItem ("Second", "", null),
-                                            new MenuItem ("Third", "", null)
-                                        ]
-                                       );
+        menuItems = new MenuBarItem (
+                                     [
+                                         new MenuItem ("First", "", null),
+                                         new MenuItem ("Second", "", null),
+                                         new MenuItem ("Third", "", null)
+                                     ]
+                                    );
 
 
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
         Application.Refresh ();
 
 
         expected = @"
         expected = @"
@@ -467,8 +478,10 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
     {
         var cm = new ContextMenu
         var cm = new ContextMenu
         {
         {
-            Position = new Point (-1, -2),
-            MenuItems = new MenuBarItem (
+            Position = new Point (-1, -2)
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("Two", "", null),
                                              new MenuItem ("Two", "", null),
@@ -488,15 +501,13 @@ public class ContextMenuTests (ITestOutputHelper output)
                                              new MenuItem ("Five", "", null),
                                              new MenuItem ("Five", "", null),
                                              new MenuItem ("Six", "", null)
                                              new MenuItem ("Six", "", null)
                                          ]
                                          ]
-                                        )
-        };
-
+                                        );
         Assert.Equal (new Point (-1, -2), cm.Position);
         Assert.Equal (new Point (-1, -2), cm.Position);
 
 
         Toplevel top = new ();
         Toplevel top = new ();
         Application.Begin (top);
         Application.Begin (top);
 
 
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
         Application.Refresh ();
 
 
         Assert.Equal (new Point (-1, -2), cm.Position);
         Assert.Equal (new Point (-1, -2), cm.Position);
@@ -545,7 +556,7 @@ public class ContextMenuTests (ITestOutputHelper output)
 
 
         ((FakeDriver)Application.Driver!).SetBufferSize (40, 20);
         ((FakeDriver)Application.Driver!).SetBufferSize (40, 20);
         cm.Position = new Point (41, -2);
         cm.Position = new Point (41, -2);
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
         Application.Refresh ();
         Assert.Equal (new Point (41, -2), cm.Position);
         Assert.Equal (new Point (41, -2), cm.Position);
 
 
@@ -592,7 +603,7 @@ public class ContextMenuTests (ITestOutputHelper output)
                                                      );
                                                      );
 
 
         cm.Position = new Point (41, 9);
         cm.Position = new Point (41, 9);
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
         Application.Refresh ();
         Assert.Equal (new Point (41, 9), cm.Position);
         Assert.Equal (new Point (41, 9), cm.Position);
 
 
@@ -636,7 +647,7 @@ public class ContextMenuTests (ITestOutputHelper output)
                                                      );
                                                      );
 
 
         cm.Position = new Point (41, 22);
         cm.Position = new Point (41, 22);
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
         Application.Refresh ();
         Assert.Equal (new Point (41, 22), cm.Position);
         Assert.Equal (new Point (41, 22), cm.Position);
 
 
@@ -680,7 +691,7 @@ public class ContextMenuTests (ITestOutputHelper output)
 
 
         ((FakeDriver)Application.Driver!).SetBufferSize (18, 8);
         ((FakeDriver)Application.Driver!).SetBufferSize (18, 8);
         cm.Position = new Point (19, 10);
         cm.Position = new Point (19, 10);
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
         Application.Refresh ();
         Assert.Equal (new Point (19, 10), cm.Position);
         Assert.Equal (new Point (19, 10), cm.Position);
 
 
@@ -773,18 +784,18 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
     {
         var cm = new ContextMenu
         var cm = new ContextMenu
         {
         {
-            Position = new Point (10, 5),
-            MenuItems = new MenuBarItem (
+            Position = new Point (10, 5)
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("Two", "", null)
                                              new MenuItem ("Two", "", null)
                                          ]
                                          ]
-                                        )
-        };
-
+                                        );
         Toplevel top = new ();
         Toplevel top = new ();
         Application.Begin (top);
         Application.Begin (top);
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
         Application.Refresh ();
 
 
         var expected = @"
         var expected = @"
@@ -798,7 +809,7 @@ public class ContextMenuTests (ITestOutputHelper output)
 
 
         cm.Position = new Point (5, 10);
         cm.Position = new Point (5, 10);
 
 
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
         Application.Refresh ();
 
 
         expected = @"
         expected = @"
@@ -816,7 +827,14 @@ public class ContextMenuTests (ITestOutputHelper output)
     [AutoInitShutdown]
     [AutoInitShutdown]
     public void RequestStop_While_ContextMenu_Is_Open_Does_Not_Throws ()
     public void RequestStop_While_ContextMenu_Is_Open_Does_Not_Throws ()
     {
     {
-        ContextMenu cm = Create_ContextMenu_With_Two_MenuItem (10, 5);
+        ContextMenu cm = new ContextMenu
+        {
+            Position = new Point (10, 5)
+        };
+
+        var menuItems = new MenuBarItem (
+                                         new MenuItem [] { new ("One", "", null), new ("Two", "", null) }
+                                        );
         Toplevel top = new ();
         Toplevel top = new ();
         var isMenuAllClosed = false;
         var isMenuAllClosed = false;
         MenuBarItem mi = null;
         MenuBarItem mi = null;
@@ -828,7 +846,7 @@ public class ContextMenuTests (ITestOutputHelper output)
 
 
                                      if (iterations == 0)
                                      if (iterations == 0)
                                      {
                                      {
-                                         cm.Show ();
+                                         cm.Show (menuItems);
                                          Assert.True (ContextMenu.IsShow);
                                          Assert.True (ContextMenu.IsShow);
                                          mi = cm.MenuBar.Menus [0];
                                          mi = cm.MenuBar.Menus [0];
 
 
@@ -853,7 +871,7 @@ public class ContextMenuTests (ITestOutputHelper output)
                                      else if (iterations == 3)
                                      else if (iterations == 3)
                                      {
                                      {
                                          isMenuAllClosed = false;
                                          isMenuAllClosed = false;
-                                         cm.Show ();
+                                         cm.Show (menuItems);
                                          Assert.True (ContextMenu.IsShow);
                                          Assert.True (ContextMenu.IsShow);
                                          cm.MenuBar.MenuAllClosed += (_, _) => isMenuAllClosed = true;
                                          cm.MenuBar.MenuAllClosed += (_, _) => isMenuAllClosed = true;
                                      }
                                      }
@@ -896,20 +914,20 @@ public class ContextMenuTests (ITestOutputHelper output)
 
 
         var cm = new ContextMenu
         var cm = new ContextMenu
         {
         {
-            Position = Point.Empty,
-            MenuItems = new MenuBarItem (
+            Position = Point.Empty
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("Two", "", null)
                                              new MenuItem ("Two", "", null)
                                          ]
                                          ]
-                                        )
-        };
-
+                                        );
         Assert.Equal (Point.Empty, cm.Position);
         Assert.Equal (Point.Empty, cm.Position);
 
 
         Toplevel top = new ();
         Toplevel top = new ();
         Application.Begin (top);
         Application.Begin (top);
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.Equal (Point.Empty, cm.Position);
         Assert.Equal (Point.Empty, cm.Position);
         Application.Refresh ();
         Application.Refresh ();
 
 
@@ -934,20 +952,20 @@ public class ContextMenuTests (ITestOutputHelper output)
 
 
         var cm = new ContextMenu
         var cm = new ContextMenu
         {
         {
-            Position = Point.Empty,
-            MenuItems = new MenuBarItem (
+            Position = Point.Empty
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("Two", "", null)
                                              new MenuItem ("Two", "", null)
                                          ]
                                          ]
-                                        )
-        };
-
+                                        );
         Assert.Equal (Point.Empty, cm.Position);
         Assert.Equal (Point.Empty, cm.Position);
 
 
         Toplevel top = new ();
         Toplevel top = new ();
         Application.Begin (top);
         Application.Begin (top);
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.Equal (Point.Empty, cm.Position);
         Assert.Equal (Point.Empty, cm.Position);
         Application.Refresh ();
         Application.Refresh ();
 
 
@@ -981,22 +999,22 @@ public class ContextMenuTests (ITestOutputHelper output)
         var cm = new ContextMenu
         var cm = new ContextMenu
         {
         {
             Host = view,
             Host = view,
-            Position = new Point (10, 5),
-            MenuItems = new MenuBarItem (
+            Position = new Point (10, 5)
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("Two", "", null)
                                              new MenuItem ("Two", "", null)
                                          ]
                                          ]
-                                        )
-        };
-
+                                        );
         var top = new Toplevel ();
         var top = new Toplevel ();
         top.Add (view);
         top.Add (view);
         Application.Begin (top);
         Application.Begin (top);
 
 
         Assert.Equal (new Point (10, 5), cm.Position);
         Assert.Equal (new Point (10, 5), cm.Position);
 
 
-        cm.Show ();
+        cm.Show (menuItems);
         top.Draw ();
         top.Draw ();
         Assert.Equal (new Point (10, 5), cm.Position);
         Assert.Equal (new Point (10, 5), cm.Position);
 
 
@@ -1017,7 +1035,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         cm.Host.Y = 10;
         cm.Host.Y = 10;
         cm.Host.Height = 3;
         cm.Host.Height = 3;
 
 
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Top.Draw ();
         Application.Top.Draw ();
         Assert.Equal (new Point (5, 12), cm.Position);
         Assert.Equal (new Point (5, 12), cm.Position);
 
 
@@ -1045,20 +1063,20 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
     {
         var cm = new ContextMenu
         var cm = new ContextMenu
         {
         {
-            Position = new Point (80, 25),
-            MenuItems = new MenuBarItem (
+            Position = new Point (80, 25)
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("Two", "", null)
                                              new MenuItem ("Two", "", null)
                                          ]
                                          ]
-                                        )
-        };
-
+                                        );
         Assert.Equal (new Point (80, 25), cm.Position);
         Assert.Equal (new Point (80, 25), cm.Position);
 
 
         Toplevel top = new ();
         Toplevel top = new ();
         Application.Begin (top);
         Application.Begin (top);
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.Equal (new Point (80, 25), cm.Position);
         Assert.Equal (new Point (80, 25), cm.Position);
         Application.Refresh ();
         Application.Refresh ();
 
 
@@ -1092,15 +1110,15 @@ public class ContextMenuTests (ITestOutputHelper output)
 
 
         var cm = new ContextMenu
         var cm = new ContextMenu
         {
         {
-            Host = view,
-            MenuItems = new MenuBarItem (
+            Host = view
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("Two", "", null)
                                              new MenuItem ("Two", "", null)
                                          ]
                                          ]
-                                        )
-        };
-
+                                        );
         var top = new Toplevel ();
         var top = new Toplevel ();
         top.Add (view);
         top.Add (view);
         Application.Begin (top);
         Application.Begin (top);
@@ -1108,7 +1126,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.Equal (new Rectangle (70, 24, 10, 1), view.Frame);
         Assert.Equal (new Rectangle (70, 24, 10, 1), view.Frame);
         Assert.Equal (Point.Empty, cm.Position);
         Assert.Equal (Point.Empty, cm.Position);
 
 
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.Equal (new Point (70, 24), cm.Position);
         Assert.Equal (new Point (70, 24), cm.Position);
         top.Draw ();
         top.Draw ();
 
 
@@ -1132,11 +1150,18 @@ public class ContextMenuTests (ITestOutputHelper output)
     [AutoInitShutdown]
     [AutoInitShutdown]
     public void Show_Hide_IsShow ()
     public void Show_Hide_IsShow ()
     {
     {
-        ContextMenu cm = Create_ContextMenu_With_Two_MenuItem (10, 5);
+        ContextMenu cm = new ContextMenu
+        {
+            Position = new Point (10, 5)
+        };
+
+        var menuItems = new MenuBarItem (
+                                         new MenuItem [] { new ("One", "", null), new ("Two", "", null) }
+                                        );
 
 
         Toplevel top = new ();
         Toplevel top = new ();
         Application.Begin (top);
         Application.Begin (top);
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.True (ContextMenu.IsShow);
         Assert.True (ContextMenu.IsShow);
         Application.Refresh ();
         Application.Refresh ();
 
 
@@ -1167,7 +1192,10 @@ public class ContextMenuTests (ITestOutputHelper output)
         var cm = new ContextMenu
         var cm = new ContextMenu
         {
         {
             Position = new Point (5, 10),
             Position = new Point (5, 10),
-            MenuItems = new MenuBarItem (
+            UseSubMenusSingleFrame = true
+        };
+
+        var menuItems = new MenuBarItem (
                                          "Numbers",
                                          "Numbers",
                                          [
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("One", "", null),
@@ -1184,19 +1212,11 @@ public class ContextMenuTests (ITestOutputHelper output)
                                                              ),
                                                              ),
                                              new MenuItem ("Three", "", null)
                                              new MenuItem ("Three", "", null)
                                          ]
                                          ]
-                                        ),
-            UseSubMenusSingleFrame = true
-        };
+                                        );
         Toplevel top = new ();
         Toplevel top = new ();
         RunState rs = Application.Begin (top);
         RunState rs = Application.Begin (top);
-        top.SetFocus ();
-        Assert.NotNull (Application.Current);
-
-        cm.Show ();
-        Assert.True(ContextMenu.IsShow);
-        Assert.True (Application.Top.Subviews [0].HasFocus);
-        Assert.Equal(Application.Top.Subviews [0], Application.Navigation.GetFocused());
-        Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
+        cm.Show (menuItems);
+        Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top!.Subviews [0].Frame);
         Application.Refresh ();
         Application.Refresh ();
 
 
         TestHelpers.AssertDriverContentsWithFrameAre (
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -1254,8 +1274,10 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
     {
         var cm = new ContextMenu
         var cm = new ContextMenu
         {
         {
-            Position = new Point (5, 10),
-            MenuItems = new MenuBarItem (
+            Position = new Point (5, 10)
+        };
+
+        var menuItems = new MenuBarItem (
                                          "Numbers",
                                          "Numbers",
                                          [
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("One", "", null),
@@ -1270,7 +1292,8 @@ public class ContextMenuTests (ITestOutputHelper output)
                                                                   new MenuItem ("Two-Menu 2", "", null)
                                                                   new MenuItem ("Two-Menu 2", "", null)
                                                               ]
                                                               ]
                                                              ),
                                                              ),
-                                             new MenuBarItem ("Three",
+                                             new MenuBarItem (
+                                                              "Three",
                                                               [
                                                               [
                                                                   new MenuItem (
                                                                   new MenuItem (
                                                                                 "Three-Menu 1",
                                                                                 "Three-Menu 1",
@@ -1281,11 +1304,10 @@ public class ContextMenuTests (ITestOutputHelper output)
                                                               ]
                                                               ]
                                                              )
                                                              )
                                          ]
                                          ]
-                                        )
-        };
+                                        );
         Toplevel top = new ();
         Toplevel top = new ();
         RunState rs = Application.Begin (top);
         RunState rs = Application.Begin (top);
-        cm.Show ();
+        cm.Show (menuItems);
 
 
         Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
         Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
         Application.Refresh ();
         Application.Refresh ();
@@ -1356,17 +1378,6 @@ public class ContextMenuTests (ITestOutputHelper output)
         top.Dispose ();
         top.Dispose ();
     }
     }
 
 
-    private ContextMenu Create_ContextMenu_With_Two_MenuItem (int x, int y)
-    {
-        return new ContextMenu
-        {
-            Position = new Point (x, y),
-            MenuItems = new MenuBarItem (
-                                         new MenuItem [] { new ("One", "", null), new ("Two", "", null) }
-                                        )
-        };
-    }
-
     [Fact]
     [Fact]
     [AutoInitShutdown]
     [AutoInitShutdown]
     public void Handling_TextField_With_Opened_ContextMenu_By_Mouse_HasFocus ()
     public void Handling_TextField_With_Opened_ContextMenu_By_Mouse_HasFocus ()
@@ -1417,4 +1428,239 @@ public class ContextMenuTests (ITestOutputHelper output)
         Application.End (rs);
         Application.End (rs);
         win.Dispose ();
         win.Dispose ();
     }
     }
+
+    [Fact]
+    [AutoInitShutdown]
+    public void Empty_Menus_Items_Children_Does_Not_Open_The_Menu ()
+    {
+        var cm = new ContextMenu ();
+        Assert.Null (cm.MenuItems);
+
+        var top = new Toplevel ();
+        Application.Begin (top);
+
+        cm.Show (cm.MenuItems);
+        Assert.Null (cm.MenuBar);
+
+        top.Dispose ();
+    }
+
+    [Fact]
+    [AutoInitShutdown]
+    public void KeyBinding_Removed_On_Close_ContextMenu ()
+    {
+        var newFile = false;
+        var renameFile = false;
+        var deleteFile = false;
+
+        var cm = new ContextMenu ();
+
+        var menuItems = new MenuBarItem (
+                                         [
+                                             new MenuItem ("New File", string.Empty, New, null, null, Key.N.WithCtrl),
+                                             new MenuItem ("Rename File", string.Empty, Rename, null, null, Key.R.WithCtrl),
+                                             new MenuItem ("Delete File", string.Empty, Delete, null, null, Key.D.WithCtrl)
+                                         ]
+                                        );
+        var top = new Toplevel ();
+        Application.Begin (top);
+
+        Assert.Null (cm.MenuBar);
+        Assert.False (Application.OnKeyDown (Key.N.WithCtrl));
+        Assert.False (Application.OnKeyDown (Key.R.WithCtrl));
+        Assert.False (Application.OnKeyDown (Key.D.WithCtrl));
+        Assert.False (newFile);
+        Assert.False (renameFile);
+        Assert.False (deleteFile);
+
+        cm.Show (menuItems);
+        Assert.True (cm.MenuBar!.KeyBindings.Bindings.ContainsKey (Key.N.WithCtrl));
+        Assert.True (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithCtrl));
+        Assert.True (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.D.WithCtrl));
+
+        Assert.True (Application.OnKeyDown (Key.N.WithCtrl));
+        Application.MainLoop!.RunIteration ();
+        Assert.True (newFile);
+        Assert.False (cm.MenuBar!.IsMenuOpen);
+        cm.Show (menuItems);
+        Assert.True (Application.OnKeyDown (Key.R.WithCtrl));
+        Application.MainLoop!.RunIteration ();
+        Assert.True (renameFile);
+        Assert.False (cm.MenuBar.IsMenuOpen);
+        cm.Show (menuItems);
+        Assert.True (Application.OnKeyDown (Key.D.WithCtrl));
+        Application.MainLoop!.RunIteration ();
+        Assert.True (deleteFile);
+        Assert.False (cm.MenuBar.IsMenuOpen);
+
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithCtrl));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithCtrl));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.D.WithCtrl));
+
+        newFile = false;
+        renameFile = false;
+        deleteFile = false;
+        Assert.False (Application.OnKeyDown (Key.N.WithCtrl));
+        Assert.False (Application.OnKeyDown (Key.R.WithCtrl));
+        Assert.False (Application.OnKeyDown (Key.D.WithCtrl));
+        Assert.False (newFile);
+        Assert.False (renameFile);
+        Assert.False (deleteFile);
+
+        top.Dispose ();
+
+        void New () { newFile = true; }
+
+        void Rename () { renameFile = true; }
+
+        void Delete () { deleteFile = true; }
+    }
+
+    [Fact]
+    [AutoInitShutdown]
+    public void KeyBindings_With_ContextMenu_And_MenuBar ()
+    {
+        var newFile = false;
+        var renameFile = false;
+
+        var menuBar = new MenuBar
+        {
+            Menus =
+            [
+                new (
+                     "File",
+                     new MenuItem []
+                     {
+                         new ("New", string.Empty, New, null, null, Key.N.WithCtrl)
+                     })
+            ]
+        };
+        var cm = new ContextMenu ();
+
+        var menuItems = new MenuBarItem (
+                                         [
+                                             new MenuItem ("Rename File", string.Empty, Rename, null, null, Key.R.WithCtrl),
+                                         ]
+                                        );
+        var top = new Toplevel ();
+        top.Add (menuBar);
+        Application.Begin (top);
+
+        Assert.True (menuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithCtrl));
+        Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithCtrl));
+        Assert.Null (cm.MenuBar);
+
+        Assert.True (Application.OnKeyDown (Key.N.WithCtrl));
+        Assert.False (Application.OnKeyDown (Key.R.WithCtrl));
+        Application.MainLoop!.RunIteration ();
+        Assert.True (newFile);
+        Assert.False (renameFile);
+
+        newFile = false;
+
+        cm.Show (menuItems);
+        Assert.True (menuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithCtrl));
+        Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithCtrl));
+        Assert.False (cm.MenuBar!.KeyBindings.Bindings.ContainsKey (Key.N.WithCtrl));
+        Assert.True (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithCtrl));
+
+        Assert.True (cm.MenuBar.IsMenuOpen);
+        Assert.True (Application.OnKeyDown (Key.N.WithCtrl));
+        Application.MainLoop!.RunIteration ();
+        Assert.True (newFile);
+        Assert.False (cm.MenuBar!.IsMenuOpen);
+        cm.Show (menuItems);
+        Assert.True (Application.OnKeyDown (Key.R.WithCtrl));
+        Application.MainLoop!.RunIteration ();
+        Assert.True (renameFile);
+        Assert.False (cm.MenuBar.IsMenuOpen);
+
+        Assert.True (menuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithCtrl));
+        Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithCtrl));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithCtrl));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithCtrl));
+
+        newFile = false;
+        renameFile = false;
+        Assert.True (Application.OnKeyDown (Key.N.WithCtrl));
+        Assert.False (Application.OnKeyDown (Key.R.WithCtrl));
+        Application.MainLoop!.RunIteration ();
+        Assert.True (newFile);
+        Assert.False (renameFile);
+
+        top.Dispose ();
+
+        void New () { newFile = true; }
+
+        void Rename () { renameFile = true; }
+    }
+
+    [Fact]
+    [AutoInitShutdown]
+    public void KeyBindings_With_Same_Shortcut_ContextMenu_And_MenuBar ()
+    {
+        var newMenuBar = false;
+        var newContextMenu = false;
+
+        var menuBar = new MenuBar
+        {
+            Menus =
+            [
+                new (
+                     "File",
+                     new MenuItem []
+                     {
+                         new ("New", string.Empty, NewMenuBar, null, null, Key.N.WithCtrl)
+                     })
+            ]
+        };
+        var cm = new ContextMenu ();
+
+        var menuItems = new MenuBarItem (
+                                         [
+                                             new MenuItem ("New File", string.Empty, NewContextMenu, null, null, Key.N.WithCtrl),
+                                         ]
+                                        );
+        var top = new Toplevel ();
+        top.Add (menuBar);
+        Application.Begin (top);
+
+        Assert.True (menuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithCtrl));
+        Assert.Null (cm.MenuBar);
+
+        Assert.True (Application.OnKeyDown (Key.N.WithCtrl));
+        Application.MainLoop!.RunIteration ();
+        Assert.True (newMenuBar);
+        Assert.False (newContextMenu);
+
+        newMenuBar = false;
+
+        cm.Show (menuItems);
+        Assert.True (menuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithCtrl));
+        Assert.True (cm.MenuBar!.KeyBindings.Bindings.ContainsKey (Key.N.WithCtrl));
+
+        Assert.True (cm.MenuBar.IsMenuOpen);
+        Assert.True (Application.OnKeyDown (Key.N.WithCtrl));
+        Application.MainLoop!.RunIteration ();
+        Assert.False (newMenuBar);
+        // The most focused shortcut is executed
+        Assert.True (newContextMenu);
+        Assert.False (cm.MenuBar!.IsMenuOpen);
+
+        Assert.True (menuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithCtrl));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithCtrl));
+
+        newMenuBar = false;
+        newContextMenu = false;
+        Assert.True (Application.OnKeyDown (Key.N.WithCtrl));
+        Application.MainLoop!.RunIteration ();
+        Assert.True (newMenuBar);
+        Assert.False (newContextMenu);
+
+        top.Dispose ();
+
+        void NewMenuBar () { newMenuBar = true; }
+
+        void NewContextMenu () { newContextMenu = true; }
+    }
 }
 }