Browse Source

Merge branch 'v2_develop' into v2_2489_scroll-scrollbar-new

BDisp 11 months ago
parent
commit
a83b8f195b

+ 1 - 1
Terminal.Gui/Views/ColorPicker.cs

@@ -361,7 +361,7 @@ public class ColorPicker : View
         }
     }
 
-
+    /// <inheritdoc />
     protected override void Dispose (bool disposing)
     {
         DisposeOldViews ();

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

@@ -1207,19 +1207,19 @@ public class FileDialog : Dialog
 
         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.fdCtxRename, string.Empty, Rename),
                                              new MenuItem (Strings.fdCtxDelete, string.Empty, Delete)
                                          ]
-                                        )
-        };
-
+                                        );
         _tableView.SetSelection (clickedCell.Value.X, clickedCell.Value.Y, false);
 
-        contextMenu.Show ();
+        contextMenu.Show (menuItems);
     }
 
     private void ShowHeaderContextMenu (int clickedCol, MouseEventEventArgs e)
@@ -1228,8 +1228,10 @@ public class FileDialog : Dialog
 
         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 (
                                                            string.Format (
@@ -1244,10 +1246,8 @@ public class FileDialog : Dialog
                                                            string.Empty,
                                                            () => SortColumn (clickedCol, isAsc))
                                          ]
-                                        )
-        };
-
-        contextMenu.Show ();
+                                        );
+        contextMenu.Show (menuItems);
     }
 
     private void SortColumn (int clickedCol)

+ 57 - 25
Terminal.Gui/Views/Menu/ContextMenu.cs

@@ -1,4 +1,6 @@
-namespace Terminal.Gui;
+#nullable enable
+
+namespace Terminal.Gui;
 
 /// <summary>
 ///     ContextMenu provides a pop-up menu that can be positioned anywhere within a <see cref="View"/>. ContextMenu is
@@ -16,15 +18,15 @@
 ///     </para>
 ///     <para>
 ///         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>ContextMenus are located using screen coordinates and appear above all other Views.</para>
 /// </summary>
 public sealed class ContextMenu : IDisposable
 {
-    private static MenuBar _menuBar;
+    private static MenuBar? _menuBar;
 
-    private Toplevel _container;
+    private Toplevel? _container;
     private Key _key = DefaultKey;
     private MouseFlags _mouseFlags = MouseFlags.Button3Clicked;
 
@@ -33,15 +35,9 @@ public sealed class ContextMenu : IDisposable
     {
         if (IsShow)
         {
-            if (_menuBar.SuperView is { })
-            {
-                Hide ();
-            }
-
+            Hide ();
             IsShow = false;
         }
-
-        MenuItems = new MenuBarItem ();
     }
 
     /// <summary>The default shortcut key for activating the context menu.</summary>
@@ -56,7 +52,7 @@ public sealed class ContextMenu : IDisposable
     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>
-    public View Host { get; set; }
+    public View? Host { get; set; }
 
     /// <summary>Gets whether the ContextMenu is showing or not.</summary>
     public static bool IsShow { get; private set; }
@@ -74,10 +70,10 @@ public sealed class ContextMenu : IDisposable
     }
 
     /// <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>
-    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>
     public MouseFlags MouseFlags
@@ -105,11 +101,10 @@ public sealed class ContextMenu : IDisposable
     /// <summary>Disposes the context menu object.</summary>
     public void Dispose ()
     {
-        if (_menuBar is null)
+        if (_menuBar is { })
         {
-            return;
+            _menuBar.MenuAllClosed -= MenuBar_MenuAllClosed;
         }
-        _menuBar.MenuAllClosed -= MenuBar_MenuAllClosed;
         Application.UngrabMouse ();
         _menuBar?.Dispose ();
         _menuBar = null;
@@ -126,18 +121,49 @@ public sealed class ContextMenu : IDisposable
     /// <summary>Hides (closes) the ContextMenu.</summary>
     public void Hide ()
     {
+        RemoveKeyBindings (MenuItems);
         _menuBar?.CleanUp ();
         IsShow = false;
     }
 
+    private void RemoveKeyBindings (MenuBarItem? menuBarItem)
+    {
+        if (menuBarItem is null)
+        {
+            return;
+        }
+
+        foreach (MenuItem? 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>
-    public event EventHandler<KeyChangedEventArgs> KeyChanged;
+    public event EventHandler<KeyChangedEventArgs>? KeyChanged;
 
     /// <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>
-    public void Show ()
+    public void Show (MenuBarItem? menuItems)
     {
         if (_menuBar is { })
         {
@@ -145,6 +171,12 @@ public sealed class ContextMenu : IDisposable
             Dispose ();
         }
 
+        if (menuItems is null || menuItems.Children!.Length == 0)
+        {
+            return;
+        }
+
+        MenuItems = menuItems;
         _container = Application.Current;
         _container!.Closing += Container_Closing;
         _container.Deactivate += Container_Deactivate;
@@ -155,7 +187,7 @@ public sealed class ContextMenu : IDisposable
         if (Host is { })
         {
             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)
             {
@@ -224,9 +256,9 @@ public sealed class ContextMenu : IDisposable
         _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 (); }
 }

+ 114 - 87
Terminal.Gui/Views/Menu/Menu.cs

@@ -1,3 +1,5 @@
+#nullable enable
+
 namespace Terminal.Gui;
 
 /// <summary>
@@ -6,12 +8,12 @@ namespace Terminal.Gui;
 /// </summary>
 internal sealed class Menu : View
 {
-    private readonly MenuBarItem _barItems;
+    private readonly MenuBarItem? _barItems;
     private readonly MenuBar _host;
     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)
         {
@@ -47,9 +49,9 @@ internal sealed class Menu : View
         }
     }
 
-    internal required MenuBarItem BarItems
+    internal required MenuBarItem? BarItems
     {
-        get => _barItems;
+        get => _barItems!;
         init
         {
             ArgumentNullException.ThrowIfNull (value);
@@ -60,13 +62,32 @@ internal sealed class Menu : View
         }
     }
 
-    internal Menu Parent { get; init; }
+    internal Menu? Parent { get; init; }
 
     public override void BeginInit ()
     {
         base.BeginInit ();
 
-        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 })
         {
@@ -78,9 +99,9 @@ internal sealed class Menu : View
         {
             _currentChild = -1;
 
-            for (var i = 0; i < _barItems!.Children?.Length; i++)
+            for (var i = 0; i < _barItems.Children?.Length; i++)
             {
-                if (_barItems.Children [i]?.IsEnabled () == true)
+                if (_barItems.Children [i]!.IsEnabled ())
                 {
                     _currentChild = i;
 
@@ -101,19 +122,17 @@ internal sealed class Menu : View
                     {
                         _host.NextMenu (
                                         !_barItems.IsTopLevel
-                                        || (_barItems.Children != null
-                                            && _barItems!.Children.Length > 0
+                                        || (_barItems.Children is { Length: > 0 }
                                             && _currentChild > -1
                                             && _currentChild < _barItems.Children.Length
-                                            && _barItems.Children [_currentChild].IsFromSubMenu),
-                                        _barItems!.Children != null
-                                        && _barItems.Children.Length > 0
+                                            && _barItems.Children [_currentChild]!.IsFromSubMenu),
+                                        _barItems.Children is { Length: > 0 }
                                         && _currentChild > -1
                                         && _host.UseSubMenusSingleFrame
                                         && _barItems.SubMenu (
-                                                              _barItems.Children [_currentChild]
+                                                              _barItems.Children [_currentChild]!
                                                              )
-                                        != null
+                                        != null!
                                        );
 
                         return true;
@@ -141,7 +160,7 @@ internal sealed class Menu : View
                     Command.Left,
                     () =>
                     {
-                        _host.PreviousMenu (true);
+                        _host!.PreviousMenu (true);
 
                         return true;
                     }
@@ -166,9 +185,9 @@ internal sealed class Menu : View
                         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
         KeyBindings.Add (Key.CursorUp, Command.LineUp);
@@ -179,47 +198,51 @@ internal sealed class Menu : View
         KeyBindings.Add (Key.Enter, Command.Accept);
     }
 
-    private void AddKeyBindingsHotKey (MenuBarItem menuBarItem)
+    private void AddKeyBindingsHotKey (MenuBarItem? menuBarItem)
     {
         if (menuBarItem is null || menuBarItem.Children is null)
         {
             return;
         }
 
-        foreach (MenuItem menuItem in menuBarItem.Children.Where (m => m is { }))
+        IEnumerable<MenuItem> menuItems = menuBarItem.Children.Where (m => m is { })!;
+
+        foreach (MenuItem menuItem in menuItems)
         {
             KeyBinding keyBinding = new ([Command.ToggleExpandCollapse], KeyBindingScope.HotKey, menuItem);
 
             if (menuItem.HotKey != Key.Empty)
             {
-                KeyBindings.Remove (menuItem.HotKey);
-                KeyBindings.Add (menuItem.HotKey, keyBinding);
-                KeyBindings.Remove (menuItem.HotKey.WithAlt);
+                KeyBindings.Remove (menuItem.HotKey!);
+                KeyBindings.Add (menuItem.HotKey!, keyBinding);
+                KeyBindings.Remove (menuItem.HotKey!.WithAlt);
                 KeyBindings.Add (menuItem.HotKey.WithAlt, keyBinding);
             }
         }
     }
 
-    private void RemoveKeyBindingsHotKey (MenuBarItem menuBarItem)
+    private void RemoveKeyBindingsHotKey (MenuBarItem? menuBarItem)
     {
         if (menuBarItem is null || menuBarItem.Children is null)
         {
             return;
         }
 
-        foreach (MenuItem menuItem in menuBarItem.Children.Where (m => m is { }))
+        IEnumerable<MenuItem> menuItems = menuBarItem.Children.Where (m => m is { })!;
+
+        foreach (MenuItem menuItem in menuItems)
         {
             if (menuItem.HotKey != Key.Empty)
             {
-                KeyBindings.Remove (menuItem.HotKey);
-                KeyBindings.Remove (menuItem.HotKey.WithAlt);
+                KeyBindings.Remove (menuItem.HotKey!);
+                KeyBindings.Remove (menuItem.HotKey!.WithAlt);
             }
         }
     }
 
     /// <summary>Called when a key bound to Command.ToggleExpandCollapse is pressed. This means a hot key was pressed.</summary>
     /// <returns></returns>
-    private bool ExpandCollapse (MenuItem menuItem)
+    private bool ExpandCollapse (MenuItem? menuItem)
     {
         if (!IsInitialized || !Visible)
         {
@@ -227,7 +250,7 @@ internal sealed class Menu : View
         }
 
 
-        for (var c = 0; c < _barItems.Children.Length; c++)
+        for (var c = 0; c < _barItems!.Children!.Length; c++)
         {
             if (_barItems.Children [c] == menuItem)
             {
@@ -243,13 +266,14 @@ internal sealed class Menu : View
 
             if (m?.Children?.Length > 0)
             {
-                MenuItem item = _barItems.Children [_currentChild];
+                MenuItem? item = _barItems.Children [_currentChild];
 
                 if (item is null)
                 {
                     return true;
                 }
 
+                // ReSharper disable once ConditionIsAlwaysTrueOrFalse
                 bool disabled = item is null || !item.IsEnabled ();
 
                 if (!disabled && (_host.UseSubMenusSingleFrame || !CheckSubMenu ()))
@@ -297,7 +321,7 @@ internal sealed class Menu : View
         return _host.OnInvokingKeyBindings (keyEvent, scope);
     }
 
-    private void Current_TerminalResized (object sender, SizeChangedEventArgs e)
+    private void Current_TerminalResized (object? sender, SizeChangedEventArgs e)
     {
         if (_host.IsMenuOpen)
         {
@@ -320,7 +344,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))
         {
@@ -350,7 +374,7 @@ internal sealed class Menu : View
         }
     }
 
-    internal Attribute DetermineColorSchemeFor (MenuItem item, int index)
+    internal Attribute DetermineColorSchemeFor (MenuItem? item, int index)
     {
         if (item is null)
         {
@@ -367,7 +391,7 @@ internal sealed class Menu : View
 
     public override void OnDrawContent (Rectangle viewport)
     {
-        if (_barItems.Children is null)
+        if (_barItems!.Children is null)
         {
             return;
         }
@@ -379,7 +403,7 @@ internal sealed class Menu : View
         OnDrawAdornments ();
         OnRenderLineCanvas ();
 
-        for (int i = Viewport.Y; i < _barItems.Children.Length; i++)
+        for (int i = Viewport.Y; i < _barItems!.Children.Length; i++)
         {
             if (i < 0)
             {
@@ -391,9 +415,10 @@ internal sealed class Menu : View
                 break;
             }
 
-            MenuItem item = _barItems.Children [i];
+            MenuItem? item = _barItems.Children [i];
 
             Driver.SetAttribute (
+                                 // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
                                  item is null ? GetNormalColor () :
                                  i == _currentChild ? GetFocusColor () : GetNormalColor ()
                                 );
@@ -428,13 +453,13 @@ internal sealed class Menu : View
                 {
                     Driver.AddRune (Glyphs.HLine);
                 }
-                else if (i == 0 && p == 0 && _host.UseSubMenusSingleFrame && item.Parent.Parent is { })
+                else if (i == 0 && p == 0 && _host.UseSubMenusSingleFrame && item.Parent!.Parent is { })
                 {
                     Driver.AddRune (Glyphs.LeftArrow);
                 }
 
                 // This `- 3` is left border + right border + one row in from right
-                else if (p == Frame.Width - 3 && _barItems.SubMenu (_barItems.Children [i]) is { })
+                else if (p == Frame.Width - 3 && _barItems?.SubMenu (_barItems.Children [i]!) is { })
                 {
                     Driver.AddRune (Glyphs.RightArrow);
                 }
@@ -456,7 +481,7 @@ internal sealed class Menu : View
                 continue;
             }
 
-            string textToDraw = null;
+            string? textToDraw;
             Rune nullCheckedChar = Glyphs.CheckStateNone;
             Rune checkChar = Glyphs.Selected;
             Rune uncheckedChar = Glyphs.UnSelected;
@@ -468,7 +493,7 @@ internal sealed class Menu : View
             }
 
             // 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}";
             }
@@ -495,7 +520,7 @@ internal sealed class Menu : View
                 {
                     DrawHotString (textToDraw, ColorScheme.Disabled, ColorScheme.Disabled);
                 }
-                else if (i == 0 && _host.UseSubMenusSingleFrame && item.Parent.Parent is { })
+                else if (i == 0 && _host.UseSubMenusSingleFrame && item.Parent!.Parent is { })
                 {
                     var tf = new TextFormatter
                     {
@@ -548,7 +573,7 @@ internal sealed class Menu : View
         // PositionCursor ();
     }
 
-    private void Current_DrawContentComplete (object sender, DrawEventArgs e)
+    private void Current_DrawContentComplete (object? sender, DrawEventArgs e)
     {
         if (Visible)
         {
@@ -558,11 +583,11 @@ internal sealed class Menu : View
 
     public override Point? PositionCursor ()
     {
-        if (_host?.IsMenuOpen != false)
+        if (_host.IsMenuOpen)
         {
-            if (_barItems.IsTopLevel)
+            if (_barItems!.IsTopLevel)
             {
-                return _host?.PositionCursor ();
+                return _host.PositionCursor ();
             }
 
             Move (2, 1 + _currentChild);
@@ -570,12 +595,12 @@ internal sealed class Menu : View
             return null; // Don't show the cursor
         }
 
-        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;
         }
@@ -587,17 +612,17 @@ internal sealed class Menu : View
         _host.Run (action);
     }
 
-    protected override void OnHasFocusChanged (bool newHasFocus, View previousFocusedView, View view)
+    protected override void OnHasFocusChanged (bool newHasFocus, View? previousFocusedView, View? view)
     {
         if (!newHasFocus)
         {
-            _host.LostFocus (previousFocusedView);
+            _host.LostFocus (previousFocusedView!);
         }
     }
 
     private void RunSelected ()
     {
-        if (_barItems.IsTopLevel)
+        if (_barItems!.IsTopLevel)
         {
             Run (_barItems.Action);
         }
@@ -605,15 +630,15 @@ internal sealed class Menu : View
         {
             switch (_currentChild)
             {
-                case > -1 when _barItems.Children [_currentChild].Action != null:
-                    Run (_barItems.Children [_currentChild].Action);
+                case > -1 when _barItems.Children! [_currentChild]!.Action != null!:
+                    Run (_barItems.Children [_currentChild]?.Action);
 
                     break;
-                case 0 when _host.UseSubMenusSingleFrame && _barItems.Children [_currentChild].Parent.Parent != null:
-                    _host.PreviousMenu (_barItems.Children [_currentChild].Parent.IsFromSubMenu, true);
+                case 0 when _host.UseSubMenusSingleFrame && _barItems.Children [_currentChild]?.Parent!.Parent != null:
+                    _host.PreviousMenu (_barItems.Children [_currentChild]!.Parent!.IsFromSubMenu, true);
 
                     break;
-                case > -1 when _barItems.SubMenu (_barItems.Children [_currentChild]) != null:
+                case > -1 when _barItems.SubMenu (_barItems.Children [_currentChild]) != null!:
                     CheckSubMenu ();
 
                     break;
@@ -629,7 +654,7 @@ internal sealed class Menu : View
 
     private bool MoveDown ()
     {
-        if (_barItems.IsTopLevel)
+        if (_barItems!.IsTopLevel)
         {
             return true;
         }
@@ -640,19 +665,19 @@ internal sealed class Menu : View
         {
             _currentChild++;
 
-            if (_currentChild >= _barItems.Children.Length)
+            if (_currentChild >= _barItems?.Children?.Length)
             {
                 _currentChild = 0;
             }
 
-            if (this != _host.OpenCurrentMenu && _barItems.Children [_currentChild]?.IsFromSubMenu == true && _host._selectedSub > -1)
+            if (this != _host.OpenCurrentMenu && _barItems?.Children? [_currentChild]?.IsFromSubMenu == true && _host._selectedSub > -1)
             {
                 _host.PreviousMenu (true);
-                _host.SelectEnabledItem (_barItems.Children, _currentChild, out _currentChild);
+                _host.SelectEnabledItem (_barItems.Children!, _currentChild, out _currentChild);
                 _host.OpenCurrentMenu = this;
             }
 
-            MenuItem item = _barItems.Children [_currentChild];
+            MenuItem? item = _barItems?.Children? [_currentChild];
 
             if (item?.IsEnabled () != true)
             {
@@ -663,9 +688,8 @@ internal sealed class Menu : View
                 disabled = false;
             }
 
-            if (!_host.UseSubMenusSingleFrame
-                && _host.UseKeysUpDownAsKeysLeftRight
-                && _barItems.SubMenu (_barItems.Children [_currentChild]) != null
+            if (_host is { UseSubMenusSingleFrame: false, UseKeysUpDownAsKeysLeftRight: true }
+                && _barItems?.SubMenu (_barItems?.Children? [_currentChild]!) != null
                 && !disabled
                 && _host.IsMenuOpen)
             {
@@ -682,7 +706,7 @@ internal sealed class Menu : View
                 _host.OpenMenu (_host._selected);
             }
         }
-        while (_barItems.Children [_currentChild] is null || disabled);
+        while (_barItems?.Children? [_currentChild] is null || disabled);
 
         SetNeedsDisplay ();
         SetParentSetNeedsDisplay ();
@@ -697,7 +721,7 @@ internal sealed class Menu : View
 
     private bool MoveUp ()
     {
-        if (_barItems.IsTopLevel || _currentChild == -1)
+        if (_barItems!.IsTopLevel || _currentChild == -1)
         {
             return true;
         }
@@ -711,7 +735,7 @@ internal sealed class Menu : View
             if (_host.UseKeysUpDownAsKeysLeftRight && !_host.UseSubMenusSingleFrame)
             {
                 if ((_currentChild == -1 || this != _host.OpenCurrentMenu)
-                    && _barItems.Children [_currentChild + 1].IsFromSubMenu
+                    && _barItems.Children! [_currentChild + 1]!.IsFromSubMenu
                     && _host._selectedSub > -1)
                 {
                     _currentChild++;
@@ -729,14 +753,14 @@ internal sealed class Menu : View
 
             if (_currentChild < 0)
             {
-                _currentChild = _barItems.Children.Length - 1;
+                _currentChild = _barItems.Children!.Length - 1;
             }
 
-            if (!_host.SelectEnabledItem (_barItems.Children, _currentChild, out _currentChild, false))
+            if (!_host.SelectEnabledItem (_barItems.Children!, _currentChild, out _currentChild, false))
             {
                 _currentChild = 0;
 
-                if (!_host.SelectEnabledItem (_barItems.Children, _currentChild, out _currentChild) && !_host.CloseMenu (false))
+                if (!_host.SelectEnabledItem (_barItems.Children!, _currentChild, out _currentChild) && !_host.CloseMenu ())
                 {
                     return false;
                 }
@@ -744,12 +768,12 @@ internal sealed class Menu : View
                 break;
             }
 
-            MenuItem item = _barItems.Children [_currentChild];
-            disabled = item?.IsEnabled () != true;
+            MenuItem item = _barItems.Children! [_currentChild]!;
+            disabled = item.IsEnabled () != true;
 
             if (_host.UseSubMenusSingleFrame
                 || !_host.UseKeysUpDownAsKeysLeftRight
-                || _barItems.SubMenu (_barItems.Children [_currentChild]) == null
+                || _barItems.SubMenu (_barItems.Children [_currentChild]!) == null!
                 || disabled
                 || !_host.IsMenuOpen)
             {
@@ -786,8 +810,8 @@ internal sealed class Menu : View
             }
         }
 
-        _host?._openMenu?.SetNeedsDisplay ();
-        _host?.SetNeedsDisplay ();
+        _host._openMenu?.SetNeedsDisplay ();
+        _host.SetNeedsDisplay ();
     }
 
     protected internal override bool OnMouseEvent (MouseEvent me)
@@ -809,13 +833,14 @@ internal sealed class Menu : View
                 return me.Handled = true;
             }
 
-            if (me.Position.Y >= _barItems.Children.Length)
+            if (me.Position.Y >= _barItems!.Children!.Length)
             {
                 return me.Handled = true;
             }
 
-            MenuItem item = _barItems.Children [me.Position.Y];
+            MenuItem item = _barItems.Children [me.Position.Y]!;
 
+            // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
             if (item is null || !item.IsEnabled ())
             {
                 disabled = true;
@@ -844,19 +869,20 @@ internal sealed class Menu : View
         {
             disabled = false;
 
-            if (me.Position.Y < 0 || me.Position.Y >= _barItems.Children.Length)
+            if (me.Position.Y < 0 || me.Position.Y >= _barItems!.Children!.Length)
             {
                 return me.Handled = true;
             }
 
-            MenuItem item = _barItems.Children [me.Position.Y];
+            MenuItem item = _barItems.Children [me.Position.Y]!;
 
+            // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
             if (item is null)
             {
                 return me.Handled = true;
             }
 
-            if (item?.IsEnabled () != true)
+            if (item.IsEnabled () != true)
             {
                 disabled = true;
             }
@@ -882,25 +908,26 @@ internal sealed class Menu : View
 
     internal bool CheckSubMenu ()
     {
-        if (_currentChild == -1 || _barItems.Children [_currentChild] is null)
+        if (_currentChild == -1 || _barItems?.Children? [_currentChild] is null)
         {
             return true;
         }
 
-        MenuBarItem subMenu = _barItems.SubMenu (_barItems.Children [_currentChild]);
+        MenuBarItem? subMenu = _barItems.SubMenu (_barItems.Children [_currentChild]!);
 
+        // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
         if (subMenu is { })
         {
             int pos = -1;
 
             if (_host._openSubMenu is { })
             {
-                pos = _host._openSubMenu.FindIndex (o => o?._barItems == subMenu);
+                pos = _host._openSubMenu.FindIndex (o => o._barItems == subMenu);
             }
 
             if (pos == -1
                 && this != _host.OpenCurrentMenu
-                && subMenu.Children != _host.OpenCurrentMenu._barItems.Children
+                && subMenu.Children != _host.OpenCurrentMenu!._barItems!.Children
                 && !_host.CloseMenu (false, true))
             {
                 return false;
@@ -908,7 +935,7 @@ internal sealed class Menu : View
 
             _host.Activate (_host._selected, pos, subMenu);
         }
-        else if (_host._openSubMenu?.Count == 0 || _host._openSubMenu?.Last ()._barItems.IsSubMenuOf (_barItems.Children [_currentChild]) == false)
+        else if (_host._openSubMenu?.Count == 0 || _host._openSubMenu?.Last ()._barItems!.IsSubMenuOf (_barItems.Children [_currentChild]!) == false)
         {
             return _host.CloseMenu (false, true);
         }

+ 138 - 128
Terminal.Gui/Views/Menu/MenuBar.cs

@@ -1,3 +1,5 @@
+#nullable enable
+
 namespace Terminal.Gui;
 
 /// <summary>
@@ -50,24 +52,22 @@ public class MenuBar : View, IDesignable
     internal bool _isMenuClosing;
     internal bool _isMenuOpening;
 
-    internal Menu _openMenu;
-    internal List<Menu> _openSubMenu;
+    internal Menu? _openMenu;
+    internal List<Menu>? _openSubMenu;
     internal int _selected;
     internal int _selectedSub;
 
     private bool _initialCanFocus;
     private bool _isCleaning;
-    private View _lastFocused;
-    private Menu _ocm;
-    private View _previousFocused;
+    private View? _lastFocused;
+    private Menu? _ocm;
+    private View? _previousFocused;
     private bool _reopen;
     private bool _useSubMenusSingleFrame;
 
     /// <summary>Initializes a new instance of the <see cref="MenuBar"/>.</summary>
     public MenuBar ()
     {
-        MenuItem._menuBar = this;
-
         TabStop = TabBehavior.NoStop;
         X = 0;
         Y = 0;
@@ -78,7 +78,9 @@ public class MenuBar : View, IDesignable
         //CanFocus = true;
         _selected = -1;
         _selectedSub = -1;
+        // ReSharper disable once VirtualMemberCallInConstructor
         ColorScheme = Colors.ColorSchemes ["Menu"];
+        // ReSharper disable once VirtualMemberCallInConstructor
         WantMousePositionReports = true;
         IsMenuOpen = false;
 
@@ -124,8 +126,19 @@ public class MenuBar : View, IDesignable
                         return true;
                     }
                    );
-        AddCommand (Command.ToggleExpandCollapse, ctx => Select (Menus.IndexOf (ctx.KeyBinding?.Context)));
-        AddCommand (Command.Select, ctx => Run ((ctx.KeyBinding?.Context as MenuItem)?.Action));
+        AddCommand (Command.ToggleExpandCollapse, ctx =>
+                                                  {
+                                                      CloseOtherOpenedMenuBar ();
+
+                                                      return Select (Menus.IndexOf (ctx.KeyBinding?.Context));
+                                                  });
+        AddCommand (Command.Select, ctx =>
+                                    {
+                                        var res =  Run ((ctx.KeyBinding?.Context as MenuItem)?.Action!);
+                                        CloseAllMenus ();
+
+                                        return res;
+                                    });
 
         // Default key bindings for this view
         KeyBindings.Add (Key.CursorLeft, Command.Left);
@@ -150,7 +163,7 @@ public class MenuBar : View, IDesignable
     public bool IsMenuOpen { get; protected set; }
 
     /// <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>
     ///     Gets or sets the array of <see cref="MenuBarItem"/>s for the menu. Only set this after the
@@ -164,7 +177,7 @@ public class MenuBar : View, IDesignable
         {
             _menus = value;
 
-            if (Menus is null)
+            if (Menus is [])
             {
                 return;
             }
@@ -174,26 +187,26 @@ public class MenuBar : View, IDesignable
             {
                 MenuBarItem menuBarItem = Menus [i];
 
-                if (menuBarItem?.HotKey != Key.Empty)
+                if (menuBarItem.HotKey != Key.Empty)
                 {
-                    KeyBindings.Remove (menuBarItem!.HotKey);
+                    KeyBindings.Remove (menuBarItem.HotKey!);
                     KeyBinding keyBinding = new ([Command.ToggleExpandCollapse], KeyBindingScope.Focused, menuBarItem);
-                    KeyBindings.Add (menuBarItem!.HotKey, keyBinding);
-                    KeyBindings.Remove (menuBarItem.HotKey.WithAlt);
+                    KeyBindings.Add (menuBarItem.HotKey!, keyBinding);
+                    KeyBindings.Remove (menuBarItem.HotKey!.WithAlt);
                     keyBinding = new ([Command.ToggleExpandCollapse], KeyBindingScope.HotKey, menuBarItem);
                     KeyBindings.Add (menuBarItem.HotKey.WithAlt, keyBinding);
                 }
 
-                if (menuBarItem?.ShortcutKey != Key.Empty)
+                if (menuBarItem.ShortcutKey != Key.Empty)
                 {
                     // Technically this will never run because MenuBarItems don't have shortcuts
                     // unless the IsTopLevel is true
-                    KeyBindings.Remove (menuBarItem.ShortcutKey);
+                    KeyBindings.Remove (menuBarItem.ShortcutKey!);
                     KeyBinding keyBinding = new ([Command.Select], KeyBindingScope.HotKey, menuBarItem);
-                    KeyBindings.Add (menuBarItem.ShortcutKey, keyBinding);
+                    KeyBindings.Add (menuBarItem.ShortcutKey!, keyBinding);
                 }
 
-                menuBarItem?.AddShortcutKeyBindings (this);
+                menuBarItem.AddShortcutKeyBindings (this);
             }
         }
     }
@@ -244,16 +257,16 @@ public class MenuBar : View, IDesignable
         }
     }
 
-    internal Menu OpenCurrentMenu
+    internal Menu? OpenCurrentMenu
     {
         get => _ocm;
         set
         {
             if (_ocm != value)
             {
-                _ocm = value;
+                _ocm = value!;
 
-                if (_ocm is { } && _ocm._currentChild > -1)
+                if (_ocm is { _currentChild: > -1 })
                 {
                     OnMenuOpened ();
                 }
@@ -265,16 +278,16 @@ public class MenuBar : View, IDesignable
     public bool CloseMenu (bool ignoreUseSubMenusSingleFrame = false) { return CloseMenu (false, false, ignoreUseSubMenusSingleFrame); }
 
     /// <summary>Raised when all the menu is closed.</summary>
-    public event EventHandler MenuAllClosed;
+    public event EventHandler? MenuAllClosed;
 
     /// <summary>Raised when a menu is closing passing <see cref="MenuClosingEventArgs"/>.</summary>
-    public event EventHandler<MenuClosingEventArgs> MenuClosing;
+    public event EventHandler<MenuClosingEventArgs>? MenuClosing;
 
     /// <summary>Raised when a menu is opened.</summary>
-    public event EventHandler<MenuOpenedEventArgs> MenuOpened;
+    public event EventHandler<MenuOpenedEventArgs>? MenuOpened;
 
     /// <summary>Raised as a menu is opening.</summary>
-    public event EventHandler<MenuOpeningEventArgs> MenuOpening;
+    public event EventHandler<MenuOpeningEventArgs>? MenuOpening;
 
     /// <inheritdoc/>
     public override void OnDrawContent (Rectangle viewport)
@@ -338,25 +351,24 @@ public class MenuBar : View, IDesignable
     /// <summary>Virtual method that will invoke the <see cref="MenuOpened"/> event if it's defined.</summary>
     public virtual void OnMenuOpened ()
     {
-        MenuItem mi = null;
-        MenuBarItem parent;
+        MenuItem? mi;
+        MenuBarItem? parent;
 
-        if (OpenCurrentMenu.BarItems.Children != null
-            && OpenCurrentMenu.BarItems!.Children.Length > 0
+        if (OpenCurrentMenu?.BarItems?.Children is { Length: > 0 }
             && OpenCurrentMenu?._currentChild > -1)
         {
             parent = OpenCurrentMenu.BarItems;
             mi = parent.Children [OpenCurrentMenu._currentChild];
         }
-        else if (OpenCurrentMenu!.BarItems.IsTopLevel)
+        else if (OpenCurrentMenu!.BarItems!.IsTopLevel)
         {
             parent = null;
             mi = OpenCurrentMenu.BarItems;
         }
         else
         {
-            parent = _openMenu.BarItems;
-            mi = parent.Children?.Length > 0 ? parent.Children [_openMenu._currentChild] : null;
+            parent = _openMenu?.BarItems;
+            mi = parent?.Children?.Length > 0 ? parent.Children [_openMenu!._currentChild] : null;
         }
 
         MenuOpened?.Invoke (this, new (parent, mi));
@@ -376,12 +388,11 @@ public class MenuBar : View, IDesignable
     /// <summary>Opens the Menu programatically, as though the F9 key were pressed.</summary>
     public void OpenMenu ()
     {
-        MenuBar mbar = GetMouseGrabViewInstance (this);
+        MenuBar? mbar = GetMouseGrabViewInstance (this);
 
-        if (mbar is { })
-        {
-            mbar.CleanUp ();
-        }
+        mbar?.CleanUp ();
+
+        CloseOtherOpenedMenuBar ();
 
         if (!Enabled || _openMenu is { })
         {
@@ -391,15 +402,15 @@ public class MenuBar : View, IDesignable
         _selected = 0;
         SetNeedsDisplay ();
 
-        _previousFocused = SuperView is null ? Application.Current?.Focused : SuperView.Focused;
+        _previousFocused = (SuperView is null ? Application.Current?.Focused : SuperView.Focused)!;
         OpenMenu (_selected);
 
         if (!SelectEnabledItem (
-                                OpenCurrentMenu.BarItems.Children,
-                                OpenCurrentMenu._currentChild,
+                                OpenCurrentMenu?.BarItems?.Children,
+                                OpenCurrentMenu!._currentChild,
                                 out OpenCurrentMenu._currentChild
                                )
-            && !CloseMenu (false))
+            && !CloseMenu ())
         {
             return;
         }
@@ -445,14 +456,14 @@ public class MenuBar : View, IDesignable
 
     // Activates the menu, handles either first focus, or activating an entry when it was already active
     // For mouse events.
-    internal void Activate (int idx, int sIdx = -1, MenuBarItem subMenu = null)
+    internal void Activate (int idx, int sIdx = -1, MenuBarItem? subMenu = null!)
     {
         _selected = idx;
         _selectedSub = sIdx;
 
         if (_openMenu is null)
         {
-            _previousFocused = SuperView is null ? Application.Current?.Focused ?? null : SuperView.Focused;
+            _previousFocused = (SuperView is null ? Application.Current?.Focused ?? null : SuperView.Focused)!;
         }
 
         OpenMenu (idx, sIdx, subMenu);
@@ -502,7 +513,7 @@ public class MenuBar : View, IDesignable
                 return;
             }
 
-            if (!CloseMenu (false))
+            if (!CloseMenu ())
             {
                 return;
             }
@@ -523,11 +534,23 @@ public class MenuBar : View, IDesignable
         IsMenuOpen = false;
         _openedByAltKey = false;
         OnMenuAllClosed ();
+
+        CloseOtherOpenedMenuBar ();
     }
 
-    internal bool CloseMenu (bool reopen = false, bool isSubMenu = false, bool ignoreUseSubMenusSingleFrame = false)
+    private void CloseOtherOpenedMenuBar ()
     {
-        MenuBarItem mbi = isSubMenu ? OpenCurrentMenu.BarItems : _openMenu?.BarItems;
+        if (Application.Current is { })
+        {
+            // Close others menu bar opened
+            Menu? menu = Application.Current.Subviews.FirstOrDefault (v => v is Menu m && m.Host != this && m.Host.IsMenuOpen) as Menu;
+            menu?.Host.CleanUp ();
+        }
+    }
+
+    internal bool CloseMenu (bool reopen, bool isSubMenu, bool ignoreUseSubMenusSingleFrame = false)
+    {
+        MenuBarItem? mbi = isSubMenu ? OpenCurrentMenu!.BarItems : _openMenu?.BarItems;
 
         if (UseSubMenusSingleFrame && mbi is { } && !ignoreUseSubMenusSingleFrame && mbi.Parent is { })
         {
@@ -536,7 +559,7 @@ public class MenuBar : View, IDesignable
 
         _isMenuClosing = true;
         _reopen = reopen;
-        MenuClosingEventArgs args = OnMenuClosing (mbi, reopen, isSubMenu);
+        MenuClosingEventArgs args = OnMenuClosing (mbi!, reopen, isSubMenu);
 
         if (args.Cancel)
         {
@@ -561,7 +584,7 @@ public class MenuBar : View, IDesignable
 
                 SetNeedsDisplay ();
 
-                if (_previousFocused is Menu && _openMenu is { } && _previousFocused.ToString () != OpenCurrentMenu.ToString ())
+                if (_previousFocused is Menu && _openMenu is { } && _previousFocused.ToString () != OpenCurrentMenu!.ToString ())
                 {
                     _previousFocused.SetFocus ();
                 }
@@ -615,7 +638,7 @@ public class MenuBar : View, IDesignable
                 _selectedSub = -1;
                 SetNeedsDisplay ();
                 RemoveAllOpensSubMenus ();
-                OpenCurrentMenu._previousSubFocused.SetFocus ();
+                OpenCurrentMenu!._previousSubFocused!.SetFocus ();
                 _openSubMenu = null;
                 IsMenuOpen = true;
 
@@ -632,13 +655,14 @@ public class MenuBar : View, IDesignable
     /// <returns>The location offset.</returns>
     internal Point GetScreenOffset ()
     {
+        // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
         if (Driver is null)
         {
             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)
         {
@@ -646,7 +670,7 @@ public class MenuBar : View, IDesignable
             return Point.Empty;
         }
 
-        Point viewportOffset = sv?.GetViewportOffsetFromFrame () ?? Point.Empty;
+        Point viewportOffset = sv.GetViewportOffsetFromFrame ();
 
         return new (
                     superViewFrame.X - sv.Frame.X - viewportOffset.X,
@@ -680,8 +704,8 @@ public class MenuBar : View, IDesignable
                 OpenMenu (_selected);
 
                 SelectEnabledItem (
-                                   OpenCurrentMenu.BarItems.Children,
-                                   OpenCurrentMenu._currentChild,
+                                   OpenCurrentMenu?.BarItems?.Children,
+                                   OpenCurrentMenu!._currentChild,
                                    out OpenCurrentMenu._currentChild
                                   );
 
@@ -696,9 +720,9 @@ public class MenuBar : View, IDesignable
                 }
                 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.Children [OpenCurrentMenu._currentChild]
+                                                                                  OpenCurrentMenu.BarItems.Children? [OpenCurrentMenu._currentChild]!
                                                                                  )
                                               : null;
 
@@ -713,8 +737,8 @@ public class MenuBar : View, IDesignable
                     }
                     else if (subMenu != null
                              || (OpenCurrentMenu._currentChild > -1
-                                 && !OpenCurrentMenu.BarItems
-                                                    .Children [OpenCurrentMenu._currentChild]
+                                 && !OpenCurrentMenu.BarItems!
+                                                    .Children! [OpenCurrentMenu._currentChild]!
                                                     .IsFromSubMenu))
                     {
                         _selectedSub++;
@@ -742,7 +766,7 @@ public class MenuBar : View, IDesignable
         }
     }
 
-    internal void OpenMenu (int index, int sIndex = -1, MenuBarItem subMenu = null)
+    internal void OpenMenu (int index, int sIndex = -1, MenuBarItem? subMenu = null!)
     {
         _isMenuOpening = true;
         MenuOpeningEventArgs newMenu = OnMenuOpening (Menus [index]);
@@ -780,7 +804,7 @@ public class MenuBar : View, IDesignable
                 }
 
                 // This positions the submenu horizontally aligned with the first character of the
-                // text belonging to the menu 
+                // text belonging to the menu
                 for (var i = 0; i < index; i++)
                 {
                     pos += Menus [i].TitleLength + (Menus [i].Help.GetColumns () > 0 ? Menus [i].Help.GetColumns () + 2 : 0) + _leftPadding + _rightPadding;
@@ -837,7 +861,7 @@ public class MenuBar : View, IDesignable
                 }
                 else
                 {
-                    Menu last = _openSubMenu.Count > 0 ? _openSubMenu.Last () : _openMenu;
+                    Menu? last = _openSubMenu.Count > 0 ? _openSubMenu.Last () : _openMenu;
 
                     if (!UseSubMenusSingleFrame)
                     {
@@ -846,7 +870,7 @@ public class MenuBar : View, IDesignable
                         OpenCurrentMenu = new ()
                         {
                             Host = this,
-                            X = last.Frame.Left + last.Frame.Width + locationOffset.X,
+                            X = last!.Frame.Left + last.Frame.Width + locationOffset.X,
                             Y = last.Frame.Top + locationOffset.Y + last._currentChild,
                             BarItems = subMenu,
                             Parent = last
@@ -854,10 +878,10 @@ public class MenuBar : View, IDesignable
                     }
                     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
-                        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 [1] = null;
 
@@ -866,13 +890,13 @@ public class MenuBar : View, IDesignable
                             mbi [j + 2] = subMenu.Children [j];
                         }
 
-                        var newSubMenu = new MenuBarItem (mbi) { Parent = subMenu };
+                        var newSubMenu = new MenuBarItem (mbi!) { Parent = subMenu };
 
                         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);
                     }
 
@@ -892,7 +916,7 @@ public class MenuBar : View, IDesignable
 
                 if (_selectedSub > -1
                     && SelectEnabledItem (
-                                          OpenCurrentMenu.BarItems.Children,
+                                          OpenCurrentMenu!.BarItems!.Children,
                                           OpenCurrentMenu._currentChild,
                                           out OpenCurrentMenu._currentChild
                                          ))
@@ -929,8 +953,8 @@ public class MenuBar : View, IDesignable
                 OpenMenu (_selected);
 
                 if (!SelectEnabledItem (
-                                        OpenCurrentMenu.BarItems.Children,
-                                        OpenCurrentMenu._currentChild,
+                                        OpenCurrentMenu?.BarItems?.Children,
+                                        OpenCurrentMenu!._currentChild,
                                         out OpenCurrentMenu._currentChild,
                                         false
                                        ))
@@ -961,33 +985,33 @@ public class MenuBar : View, IDesignable
         {
             foreach (Menu item in _openSubMenu)
             {
-                Application.Current.Remove (item);
+                Application.Current!.Remove (item);
                 item.Dispose ();
             }
         }
     }
 
-    internal bool Run (Action action)
+    internal bool Run (Action? action)
     {
         if (action is null)
         {
             return false;
         }
 
-        Application.MainLoop.AddIdle (
-                                      () =>
-                                      {
-                                          action ();
+        Application.MainLoop!.AddIdle (
+                                       () =>
+                                       {
+                                           action ();
 
-                                          return false;
-                                      }
-                                     );
+                                           return false;
+                                       }
+                                      );
 
         return true;
     }
 
     internal bool SelectEnabledItem (
-        IEnumerable<MenuItem> children,
+        MenuItem? []? children,
         int current,
         out int newCurrent,
         bool forward = true
@@ -1000,11 +1024,11 @@ public class MenuBar : View, IDesignable
             return true;
         }
 
-        IEnumerable<MenuItem> childMenuItems = forward ? children : children.Reverse ();
+        IEnumerable<MenuItem?> childMenuItems = forward ? children : children.Reverse ();
 
         int count;
 
-        IEnumerable<MenuItem> menuItems = childMenuItems as MenuItem [] ?? childMenuItems.ToArray ();
+        IEnumerable<MenuItem?> menuItems = childMenuItems as MenuItem [] ?? childMenuItems.ToArray ();
 
         if (forward)
         {
@@ -1015,7 +1039,7 @@ public class MenuBar : View, IDesignable
             count = menuItems.Count ();
         }
 
-        foreach (MenuItem child in menuItems)
+        foreach (MenuItem? child in menuItems)
         {
             if (forward)
             {
@@ -1032,6 +1056,7 @@ public class MenuBar : View, IDesignable
                 }
             }
 
+            // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
             if (child is null || !child.IsEnabled ())
             {
                 if (forward)
@@ -1058,7 +1083,7 @@ public class MenuBar : View, IDesignable
 
     /// <summary>Called when an item is selected; Runs the action.</summary>
     /// <param name="item"></param>
-    internal bool SelectItem (MenuItem item)
+    internal bool SelectItem (MenuItem? item)
     {
         if (item?.Action is null)
         {
@@ -1070,12 +1095,12 @@ public class MenuBar : View, IDesignable
         Application.Refresh ();
         _openedByAltKey = true;
 
-        return Run (item?.Action);
+        return Run (item.Action);
     }
 
     private void CloseMenuBar ()
     {
-        if (!CloseMenu (false))
+        if (!CloseMenu ())
         {
             return;
         }
@@ -1099,7 +1124,7 @@ public class MenuBar : View, IDesignable
         return new (-2, 0);
     }
 
-    private void MenuBar_Added (object sender, SuperViewChangedEventArgs e)
+    private void MenuBar_Added (object? sender, SuperViewChangedEventArgs e)
     {
         _initialCanFocus = CanFocus;
         Added -= MenuBar_Added;
@@ -1146,11 +1171,11 @@ public class MenuBar : View, IDesignable
             OpenMenu (i);
 
             if (!SelectEnabledItem (
-                                    OpenCurrentMenu.BarItems.Children,
-                                    OpenCurrentMenu._currentChild,
+                                    OpenCurrentMenu?.BarItems?.Children,
+                                    OpenCurrentMenu!._currentChild,
                                     out OpenCurrentMenu._currentChild
                                    )
-                && !CloseMenu (false))
+                && !CloseMenu ())
             {
                 return;
             }
@@ -1177,9 +1202,9 @@ public class MenuBar : View, IDesignable
         for (int i = _openSubMenu.Count - 1; i > index; i--)
         {
             _isMenuClosing = true;
-            Menu menu;
+            Menu? menu;
 
-            if (_openSubMenu.Count - 1 > 0)
+            if (_openSubMenu!.Count - 1 > 0)
             {
                 menu = _openSubMenu [i - 1];
             }
@@ -1188,7 +1213,7 @@ public class MenuBar : View, IDesignable
                 menu = _openMenu;
             }
 
-            if (!menu.Visible)
+            if (!menu!.Visible)
             {
                 menu.Visible = true;
             }
@@ -1199,7 +1224,7 @@ public class MenuBar : View, IDesignable
             if (_openSubMenu is { })
             {
                 menu = _openSubMenu [i];
-                Application.Current.Remove (menu);
+                Application.Current!.Remove (menu);
                 _openSubMenu.Remove (menu);
 
                 if (Application.MouseGrabView == menu)
@@ -1213,7 +1238,7 @@ public class MenuBar : View, IDesignable
             RemoveSubMenu (i, ignoreUseSubMenusSingleFrame);
         }
 
-        if (_openSubMenu.Count > 0)
+        if (_openSubMenu!.Count > 0)
         {
             OpenCurrentMenu = _openSubMenu.Last ();
         }
@@ -1305,12 +1330,7 @@ public class MenuBar : View, IDesignable
             {
                 MenuBarItem open = Menus [i];
 
-                if (open is null)
-                {
-                    continue;
-                }
-
-                if (open == OpenCurrentMenu.BarItems && i == index)
+                if (open == OpenCurrentMenu!.BarItems && i == index)
                 {
                     CloseAllMenus ();
                     return true;
@@ -1338,15 +1358,12 @@ public class MenuBar : View, IDesignable
 
     #region Mouse Handling
 
-    /// <inheritdoc/>
     internal void LostFocus (View view)
     {
-        if (((!(view is MenuBar) && !(view is Menu))) && !_isCleaning && !_reopen)
+        if (view is not MenuBar && view is not Menu && !_isCleaning && !_reopen)
         {
             CleanUp ();
         }
-
-        return;
     }
 
     /// <inheritdoc/>
@@ -1411,7 +1428,7 @@ public class MenuBar : View, IDesignable
                     else if (_selected != i
                              && _selected > -1
                              && (me.Flags == MouseFlags.ReportMousePosition
-                                 || (me.Flags == MouseFlags.Button1Pressed && me.Flags == MouseFlags.ReportMousePosition)))
+                                 || (me.Flags is MouseFlags.Button1Pressed && me.Flags == MouseFlags.ReportMousePosition)))
                     {
                         if (IsMenuOpen)
                         {
@@ -1427,8 +1444,7 @@ public class MenuBar : View, IDesignable
                     {
                         if (!UseSubMenusSingleFrame
                             || (UseSubMenusSingleFrame
-                                && OpenCurrentMenu != null
-                                && OpenCurrentMenu.BarItems.Parent != null
+                                && OpenCurrentMenu is { BarItems.Parent: { } }
                                 && OpenCurrentMenu.BarItems.Parent.Parent != Menus [i]))
                         {
                             Activate (i);
@@ -1457,15 +1473,15 @@ public class MenuBar : View, IDesignable
 
     internal bool _handled;
     internal bool _isContextMenuLoading;
-    private MenuBarItem [] _menus;
+    private MenuBarItem [] _menus = [];
 
     internal bool HandleGrabView (MouseEvent me, View current)
     {
         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 { })
                 {
@@ -1563,14 +1579,14 @@ public class MenuBar : View, IDesignable
         return true;
     }
 
-    private MenuBar GetMouseGrabViewInstance (View view)
+    private MenuBar? GetMouseGrabViewInstance (View? view)
     {
         if (view is null || Application.MouseGrabView is null)
         {
             return null;
         }
 
-        MenuBar hostView = null;
+        MenuBar? hostView = null;
 
         if (view is MenuBar)
         {
@@ -1582,15 +1598,15 @@ public class MenuBar : View, IDesignable
         }
 
         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;
@@ -1604,7 +1620,7 @@ public class MenuBar : View, IDesignable
     {
         if (context is not Func<string, bool> actionFn)
         {
-            actionFn = (s) => true;
+            actionFn = (_) => true;
         }
 
         Menus =
@@ -1637,7 +1653,9 @@ public class MenuBar : View, IDesignable
                                       null,
                                       KeyCode.CtrlMask | KeyCode.S
                                      ),
+#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
                                  null,
+#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
 
                                  // Don't use Application.Quit so we can disambiguate between quitting and closing the toplevel
                                  new (
@@ -1770,12 +1788,4 @@ public class MenuBar : View, IDesignable
         ];
         return true;
     }
-
-    /// <inheritdoc />
-    protected override void Dispose (bool disposing)
-    {
-        MenuItem._menuBar = null;
-
-        base.Dispose (disposing);
-    }
 }

+ 39 - 23
Terminal.Gui/Views/Menu/MenuBarItem.cs

@@ -1,3 +1,5 @@
+#nullable enable
+
 namespace Terminal.Gui;
 
 /// <summary>
@@ -16,8 +18,8 @@ public class MenuBarItem : MenuItem
         string title,
         string help,
         Action action,
-        Func<bool> canExecute = null,
-        MenuItem parent = null
+        Func<bool>? canExecute = null,
+        MenuItem? parent = null
     ) : base (title, help, action, canExecute, parent)
     {
         SetInitialProperties (title, null, null, true);
@@ -27,13 +29,13 @@ public class MenuBarItem : MenuItem
     /// <param name="title">Title for the menu item.</param>
     /// <param name="children">The items in the current menu.</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>
     /// <param name="title">Title for the menu item.</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>
-    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>
     /// <param name="children">The items in the current menu.</param>
@@ -47,7 +49,7 @@ public class MenuBarItem : MenuItem
     ///     <see cref="MenuBarItem"/>
     /// </summary>
     /// <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;
 
@@ -63,7 +65,7 @@ public class MenuBarItem : MenuItem
             return -1;
         }
 
-        foreach (MenuItem child in Children)
+        foreach (MenuItem? child in Children)
         {
             if (child == children)
             {
@@ -81,13 +83,13 @@ public class MenuBarItem : MenuItem
     /// <returns>Returns <c>true</c> if it is a submenu. <c>false</c> otherwise.</returns>
     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>
     /// <param name="menuItem"></param>
     /// <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)
     {
@@ -96,20 +98,27 @@ public class MenuBarItem : MenuItem
             return;
         }
 
-        foreach (MenuItem menuItem in Children.Where (m => m is { }))
+        _menuBar = menuBar;
+
+        IEnumerable<MenuItem> menuItems = Children.Where (m => m is { })!;
+
+        foreach (MenuItem menuItem in menuItems)
         {
-            // For MenuBar only add shortcuts for submenus
+            // Initialize MenuItem _menuBar
+            menuItem._menuBar = menuBar;
 
+            // For MenuBar only add shortcuts for submenus
             if (menuItem.ShortcutKey != Key.Empty)
             {
-                menuItem.UpdateShortcutKeyBinding (Key.Empty);
+                menuItem.AddShortcutKeyBinding (menuBar, Key.Empty);
             }
 
             SubMenu (menuItem)?.AddShortcutKeyBindings (menuBar);
         }
     }
 
-    private void SetInitialProperties (string title, object children, MenuItem parent = null, bool isTopLevel = false)
+    // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local
+    private void SetInitialProperties (string title, object? children, MenuItem? parent = null, bool isTopLevel = false)
     {
         if (!isTopLevel && children is null)
         {
@@ -119,7 +128,7 @@ public class MenuBarItem : MenuItem
                                             );
         }
 
-        SetTitle (title ?? "");
+        SetTitle (title);
 
         if (parent is { })
         {
@@ -169,7 +178,7 @@ public class MenuBarItem : MenuItem
         }
     }
 
-    private void SetTitle (string title)
+    private void SetTitle (string? title)
     {
         title ??= string.Empty;
         Title = title;
@@ -178,9 +187,14 @@ public class MenuBarItem : MenuItem
     /// <summary>
     /// Add a <see cref="MenuBarItem"/> dynamically into the <see cref="MenuBar"/><c>.Menus</c>.
     /// </summary>
+    /// <param name="menuBar"></param>
     /// <param name="menuItem"></param>
-    public void AddMenuBarItem (MenuItem menuItem = null)
+    public void AddMenuBarItem (MenuBar menuBar, MenuItem? menuItem = null)
     {
+        ArgumentNullException.ThrowIfNull (menuBar);
+
+        _menuBar = menuBar;
+
         if (menuItem is null)
         {
             MenuBarItem [] menus = _menuBar.Menus;
@@ -190,8 +204,9 @@ public class MenuBarItem : MenuItem
         }
         else
         {
-            MenuItem [] childrens = Children ?? [];
+            MenuItem [] childrens = (Children ?? [])!;
             Array.Resize (ref childrens, childrens.Length + 1);
+            menuItem._menuBar = menuBar;
             childrens [^1] = menuItem;
             Children = childrens;
         }
@@ -202,12 +217,12 @@ public class MenuBarItem : MenuItem
     {
         if (Children is { })
         {
-            foreach (MenuItem menuItem in Children)
+            foreach (MenuItem? menuItem in Children)
             {
-                if (menuItem.ShortcutKey != Key.Empty)
+                if (menuItem?.ShortcutKey != Key.Empty)
                 {
                     // Remove an existent ShortcutKey
-                    _menuBar?.KeyBindings.Remove (menuItem.ShortcutKey);
+                    _menuBar?.KeyBindings.Remove (menuItem?.ShortcutKey!);
                 }
             }
         }
@@ -215,25 +230,26 @@ public class MenuBarItem : MenuItem
         if (ShortcutKey != Key.Empty)
         {
             // Remove an existent ShortcutKey
-            _menuBar?.KeyBindings.Remove (ShortcutKey);
+            _menuBar?.KeyBindings.Remove (ShortcutKey!);
         }
 
         var index = _menuBar!.Menus.IndexOf (this);
         if (index > -1)
         {
-            if (_menuBar!.Menus [index].HotKey != Key.Empty)
+            if (_menuBar.Menus [index].HotKey != Key.Empty)
             {
                 // Remove an existent HotKey
-                _menuBar?.KeyBindings.Remove (HotKey.WithAlt);
+                _menuBar.KeyBindings.Remove (HotKey!.WithAlt);
             }
 
-            _menuBar!.Menus [index] = null;
+            _menuBar.Menus [index] = null!;
         }
 
         var i = 0;
 
         foreach (MenuBarItem m in _menuBar.Menus)
         {
+            // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
             if (m != null)
             {
                 _menuBar.Menus [i] = m;

+ 58 - 41
Terminal.Gui/Views/Menu/MenuItem.cs

@@ -1,3 +1,5 @@
+#nullable enable
+
 namespace Terminal.Gui;
 
 /// <summary>
@@ -6,10 +8,10 @@ namespace Terminal.Gui;
 /// </summary>
 public class MenuItem
 {
-    internal static MenuBar _menuBar;
+    internal MenuBar _menuBar;
 
     /// <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>
     /// <param name="title">Title for the menu item.</param>
@@ -19,26 +21,26 @@ public class MenuItem
     /// <param name="parent">The <see cref="Parent"/> of this menu item.</param>
     /// <param name="shortcutKey">The <see cref="ShortcutKey"/> keystroke combination.</param>
     public MenuItem (
-        string title,
-        string help,
-        Action action,
-        Func<bool> canExecute = null,
-        MenuItem parent = null,
-        Key shortcutKey = null
+        string? title,
+        string? help,
+        Action? action,
+        Func<bool>? canExecute = null,
+        MenuItem? parent = null,
+        Key? shortcutKey = null
     )
     {
         Title = title ?? "";
         Help = help ?? "";
-        Action = action;
-        CanExecute = canExecute;
-        Parent = parent;
+        Action = action!;
+        CanExecute = canExecute!;
+        Parent = parent!;
 
         if (Parent is { } && Parent.ShortcutKey != Key.Empty)
         {
             Parent.ShortcutKey = Key.Empty;
         }
         // Setter will ensure Key.Empty if it's null
-        ShortcutKey = shortcutKey;
+        ShortcutKey = shortcutKey!;
     }
 
     private bool _allowNullChecked;
@@ -48,7 +50,7 @@ public class MenuItem
 
     /// <summary>Gets or sets the action to be invoked when the menu item is triggered.</summary>
     /// <value>Method to invoke.</value>
-    public Action Action { get; set; }
+    public Action? Action { get; set; }
 
     /// <summary>
     ///     Used only if <see cref="CheckType"/> is of <see cref="MenuItemCheckStyle.Checked"/> type. If
@@ -70,7 +72,7 @@ public class MenuItem
     ///     returns <see langword="true"/> the menu item will be enabled. Otherwise, it will be disabled.
     /// </summary>
     /// <value>Function to determine if the action is can be executed or not.</value>
-    public Func<bool> CanExecute { get; set; }
+    public Func<bool>? CanExecute { get; set; }
 
     /// <summary>
     ///     Sets or gets whether the <see cref="MenuItem"/> shows a check indicator or not. See
@@ -112,7 +114,7 @@ public class MenuItem
 
     /// <summary>Gets the parent for this <see cref="MenuItem"/>.</summary>
     /// <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>
     /// <value>The title.</value>
@@ -186,7 +188,7 @@ public class MenuItem
                           (Checked == true || CheckType.HasFlag (MenuItemCheckStyle.Checked) || CheckType.HasFlag (MenuItemCheckStyle.Radio)
                                ? 2
                                : 0)
-                          + // check glyph + space 
+                          + // check glyph + space
                           (Help.GetColumns () > 0 ? 2 + Help.GetColumns () : 0)
                           + // Two spaces before Help
                           (ShortcutTag.GetColumns () > 0
@@ -217,12 +219,12 @@ public class MenuItem
     ///     </para>
     ///     <para>See also <see cref="ShortcutKey"/> which enable global key-bindings to menu items.</para>
     /// </summary>
-    public Key HotKey
+    public Key? HotKey
     {
         get => _hotKey;
         private set
         {
-            var oldKey = _hotKey ?? Key.Empty;
+            var oldKey = _hotKey;
             _hotKey = value ?? Key.Empty;
             UpdateHotKeyBinding (oldKey);
         }
@@ -260,30 +262,55 @@ public class MenuItem
     ///         <see cref="Help"/> text. See <see cref="ShortcutTag"/>.
     ///     </para>
     /// </summary>
-    public Key ShortcutKey
+    public Key? ShortcutKey
     {
         get => _shortcutKey;
         set
         {
-            var oldKey = _shortcutKey ?? Key.Empty;
+            var oldKey = _shortcutKey;
             _shortcutKey = value ?? Key.Empty;
             UpdateShortcutKeyBinding (oldKey);
         }
     }
 
     /// <summary>Gets the text describing the keystroke combination defined by <see cref="ShortcutKey"/>.</summary>
-    public string ShortcutTag => ShortcutKey != Key.Empty ? ShortcutKey.ToString () : string.Empty;
+    public string ShortcutTag => ShortcutKey != Key.Empty ? ShortcutKey!.ToString () : string.Empty;
+
+    internal void AddShortcutKeyBinding (MenuBar menuBar, Key key)
+    {
+        ArgumentNullException.ThrowIfNull (menuBar);
+
+        _menuBar = menuBar;
+
+        AddOrUpdateShortcutKeyBinding (key);
+    }
+
+    private void AddOrUpdateShortcutKeyBinding (Key key)
+    {
+        if (key != Key.Empty)
+        {
+            _menuBar.KeyBindings.Remove (key);
+        }
+
+        if (ShortcutKey != Key.Empty)
+        {
+            KeyBinding keyBinding = new ([Command.Select], KeyBindingScope.HotKey, this);
+            // Remove an existent ShortcutKey
+            _menuBar.KeyBindings.Remove (ShortcutKey!);
+            _menuBar.KeyBindings.Add (ShortcutKey!, keyBinding);
+        }
+    }
 
     private void UpdateHotKeyBinding (Key oldKey)
     {
-        if (_menuBar is null || _menuBar?.IsInitialized == false)
+        if (_menuBar is null or { IsInitialized: false })
         {
             return;
         }
 
         if (oldKey != Key.Empty)
         {
-            var index = _menuBar.Menus?.IndexOf (this);
+            var index = _menuBar.Menus.IndexOf (this);
 
             if (index > -1)
             {
@@ -293,36 +320,26 @@ public class MenuItem
 
         if (HotKey != Key.Empty)
         {
-            var index = _menuBar.Menus?.IndexOf (this);
+            var index = _menuBar.Menus.IndexOf (this);
 
             if (index > -1)
             {
-                _menuBar.KeyBindings.Remove (HotKey.WithAlt);
+                _menuBar.KeyBindings.Remove (HotKey!.WithAlt);
                 KeyBinding keyBinding = new ([Command.ToggleExpandCollapse], KeyBindingScope.HotKey, this);
                 _menuBar.KeyBindings.Add (HotKey.WithAlt, keyBinding);
             }
         }
     }
 
-    internal void UpdateShortcutKeyBinding (Key oldKey)
+    private void UpdateShortcutKeyBinding (Key oldKey)
     {
+        // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
         if (_menuBar is null)
         {
             return;
         }
 
-        if (oldKey != Key.Empty)
-        {
-            _menuBar.KeyBindings.Remove (oldKey);
-        }
-
-        if (ShortcutKey != Key.Empty)
-        {
-            KeyBinding keyBinding = new ([Command.Select], KeyBindingScope.HotKey, this);
-            // Remove an existent ShortcutKey
-            _menuBar?.KeyBindings.Remove (ShortcutKey);
-            _menuBar?.KeyBindings.Add (ShortcutKey, keyBinding);
-        }
+        AddOrUpdateShortcutKeyBinding (oldKey);
     }
 
     #endregion Keyboard Handling
@@ -334,10 +351,10 @@ public class MenuItem
     {
         if (Parent is { })
         {
-            MenuItem [] childrens = ((MenuBarItem)Parent).Children;
+            MenuItem? []? childrens = ((MenuBarItem)Parent).Children;
             var i = 0;
 
-            foreach (MenuItem c in childrens)
+            foreach (MenuItem? c in childrens!)
             {
                 if (c != this)
                 {
@@ -361,7 +378,7 @@ public class MenuItem
         if (ShortcutKey != Key.Empty)
         {
             // Remove an existent ShortcutKey
-            _menuBar?.KeyBindings.Remove (ShortcutKey);
+            _menuBar.KeyBindings.Remove (ShortcutKey!);
         }
     }
 }

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

@@ -405,7 +405,7 @@ public class TextField : View
 
         _currentCulture = Thread.CurrentThread.CurrentUICulture;
 
-        ContextMenu = new ContextMenu { Host = this, MenuItems = BuildContextMenuBarItem () };
+        ContextMenu = new ContextMenu { Host = this };
         ContextMenu.KeyChanged += ContextMenu_KeyChanged;
 
         KeyBindings.Add (ContextMenu.Key, KeyBindingScope.HotKey, Command.ShowContextMenu);
@@ -1853,14 +1853,12 @@ public class TextField : View
 
     private void ShowContextMenu ()
     {
-        if (_currentCulture != Thread.CurrentThread.CurrentUICulture)
+        if (!Equals (_currentCulture, Thread.CurrentThread.CurrentUICulture))
         {
             _currentCulture = Thread.CurrentThread.CurrentUICulture;
-
-            ContextMenu.MenuItems = BuildContextMenuBarItem ();
         }
 
-        ContextMenu.Show ();
+        ContextMenu.Show (BuildContextMenuBarItem ());
     }
 
     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;
 
-        ContextMenu = new () { MenuItems = BuildContextMenuBarItem () };
+        ContextMenu = new ();
         ContextMenu.KeyChanged += ContextMenu_KeyChanged!;
 
         KeyBindings.Add ((KeyCode)ContextMenu.Key, KeyBindingScope.HotKey, Command.ShowContextMenu);
@@ -3494,7 +3494,7 @@ public class TextView : View
         }
         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 ();
         }
 
@@ -4131,7 +4131,7 @@ public class TextView : View
 
     private void AppendClipboard (string text) { Clipboard.Contents += text; }
 
-    private MenuBarItem BuildContextMenuBarItem ()
+    private MenuBarItem? BuildContextMenuBarItem ()
     {
         return new (
                     new MenuItem []
@@ -6289,14 +6289,12 @@ public class TextView : View
 
     private void ShowContextMenu ()
     {
-        if (_currentCulture != Thread.CurrentThread.CurrentUICulture)
+        if (!Equals (_currentCulture, Thread.CurrentThread.CurrentUICulture))
         {
             _currentCulture = Thread.CurrentThread.CurrentUICulture;
-
-            ContextMenu!.MenuItems = BuildContextMenuBarItem ();
         }
 
-        ContextMenu!.Show ();
+        ContextMenu!.Show (BuildContextMenuBarItem ());
     }
 
     private void StartSelecting ()

+ 1 - 0
Terminal.sln.DotSettings

@@ -400,6 +400,7 @@
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002EMemberReordering_002EMigrations_002ECSharpFileLayoutPatternRemoveIsAttributeUpgrade/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/UserDictionary/Words/=Justifier/@EntryIndexedValue">True</s:Boolean>

+ 25 - 24
UICatalog/Scenarios/CharacterMap.cs

@@ -902,31 +902,32 @@ internal class CharMap : View
 
             _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);
         }
     }
 

+ 120 - 120
UICatalog/Scenarios/ContextMenus.cs

@@ -98,8 +98,8 @@ public class ContextMenus : Scenario
             Menus =
             [
                 new (
-                     "File",
-                     new MenuItem [] { new ("Quit", "", () => Application.RequestStop (), null, null, Application.QuitKey) })
+                     "_File",
+                     new MenuItem [] { new ("_Quit", "", () => Application.RequestStop (), null, null, Application.QuitKey) })
             ]
         };
 
@@ -163,133 +163,133 @@ public class ContextMenus : Scenario
         _contextMenu = new()
         {
             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,
             UseSubMenusSingleFrame = _useSubMenusSingleFrame
         };
 
+        MenuBarItem menuItems = new (
+                                     new []
+                                     {
+                                         new MenuBarItem (
+                                                          "_Languages",
+                                                          GetSupportedCultures ()
+                                                         ),
+                                         new (
+                                              "_Configuration",
+                                              "Show configuration",
+                                              () => MessageBox.Query (
+                                                                      50,
+                                                                      5,
+                                                                      "Info",
+                                                                      "This would open settings dialog",
+                                                                      "Ok"
+                                                                     )
+                                             ),
+                                         new MenuBarItem (
+                                                          "M_ore 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"
+                                                                              )
+                                                                  )
+                                                          }
+                                                         ),
+                                         _miForceMinimumPosToZero =
+                                             new (
+                                                  "Fo_rceMinimumPosToZero",
+                                                  "",
+                                                  () =>
+                                                  {
+                                                      _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;
         _tfTopRight.ContextMenu.ForceMinimumPosToZero = _forceMinimumPosToZero;
         _tfMiddle.ContextMenu.ForceMinimumPosToZero = _forceMinimumPosToZero;
         _tfBottomLeft.ContextMenu.ForceMinimumPosToZero = _forceMinimumPosToZero;
         _tfBottomRight.ContextMenu.ForceMinimumPosToZero = _forceMinimumPosToZero;
 
-        _contextMenu.Show ();
+        _contextMenu.Show (menuItems);
     }
 }

+ 27 - 17
UICatalog/Scenarios/DynamicMenuBar.cs

@@ -875,7 +875,7 @@ public class DynamicMenuBar : Scenario
                                   {
                                       MenuItem newMenu = CreateNewMenu (item, _currentMenuBarItem);
                                       var menuBarItem = _currentMenuBarItem as MenuBarItem;
-                                      menuBarItem.AddMenuBarItem (newMenu);
+                                      menuBarItem.AddMenuBarItem (MenuBar, newMenu);
 
 
                                       DataContext.Menus.Add (new () { Title = newMenu.Title, MenuItem = newMenu });
@@ -915,6 +915,11 @@ public class DynamicMenuBar : Scenario
                                             _lstMenus.SelectedItem = _lstMenus.Source.Count - 1;
                                         }
 
+                                        if (_menuBar.Menus.Length == 0)
+                                        {
+                                            RemoveMenuBar ();
+                                        }
+
                                         _lstMenus.SetNeedsDisplay ();
                                         SetFrameDetails ();
                                     }
@@ -992,7 +997,7 @@ public class DynamicMenuBar : Scenario
                                          }
 
                                          var newMenu = CreateNewMenu (item) as MenuBarItem;
-                                         newMenu.AddMenuBarItem ();
+                                         newMenu.AddMenuBarItem (MenuBar);
 
                                          _currentMenuBarItem = newMenu;
                                          _currentMenuBarItem.CheckType = item.CheckStyle;
@@ -1012,7 +1017,7 @@ public class DynamicMenuBar : Scenario
 
             btnRemoveMenuBar.Accept += (s, e) =>
                                         {
-                                            if (_menuBar == null || _menuBar.Menus.Length == 0)
+                                            if (_menuBar == null)
                                             {
                                                 return;
                                             }
@@ -1033,25 +1038,30 @@ public class DynamicMenuBar : Scenario
                                                                           : null;
                                             }
 
-                                            if (MenuBar != null && _currentMenuBarItem == null && _menuBar.Menus.Length == 0)
-                                            {
-                                                Remove (_menuBar);
-                                                _menuBar.Dispose ();
-                                                _menuBar = null;
-                                                DataContext.Menus = new ();
-                                                _currentMenuBarItem = null;
-                                                _currentSelectedMenuBar = -1;
-                                                lblMenuBar.Text = string.Empty;
-                                            }
-                                            else
-                                            {
-                                                lblMenuBar.Text = _menuBar.Menus [_currentSelectedMenuBar].Title;
-                                            }
+                                            RemoveMenuBar ();
 
                                             SetListViewSource (_currentMenuBarItem, true);
                                             SetFrameDetails ();
                                         };
 
+            void RemoveMenuBar ()
+            {
+                if (MenuBar != null && _currentMenuBarItem == null && _menuBar.Menus.Length == 0)
+                {
+                    Remove (_menuBar);
+                    _menuBar.Dispose ();
+                    _menuBar = null;
+                    DataContext.Menus = new ();
+                    _currentMenuBarItem = null;
+                    _currentSelectedMenuBar = -1;
+                    lblMenuBar.Text = string.Empty;
+                }
+                else
+                {
+                    lblMenuBar.Text = _menuBar.Menus [_currentSelectedMenuBar].Title;
+                }
+            }
+
             SetFrameDetails ();
 
             var ustringConverter = new UStringValueConverter ();

+ 2 - 2
UICatalog/Scenarios/Notepad.cs

@@ -362,9 +362,9 @@ public class Notepad : Scenario
 
         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;
     }
 

+ 20 - 20
UICatalog/Scenarios/TableEditor.cs

@@ -1266,28 +1266,28 @@ public class TableEditor : Scenario
 
         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)

+ 6 - 7
UICatalog/Scenarios/TreeViewFileSystem.cs

@@ -415,21 +415,20 @@ public class TreeViewFileSystem : Scenario
 
     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 ()
     {
         _miShowLines.Checked = !_miShowLines.Checked;
 
-        _treeViewFiles.Style.ShowBranchLines = (bool)_miShowLines.Checked;
+        _treeViewFiles.Style.ShowBranchLines = (bool)_miShowLines.Checked!;
         _treeViewFiles.SetNeedsDisplay ();
     }
 

+ 1 - 1
UICatalog/UICatalog.cs

@@ -875,7 +875,7 @@ public class UICatalogApp
                 };
             }
 
-            Enum GetDiagnosticsEnumValue (string title)
+            Enum GetDiagnosticsEnumValue (string? title)
             {
                 return title switch
                 {

+ 663 - 146
UnitTests/Views/ContextMenuTests.cs

@@ -10,42 +10,54 @@ public class ContextMenuTests (ITestOutputHelper output)
     public void ContextMenu_Constructors ()
     {
         var cm = new ContextMenu ();
+        var top = new Toplevel ();
+        Application.Begin (top);
+
         Assert.Equal (Point.Empty, cm.Position);
-        Assert.Empty (cm.MenuItems.Children);
+        Assert.Null (cm.MenuItems);
         Assert.Null (cm.Host);
         cm.Position = new Point (20, 10);
 
-        cm.MenuItems = new MenuBarItem (
-                                        [
-                                            new MenuItem ("First", "", null)
-                                        ]
-                                       );
+        var menuItems = new MenuBarItem (
+                                         [
+                                             new MenuItem ("First", "", null)
+                                         ]
+                                        );
+        cm.Show (menuItems);
         Assert.Equal (new Point (20, 10), cm.Position);
-        Assert.Single (cm.MenuItems.Children);
+        Assert.Single (cm.MenuItems!.Children);
 
         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 (2, cm.MenuItems.Children.Length);
+        Assert.Equal (2, cm.MenuItems!.Children.Length);
         Assert.Null (cm.Host);
 
+        var view = new View { X = 5, Y = 10 };
+        top.Add (view);
+
         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 (2, cm.MenuItems.Children.Length);
         Assert.NotNull (cm.Host);
+
+        top.Dispose ();
     }
 
     [Fact]
@@ -54,14 +66,15 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
         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 ("Two", "", null)
                                          ]
-                                        )
-        };
+                                        );
 
         var menu = new MenuBar
         {
@@ -78,7 +91,7 @@ public class ContextMenuTests (ITestOutputHelper output)
 
         Assert.Null (Application.MouseGrabView);
 
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.True (ContextMenu.IsShow);
         Assert.Equal (cm.MenuBar, Application.MouseGrabView);
         Assert.False (menu.IsMenuOpen);
@@ -87,7 +100,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.Equal (menu, Application.MouseGrabView);
         Assert.True (menu.IsMenuOpen);
 
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.True (ContextMenu.IsShow);
         Assert.Equal (cm.MenuBar, Application.MouseGrabView);
         Assert.False (menu.IsMenuOpen);
@@ -98,7 +111,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.True (menu.IsMenuOpen);
 #endif
 
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.True (ContextMenu.IsShow);
         Assert.Equal (cm.MenuBar, Application.MouseGrabView);
         Assert.False (menu.IsMenuOpen);
@@ -305,21 +318,21 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
         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 ("Two", "", null)
                                          ]
-                                        )
-        };
-
+                                        );
         Assert.Equal (new Point (-1, -2), cm.Position);
-        
+
         Toplevel top = new ();
         Application.Begin (top);
 
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.Equal (new Point (-1, -2), cm.Position);
         Application.Refresh ();
 
@@ -334,7 +347,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.Equal (new Rectangle (0, 1, 8, 4), pos);
 
         cm.ForceMinimumPosToZero = false;
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.Equal (new Point (-1, -2), cm.Position);
         Application.Refresh ();
 
@@ -355,22 +368,22 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
         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 ("Two", "", null)
                                          ]
-                                        )
-        };
-
+                                        );
         Toplevel top = new ();
         Application.Begin (top);
         top.Running = true;
 
         Assert.False (ContextMenu.IsShow);
 
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.True (ContextMenu.IsShow);
 
         top.RequestStop ();
@@ -388,8 +401,9 @@ public class ContextMenuTests (ITestOutputHelper output)
         Application.Begin (top);
 
         Assert.True (Application.OnKeyDown (ContextMenu.DefaultKey));
-        Assert.True (tf.ContextMenu.MenuBar.IsMenuOpen);
+        Assert.True (tf.ContextMenu.MenuBar!.IsMenuOpen);
         Assert.True (Application.OnKeyDown (ContextMenu.DefaultKey));
+
         // The last context menu bar opened is always preserved
         Assert.NotNull (tf.ContextMenu.MenuBar);
         top.Dispose ();
@@ -415,18 +429,18 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
         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 ("Two", "", null)
                                          ]
-                                        )
-        };
-
+                                        );
         Toplevel top = new ();
         Application.Begin (top);
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
 
         var expected = @"
@@ -438,15 +452,15 @@ public class ContextMenuTests (ITestOutputHelper 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 ();
 
         expected = @"
@@ -467,8 +481,10 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
         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 ("Two", "", null),
@@ -488,15 +504,13 @@ public class ContextMenuTests (ITestOutputHelper output)
                                              new MenuItem ("Five", "", null),
                                              new MenuItem ("Six", "", null)
                                          ]
-                                        )
-        };
-
+                                        );
         Assert.Equal (new Point (-1, -2), cm.Position);
 
         Toplevel top = new ();
         Application.Begin (top);
 
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
 
         Assert.Equal (new Point (-1, -2), cm.Position);
@@ -518,8 +532,8 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.True (
                      top.Subviews [0]
                         .NewMouseEvent (
-                                     new MouseEvent { Position = new (0, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
-                                    )
+                                        new MouseEvent { Position = new (0, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
+                                       )
                     );
         Application.Refresh ();
         Assert.Equal (new Point (-1, -2), cm.Position);
@@ -545,7 +559,7 @@ public class ContextMenuTests (ITestOutputHelper output)
 
         ((FakeDriver)Application.Driver!).SetBufferSize (40, 20);
         cm.Position = new Point (41, -2);
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
         Assert.Equal (new Point (41, -2), cm.Position);
 
@@ -566,8 +580,8 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.True (
                      top.Subviews [0]
                         .NewMouseEvent (
-                                     new MouseEvent { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
-                                    )
+                                        new MouseEvent { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
+                                       )
                     );
         Application.Refresh ();
         Assert.Equal (new Point (41, -2), cm.Position);
@@ -592,7 +606,7 @@ public class ContextMenuTests (ITestOutputHelper output)
                                                      );
 
         cm.Position = new Point (41, 9);
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
         Assert.Equal (new Point (41, 9), cm.Position);
 
@@ -613,8 +627,8 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.True (
                      top.Subviews [0]
                         .NewMouseEvent (
-                                     new MouseEvent { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
-                                    )
+                                        new MouseEvent { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
+                                       )
                     );
         Application.Refresh ();
         Assert.Equal (new Point (41, 9), cm.Position);
@@ -636,7 +650,7 @@ public class ContextMenuTests (ITestOutputHelper output)
                                                      );
 
         cm.Position = new Point (41, 22);
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
         Assert.Equal (new Point (41, 22), cm.Position);
 
@@ -657,8 +671,8 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.True (
                      top.Subviews [0]
                         .NewMouseEvent (
-                                     new MouseEvent { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
-                                    )
+                                        new MouseEvent { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
+                                       )
                     );
         Application.Refresh ();
         Assert.Equal (new Point (41, 22), cm.Position);
@@ -680,7 +694,7 @@ public class ContextMenuTests (ITestOutputHelper output)
 
         ((FakeDriver)Application.Driver!).SetBufferSize (18, 8);
         cm.Position = new Point (19, 10);
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
         Assert.Equal (new Point (19, 10), cm.Position);
 
@@ -701,8 +715,8 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.True (
                      top.Subviews [0]
                         .NewMouseEvent (
-                                     new MouseEvent { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
-                                    )
+                                        new MouseEvent { Position = new (30, 3), Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] }
+                                       )
                     );
         Application.Refresh ();
         Assert.Equal (new Point (19, 10), cm.Position);
@@ -773,18 +787,18 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
         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 ("Two", "", null)
                                          ]
-                                        )
-        };
-
+                                        );
         Toplevel top = new ();
         Application.Begin (top);
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
 
         var expected = @"
@@ -798,7 +812,7 @@ public class ContextMenuTests (ITestOutputHelper output)
 
         cm.Position = new Point (5, 10);
 
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Refresh ();
 
         expected = @"
@@ -816,7 +830,14 @@ public class ContextMenuTests (ITestOutputHelper output)
     [AutoInitShutdown]
     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 ();
         var isMenuAllClosed = false;
         MenuBarItem mi = null;
@@ -828,7 +849,7 @@ public class ContextMenuTests (ITestOutputHelper output)
 
                                      if (iterations == 0)
                                      {
-                                         cm.Show ();
+                                         cm.Show (menuItems);
                                          Assert.True (ContextMenu.IsShow);
                                          mi = cm.MenuBar.Menus [0];
 
@@ -853,7 +874,7 @@ public class ContextMenuTests (ITestOutputHelper output)
                                      else if (iterations == 3)
                                      {
                                          isMenuAllClosed = false;
-                                         cm.Show ();
+                                         cm.Show (menuItems);
                                          Assert.True (ContextMenu.IsShow);
                                          cm.MenuBar.MenuAllClosed += (_, _) => isMenuAllClosed = true;
                                      }
@@ -896,20 +917,20 @@ public class ContextMenuTests (ITestOutputHelper output)
 
         var cm = new ContextMenu
         {
-            Position = Point.Empty,
-            MenuItems = new MenuBarItem (
+            Position = Point.Empty
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("Two", "", null)
                                          ]
-                                        )
-        };
-
+                                        );
         Assert.Equal (Point.Empty, cm.Position);
 
         Toplevel top = new ();
         Application.Begin (top);
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.Equal (Point.Empty, cm.Position);
         Application.Refresh ();
 
@@ -934,20 +955,20 @@ public class ContextMenuTests (ITestOutputHelper output)
 
         var cm = new ContextMenu
         {
-            Position = Point.Empty,
-            MenuItems = new MenuBarItem (
+            Position = Point.Empty
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("Two", "", null)
                                          ]
-                                        )
-        };
-
+                                        );
         Assert.Equal (Point.Empty, cm.Position);
 
         Toplevel top = new ();
         Application.Begin (top);
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.Equal (Point.Empty, cm.Position);
         Application.Refresh ();
 
@@ -981,22 +1002,22 @@ public class ContextMenuTests (ITestOutputHelper output)
         var cm = new ContextMenu
         {
             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 ("Two", "", null)
                                          ]
-                                        )
-        };
-
+                                        );
         var top = new Toplevel ();
         top.Add (view);
         Application.Begin (top);
 
         Assert.Equal (new Point (10, 5), cm.Position);
 
-        cm.Show ();
+        cm.Show (menuItems);
         top.Draw ();
         Assert.Equal (new Point (10, 5), cm.Position);
 
@@ -1017,7 +1038,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         cm.Host.Y = 10;
         cm.Host.Height = 3;
 
-        cm.Show ();
+        cm.Show (menuItems);
         Application.Top.Draw ();
         Assert.Equal (new Point (5, 12), cm.Position);
 
@@ -1045,20 +1066,20 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
         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 ("Two", "", null)
                                          ]
-                                        )
-        };
-
+                                        );
         Assert.Equal (new Point (80, 25), cm.Position);
 
         Toplevel top = new ();
         Application.Begin (top);
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.Equal (new Point (80, 25), cm.Position);
         Application.Refresh ();
 
@@ -1092,15 +1113,15 @@ public class ContextMenuTests (ITestOutputHelper output)
 
         var cm = new ContextMenu
         {
-            Host = view,
-            MenuItems = new MenuBarItem (
+            Host = view
+        };
+
+        var menuItems = new MenuBarItem (
                                          [
                                              new MenuItem ("One", "", null),
                                              new MenuItem ("Two", "", null)
                                          ]
-                                        )
-        };
-
+                                        );
         var top = new Toplevel ();
         top.Add (view);
         Application.Begin (top);
@@ -1108,7 +1129,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.Equal (new Rectangle (70, 24, 10, 1), view.Frame);
         Assert.Equal (Point.Empty, cm.Position);
 
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.Equal (new Point (70, 24), cm.Position);
         top.Draw ();
 
@@ -1132,11 +1153,18 @@ public class ContextMenuTests (ITestOutputHelper output)
     [AutoInitShutdown]
     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 ();
         Application.Begin (top);
-        cm.Show ();
+        cm.Show (menuItems);
         Assert.True (ContextMenu.IsShow);
         Application.Refresh ();
 
@@ -1167,7 +1195,10 @@ public class ContextMenuTests (ITestOutputHelper output)
         var cm = new ContextMenu
         {
             Position = new Point (5, 10),
-            MenuItems = new MenuBarItem (
+            UseSubMenusSingleFrame = true
+        };
+
+        var menuItems = new MenuBarItem (
                                          "Numbers",
                                          [
                                              new MenuItem ("One", "", null),
@@ -1184,19 +1215,11 @@ public class ContextMenuTests (ITestOutputHelper output)
                                                              ),
                                              new MenuItem ("Three", "", null)
                                          ]
-                                        ),
-            UseSubMenusSingleFrame = true
-        };
+                                        );
         Toplevel top = new ();
         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 ();
 
         TestHelpers.AssertDriverContentsWithFrameAre (
@@ -1254,8 +1277,10 @@ public class ContextMenuTests (ITestOutputHelper output)
     {
         var cm = new ContextMenu
         {
-            Position = new Point (5, 10),
-            MenuItems = new MenuBarItem (
+            Position = new Point (5, 10)
+        };
+
+        var menuItems = new MenuBarItem (
                                          "Numbers",
                                          [
                                              new MenuItem ("One", "", null),
@@ -1270,7 +1295,8 @@ public class ContextMenuTests (ITestOutputHelper output)
                                                                   new MenuItem ("Two-Menu 2", "", null)
                                                               ]
                                                              ),
-                                             new MenuBarItem ("Three",
+                                             new MenuBarItem (
+                                                              "Three",
                                                               [
                                                                   new MenuItem (
                                                                                 "Three-Menu 1",
@@ -1281,11 +1307,10 @@ public class ContextMenuTests (ITestOutputHelper output)
                                                               ]
                                                              )
                                          ]
-                                        )
-        };
+                                        );
         Toplevel top = new ();
         RunState rs = Application.Begin (top);
-        cm.Show ();
+        cm.Show (menuItems);
 
         Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);
         Application.Refresh ();
@@ -1356,17 +1381,6 @@ public class ContextMenuTests (ITestOutputHelper output)
         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]
     [AutoInitShutdown]
     public void Handling_TextField_With_Opened_ContextMenu_By_Mouse_HasFocus ()
@@ -1397,6 +1411,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.True (tf1.HasFocus);
         Assert.False (tf2.HasFocus);
         Assert.Equal (4, win.Subviews.Count);
+
         // The last context menu bar opened is always preserved
         Assert.NotNull (tf2.ContextMenu.MenuBar);
         Assert.Equal (win.Focused, tf1);
@@ -1408,6 +1423,7 @@ public class ContextMenuTests (ITestOutputHelper output)
         Assert.False (tf1.HasFocus);
         Assert.True (tf2.HasFocus);
         Assert.Equal (4, win.Subviews.Count);
+
         // The last context menu bar opened is always preserved
         Assert.NotNull (tf2.ContextMenu.MenuBar);
         Assert.Equal (win.Focused, tf2);
@@ -1417,4 +1433,505 @@ public class ContextMenuTests (ITestOutputHelper output)
         Application.End (rs);
         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 KeyBindings_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 ("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 ("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; }
+    }
+
+    [Fact]
+    [AutoInitShutdown]
+    public void HotKeys_Removed_On_Close_ContextMenu ()
+    {
+        var newFile = false;
+        var renameFile = false;
+        var deleteFile = false;
+
+        var cm = new ContextMenu ();
+
+        var menuItems = new MenuBarItem (
+                                         [
+                                             new ("_New File", string.Empty, New, null, null),
+                                             new ("_Rename File", string.Empty, Rename, null, null),
+                                             new ("_Delete File", string.Empty, Delete, null, null)
+                                         ]
+                                        );
+        var top = new Toplevel ();
+        Application.Begin (top);
+
+        Assert.Null (cm.MenuBar);
+        Assert.False (Application.OnKeyDown (Key.N.WithAlt));
+        Assert.False (Application.OnKeyDown (Key.R.WithAlt));
+        Assert.False (Application.OnKeyDown (Key.D.WithAlt));
+        Assert.False (newFile);
+        Assert.False (renameFile);
+        Assert.False (deleteFile);
+
+        cm.Show (menuItems);
+        Assert.True (cm.MenuBar!.IsMenuOpen);
+        Assert.False (cm.MenuBar!.KeyBindings.Bindings.ContainsKey (Key.N.WithAlt));
+        Assert.False (cm.MenuBar!.KeyBindings.Bindings.ContainsKey (Key.N.NoShift));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithAlt));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.NoShift));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.D.WithAlt));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.D.NoShift));
+        Assert.Single (Application.Current!.Subviews);
+        View [] menus = Application.Current!.Subviews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray ();
+        Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.N.WithAlt));
+        Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.N.NoShift));
+        Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.R.WithAlt));
+        Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.R.NoShift));
+        Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.D.WithAlt));
+        Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.D.NoShift));
+
+        Assert.True (Application.OnKeyDown (Key.N.WithAlt));
+        Assert.False (cm.MenuBar!.IsMenuOpen);
+        Application.MainLoop!.RunIteration ();
+        Assert.True (newFile);
+        cm.Show (menuItems);
+        Assert.True (Application.OnKeyDown (Key.R.WithAlt));
+        Assert.False (cm.MenuBar.IsMenuOpen);
+        Application.MainLoop!.RunIteration ();
+        Assert.True (renameFile);
+        cm.Show (menuItems);
+        Assert.True (Application.OnKeyDown (Key.D.WithAlt));
+        Assert.False (cm.MenuBar.IsMenuOpen);
+        Application.MainLoop!.RunIteration ();
+        Assert.True (deleteFile);
+
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithAlt));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.N.NoShift));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithAlt));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.NoShift));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.D.WithAlt));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.D.NoShift));
+
+        newFile = false;
+        renameFile = false;
+        deleteFile = false;
+        Assert.False (Application.OnKeyDown (Key.N.WithAlt));
+        Assert.False (Application.OnKeyDown (Key.R.WithAlt));
+        Assert.False (Application.OnKeyDown (Key.D.WithAlt));
+        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 HotKeys_With_ContextMenu_And_MenuBar ()
+    {
+        var newFile = false;
+        var renameFile = false;
+
+        var menuBar = new MenuBar
+        {
+            Menus =
+            [
+                new (
+                     "_File",
+                     new MenuItem []
+                     {
+                         new ("_New", string.Empty, New)
+                     })
+            ]
+        };
+        var cm = new ContextMenu ();
+
+        var menuItems = new MenuBarItem (
+                                         [
+                                             new MenuBarItem (
+                                                              "_Edit",
+                                                              new MenuItem []
+                                                              {
+                                                                  new ("_Rename File", string.Empty, Rename)
+                                                              }
+                                                             )
+                                         ]
+                                        );
+        var top = new Toplevel ();
+        top.Add (menuBar);
+        Application.Begin (top);
+
+        Assert.True (menuBar.KeyBindings.Bindings.ContainsKey (Key.F.WithAlt));
+        Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithAlt));
+        Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithAlt));
+        View [] menus = Application.Current!.Subviews.Where (v => v is Menu m && m.Host == menuBar).ToArray ();
+        Assert.Empty (menus);
+        Assert.Null (cm.MenuBar);
+
+        Assert.True (Application.OnKeyDown (Key.F.WithAlt));
+        Assert.True (menuBar.IsMenuOpen);
+        Assert.Equal (2, Application.Current!.Subviews.Count);
+        menus = Application.Current!.Subviews.Where (v => v is Menu m && m.Host == menuBar).ToArray ();
+        Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.N.WithAlt));
+        Assert.True (Application.OnKeyDown (Key.N.WithAlt));
+        Assert.False (menuBar.IsMenuOpen);
+        Assert.False (Application.OnKeyDown (Key.R.WithAlt));
+        Application.MainLoop!.RunIteration ();
+        Assert.True (newFile);
+        Assert.False (renameFile);
+
+        newFile = false;
+
+        cm.Show (menuItems);
+        Assert.True (menuBar.KeyBindings.Bindings.ContainsKey (Key.F.WithAlt));
+        Assert.True (menuBar.KeyBindings.Bindings.ContainsKey (Key.F.NoShift));
+        Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithAlt));
+        Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.N.NoShift));
+        Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.E.WithAlt));
+        Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.E.NoShift));
+        Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithAlt));
+        Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.R.NoShift));
+        Assert.True (cm.MenuBar!.IsMenuOpen);
+        Assert.False (cm.MenuBar!.KeyBindings.Bindings.ContainsKey (Key.F.WithAlt));
+        Assert.False (cm.MenuBar!.KeyBindings.Bindings.ContainsKey (Key.F.NoShift));
+        Assert.False (cm.MenuBar!.KeyBindings.Bindings.ContainsKey (Key.N.WithAlt));
+        Assert.False (cm.MenuBar!.KeyBindings.Bindings.ContainsKey (Key.N.NoShift));
+        Assert.False (cm.MenuBar!.KeyBindings.Bindings.ContainsKey (Key.E.WithAlt));
+        Assert.False (cm.MenuBar!.KeyBindings.Bindings.ContainsKey (Key.E.NoShift));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithAlt));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.NoShift));
+        Assert.Equal (3, Application.Current!.Subviews.Count);
+        menus = Application.Current!.Subviews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray ();
+        Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.E.WithAlt));
+        Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.E.NoShift));
+        Assert.True (menus [1].KeyBindings.Bindings.ContainsKey (Key.R.WithAlt));
+        Assert.True (menus [1].KeyBindings.Bindings.ContainsKey (Key.R.NoShift));
+        Assert.True (cm.MenuBar.IsMenuOpen);
+        Assert.True (Application.OnKeyDown (Key.F.WithAlt));
+        Assert.False (cm.MenuBar.IsMenuOpen);
+        Assert.True (Application.OnKeyDown (Key.N.WithAlt));
+        Application.MainLoop!.RunIteration ();
+        Assert.True (newFile);
+
+        cm.Show (menuItems);
+        Assert.True (cm.MenuBar.IsMenuOpen);
+        Assert.Equal (3, Application.Current!.Subviews.Count);
+        menus = Application.Current!.Subviews.Where (v => v is Menu m && m.Host == cm.MenuBar).ToArray ();
+        Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.E.WithAlt));
+        Assert.True (menus [0].KeyBindings.Bindings.ContainsKey (Key.E.NoShift));
+        Assert.False (menus [0].KeyBindings.Bindings.ContainsKey (Key.R.WithAlt));
+        Assert.False (menus [0].KeyBindings.Bindings.ContainsKey (Key.R.NoShift));
+        Assert.False (menus [1].KeyBindings.Bindings.ContainsKey (Key.E.WithAlt));
+        Assert.False (menus [1].KeyBindings.Bindings.ContainsKey (Key.E.NoShift));
+        Assert.True (menus [1].KeyBindings.Bindings.ContainsKey (Key.R.WithAlt));
+        Assert.True (menus [1].KeyBindings.Bindings.ContainsKey (Key.R.NoShift));
+        Assert.True (Application.OnKeyDown (Key.E.NoShift));
+        Assert.True (Application.OnKeyDown (Key.R.WithAlt));
+        Assert.False (cm.MenuBar.IsMenuOpen);
+        Application.MainLoop!.RunIteration ();
+        Assert.True (renameFile);
+
+        Assert.Single (Application.Current!.Subviews);
+        Assert.True (menuBar.KeyBindings.Bindings.ContainsKey (Key.F.WithAlt));
+        Assert.True (menuBar.KeyBindings.Bindings.ContainsKey (Key.F.NoShift));
+        Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.N.WithAlt));
+        Assert.False (menuBar.KeyBindings.Bindings.ContainsKey (Key.N.NoShift));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.E.WithAlt));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.E.NoShift));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.WithAlt));
+        Assert.False (cm.MenuBar.KeyBindings.Bindings.ContainsKey (Key.R.NoShift));
+
+        newFile = false;
+        renameFile = false;
+        Assert.True (Application.OnKeyDown (Key.F.WithAlt));
+        Assert.True (Application.OnKeyDown (Key.N.WithAlt));
+        Assert.False (Application.OnKeyDown (Key.R.WithAlt));
+        Application.MainLoop!.RunIteration ();
+        Assert.True (newFile);
+        Assert.False (renameFile);
+
+        top.Dispose ();
+
+        void New () { newFile = true; }
+
+        void Rename () { renameFile = true; }
+    }
+
+    [Fact]
+    [AutoInitShutdown]
+    public void Opened_MenuBar_Is_Closed_When_Another_MenuBar_Is_Opening_Also_By_HotKey ()
+    {
+        var menuBar = new MenuBar
+        {
+            Menus =
+            [
+                new (
+                     "_File",
+                     new MenuItem []
+                     {
+                         new ("_New", string.Empty, null)
+                     })
+            ]
+        };
+        var cm = new ContextMenu ();
+
+        var menuItems = new MenuBarItem (
+                                         [
+                                             new MenuBarItem (
+                                                              "_Edit",
+                                                              new MenuItem []
+                                                              {
+                                                                  new ("_Rename File", string.Empty, null)
+                                                              }
+                                                             )
+                                         ]
+                                        );
+        var top = new Toplevel ();
+        top.Add (menuBar);
+        Application.Begin (top);
+
+        Assert.True (Application.OnKeyDown (Key.F.WithAlt));
+        Assert.True (menuBar.IsMenuOpen);
+
+        cm.Show (menuItems);
+        Assert.False (menuBar.IsMenuOpen);
+        Assert.True (cm.MenuBar!.IsMenuOpen);
+
+        Assert.True (Application.OnKeyDown (Key.F.WithAlt));
+        Assert.True (menuBar.IsMenuOpen);
+        Assert.False (cm.MenuBar!.IsMenuOpen);
+
+        top.Dispose ();
+    }
+}

+ 3 - 3
UnitTests/Views/MenuBarTests.cs

@@ -15,10 +15,10 @@ public class MenuBarTests (ITestOutputHelper output)
         Assert.Equal ("n", menuBarItem.HotKey);
         Assert.Equal ("i", menuItem.HotKey);
         Assert.Empty (menuBar.Menus);
-        menuBarItem.AddMenuBarItem (menuItem);
+        menuBarItem.AddMenuBarItem (menuBar, menuItem);
         menuBar.Menus = [menuBarItem];
         Assert.Single (menuBar.Menus);
-        Assert.Single (menuBar.Menus [0].Children);
+        Assert.Single (menuBar.Menus [0].Children!);
         Assert.Contains (Key.N.WithAlt, menuBar.KeyBindings.Bindings);
         Assert.DoesNotContain (Key.I, menuBar.KeyBindings.Bindings);
 
@@ -2938,7 +2938,7 @@ Edit
 
         Assert.Contains (Key.A.WithCtrl, menuBar.KeyBindings.Bindings);
 
-        menuBar.Menus [0].Children [0].ShortcutKey = Key.B.WithCtrl;
+        menuBar.Menus [0].Children! [0].ShortcutKey = Key.B.WithCtrl;
 
         Assert.DoesNotContain (Key.A.WithCtrl, menuBar.KeyBindings.Bindings);
         Assert.Contains (Key.B.WithCtrl, menuBar.KeyBindings.Bindings);

+ 64 - 0
UnitTests/Views/MenuTests.cs

@@ -43,4 +43,68 @@ public class MenuTests
 
         void Run () { }
     }
+
+    [Fact]
+    public void MenuBarItem_SubMenu_Can_Return_Null ()
+    {
+        var menuItem = new MenuItem ();
+        var menuBarItem = new MenuBarItem ();
+        Assert.Null (menuBarItem.SubMenu (menuItem));
+    }
+
+    [Fact]
+    public void MenuBarItem_Constructors_Defaults ()
+    {
+        var menuBarItem = new MenuBarItem ();
+        Assert.Equal ("", menuBarItem.Title);
+        Assert.Equal ("", menuBarItem.Help);
+        Assert.Null (menuBarItem.Action);
+        Assert.Null (menuBarItem.CanExecute);
+        Assert.Null (menuBarItem.Parent);
+        Assert.Equal (Key.Empty, menuBarItem.ShortcutKey);
+        Assert.Equal ([], menuBarItem.Children);
+        Assert.False (menuBarItem.IsTopLevel);
+
+        menuBarItem = new MenuBarItem (null!, null!, Run, () => true, new ());
+        Assert.Equal ("", menuBarItem.Title);
+        Assert.Equal ("", menuBarItem.Help);
+        Assert.Equal (Run, menuBarItem.Action);
+        Assert.NotNull (menuBarItem.CanExecute);
+        Assert.NotNull (menuBarItem.Parent);
+        Assert.Equal (Key.Empty, menuBarItem.ShortcutKey);
+        Assert.Null (menuBarItem.Children);
+        Assert.False (menuBarItem.IsTopLevel);
+
+        menuBarItem = new MenuBarItem (null!, Array.Empty<MenuItem> (), new ());
+        Assert.Equal ("", menuBarItem.Title);
+        Assert.Equal ("", menuBarItem.Help);
+        Assert.Null (menuBarItem.Action);
+        Assert.Null (menuBarItem.CanExecute);
+        Assert.NotNull (menuBarItem.Parent);
+        Assert.Equal (Key.Empty, menuBarItem.ShortcutKey);
+        Assert.Equal ([], menuBarItem.Children);
+        Assert.False (menuBarItem.IsTopLevel);
+
+        menuBarItem = new MenuBarItem (null!, new List<MenuItem []> (), new ());
+        Assert.Equal ("", menuBarItem.Title);
+        Assert.Equal ("", menuBarItem.Help);
+        Assert.Null (menuBarItem.Action);
+        Assert.Null (menuBarItem.CanExecute);
+        Assert.NotNull (menuBarItem.Parent);
+        Assert.Equal (Key.Empty, menuBarItem.ShortcutKey);
+        Assert.Equal ([], menuBarItem.Children);
+        Assert.False (menuBarItem.IsTopLevel);
+
+        menuBarItem = new MenuBarItem ([]);
+        Assert.Equal ("", menuBarItem.Title);
+        Assert.Equal ("", menuBarItem.Help);
+        Assert.Null (menuBarItem.Action);
+        Assert.Null (menuBarItem.CanExecute);
+        Assert.Null (menuBarItem.Parent);
+        Assert.Equal (Key.Empty, menuBarItem.ShortcutKey);
+        Assert.Equal ([], menuBarItem.Children);
+        Assert.False (menuBarItem.IsTopLevel);
+
+        void Run () { }
+    }
 }