diff --git a/doc/controls/NavigationBar.md b/doc/controls/NavigationBar.md index a07306114..38cc507f9 100644 --- a/doc/controls/NavigationBar.md +++ b/doc/controls/NavigationBar.md @@ -285,12 +285,23 @@ The height is fixed and cannot be changed. ### MainCommandMode -The `NavigationBar` has a property named `MainCommandMode` that can be set to either: +The `NavigationBar` has a property named `MainCommandMode` that can be set to: 1. `MainCommandMode.Back` (default) -1. `MainCommandMode.Action` +2. `MainCommandMode.Action` +3. `MainCommandMode.Hidden` -`MainCommandMode` should be set to `Action` when the `MainCommand` is being used for anything other than backward navigation, such as displaying a burger menu or displaying a prompt to the user before the navigation occurs. +#### Back Mode (Default) + +When set to `Back`, the `MainCommand` will be used for backward navigation. The button will automatically appear when the Frame has items in its back stack and will trigger navigation back when clicked. + +#### Action Mode + +`MainCommandMode` should be set to `Action` when the `MainCommand` is being used for anything other than backward navigation, such as displaying a burger menu or displaying a prompt to the user before the navigation occurs. In this mode, the `MainCommand` remains visible and its click behavior must be handled by setting the `Command` property or handling the `Click` event. + +#### Hidden Mode + +When set to `Hidden`, the `MainCommand` will be completely hidden from view regardless of the Frame's back stack state. This is useful when you want to hide the main command entirely, such as on a home/landing page or when implementing custom navigation logic that doesn't require a visible back button. ### MainCommand diff --git a/src/Uno.Toolkit.RuntimeTests/Tests/NavigationBarTests.cs b/src/Uno.Toolkit.RuntimeTests/Tests/NavigationBarTests.cs index 09a989016..33421b934 100644 --- a/src/Uno.Toolkit.RuntimeTests/Tests/NavigationBarTests.cs +++ b/src/Uno.Toolkit.RuntimeTests/Tests/NavigationBarTests.cs @@ -253,6 +253,62 @@ public async Task MainCommand_In_Popup_With_Page_With_BackStack(MainCommandMode } } + [TestMethod] + public async Task MainCommand_Hidden_Mode_Hides_Button() + { + var mainCommand = new AppBarButton(); + var navigationBar = new NavigationBar + { + Content = "Title", + MainCommandMode = MainCommandMode.Hidden, + MainCommand = mainCommand + }; + var content = new Grid { Children = { navigationBar } }; + + await UnitTestUIContentHelperEx.SetContentAndWait(content); + + Assert.AreEqual(Visibility.Collapsed, mainCommand.Visibility, "MainCommand should be collapsed when MainCommandMode is Hidden"); + Assert.IsFalse(navigationBar.TryPerformMainCommand(), "TryPerformMainCommand should return false when MainCommandMode is Hidden"); + } + + [TestMethod] + public async Task MainCommand_Hidden_Mode_In_Frame_Stays_Hidden() + { + var frame = new Frame() { Width = 400, Height = 400 }; + await UnitTestUIContentHelperEx.SetContentAndWait(frame); + + frame.Navigate(typeof(NavBarFirstPage)); + await UnitTestsUIContentHelper.WaitForIdle(); + + var firstPage = frame.Content as NavBarFirstPage; + var firstNavBar = firstPage?.FindChild(); + + if (firstNavBar != null) + { + firstNavBar.MainCommandMode = MainCommandMode.Hidden; + await UnitTestsUIContentHelper.WaitForIdle(); + + // Navigate to a second page to create backstack + frame.Navigate(typeof(NavBarSecondPage)); + await UnitTestsUIContentHelper.WaitForIdle(); + + var secondPage = frame.Content as NavBarSecondPage; + var secondNavBar = secondPage?.FindChild(); + + if (secondNavBar != null) + { + secondNavBar.MainCommandMode = MainCommandMode.Hidden; + await UnitTestsUIContentHelper.WaitForIdle(); + + // Even with backstack, Hidden mode should keep button collapsed + Assert.AreEqual(Visibility.Collapsed, secondNavBar.MainCommand?.Visibility, + "MainCommand should remain collapsed in Hidden mode even with backstack"); + Assert.IsFalse(secondNavBar.TryPerformMainCommand(), + "TryPerformMainCommand should return false in Hidden mode"); + } + } + } + #if __ANDROID__ || __IOS__ [TestMethod] public async Task NavigationBar_Dynamic_Background() diff --git a/src/Uno.Toolkit.UI/Controls/NavigationBar/LeftCommandMode.cs b/src/Uno.Toolkit.UI/Controls/NavigationBar/LeftCommandMode.cs index c782d190c..aebc490e7 100644 --- a/src/Uno.Toolkit.UI/Controls/NavigationBar/LeftCommandMode.cs +++ b/src/Uno.Toolkit.UI/Controls/NavigationBar/LeftCommandMode.cs @@ -10,5 +10,6 @@ public enum MainCommandMode { Back, Action, + Hidden, } } diff --git a/src/Uno.Toolkit.UI/Controls/NavigationBar/NavigationBar.cs b/src/Uno.Toolkit.UI/Controls/NavigationBar/NavigationBar.cs index 02aea731d..3384d85a2 100644 --- a/src/Uno.Toolkit.UI/Controls/NavigationBar/NavigationBar.cs +++ b/src/Uno.Toolkit.UI/Controls/NavigationBar/NavigationBar.cs @@ -97,6 +97,8 @@ protected override void OnApplyTemplate() internal bool TryPerformMainCommand() { + // Only perform back navigation when MainCommandMode is Back + // Action and Hidden modes should not perform automatic navigation if (MainCommandMode != MainCommandMode.Back) { return false; @@ -198,13 +200,24 @@ private void OnBackStackChanged(object? sender, NotifyCollectionChangedEventArgs internal void UpdateMainCommandVisibility() { + if (MainCommand is not { } mainCommand) + { + return; + } + + if (MainCommandMode == MainCommandMode.Hidden) + { + mainCommand.Visibility = Visibility.Collapsed; + return; + } + if (MainCommandMode != MainCommandMode.Back) { return; } var buttonVisibility = Visibility.Collapsed; - if (GetPage() is { } page && MainCommand is { } mainCommand) + if (GetPage() is { } page) { if (page.Frame?.CanGoBack ?? false) {