diff --git a/src/Controls/src/Core/Handlers/Shell/ShellItemHandler.Windows.cs b/src/Controls/src/Core/Handlers/Shell/ShellItemHandler.Windows.cs index b60e49ca4126..c1f0c2f021ce 100644 --- a/src/Controls/src/Core/Handlers/Shell/ShellItemHandler.Windows.cs +++ b/src/Controls/src/Core/Handlers/Shell/ShellItemHandler.Windows.cs @@ -151,7 +151,7 @@ private void OnNavigationTabChanged(NavigationView sender, NavigationViewSelecti } } - void MapMenuItems() + internal void MapMenuItems() { IShellItemController shellItemController = VirtualView; var items = new List(); diff --git a/src/Controls/src/Core/Handlers/Shell/ShellSectionHandler.Windows.cs b/src/Controls/src/Core/Handlers/Shell/ShellSectionHandler.Windows.cs index 143684a7c3c0..5c930f718b76 100644 --- a/src/Controls/src/Core/Handlers/Shell/ShellSectionHandler.Windows.cs +++ b/src/Controls/src/Core/Handlers/Shell/ShellSectionHandler.Windows.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.Specialized; using System.Text; using Microsoft.Maui.Controls.Internals; using WFrame = Microsoft.UI.Xaml.Controls.Frame; @@ -54,6 +55,8 @@ public override void SetVirtualView(Maui.IElement view) { ((IShellSectionController)_shellSection).NavigationRequested -= OnNavigationRequested; + ((IShellSectionController)_shellSection).ItemsCollectionChanged -= OnItemsCollectionChanged; + if (_lastShell?.Target is IShellController shell) { shell.RemoveAppearanceObserver(this); @@ -82,6 +85,8 @@ public override void SetVirtualView(Maui.IElement view) { ((IShellSectionController)_shellSection).NavigationRequested += OnNavigationRequested; + ((IShellSectionController)_shellSection).ItemsCollectionChanged += OnItemsCollectionChanged; + var shell = _shellSection.FindParentOfType() as IShellController; if (shell != null) { @@ -96,6 +101,17 @@ void OnNavigationRequested(object? sender, NavigationRequestedEventArgs e) SyncNavigationStack(e.Animated, e); } + void OnItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) + { + if (_shellSection is null) + return; + + if (_shellSection.Parent is ShellItem shellItem && shellItem.Handler is ShellItemHandler shellItemHandler) + { + shellItemHandler.MapMenuItems(); + } + } + void SyncNavigationStack(bool animated, NavigationRequestedEventArgs? e) { // Current Item might transition to null while visibility is adjusting on shell diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/DynamicTabSectionVisibility.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/DynamicTabSectionVisibility.png new file mode 100644 index 000000000000..b606e64cfbee Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/DynamicTabSectionVisibility.png differ diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue25913.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue25913.cs new file mode 100644 index 000000000000..8e4a450e4242 --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue25913.cs @@ -0,0 +1,99 @@ +namespace Maui.Controls.Sample.Issues +{ + [Issue(IssueTracker.Github, 25913, "Top Tab Visibility Changes Not Reflected Until Tab Switch", PlatformAffected.UWP)] + public partial class Issue25913 : Shell + { + public Issue25913() + { + InitializeShell(); + } + + private void InitializeShell() + { + var tabBar = new TabBar(); + + var tab1 = new Tab { Title = "Tab 1" }; + var topTab1Content = new ContentPage + { + Title = "TopTab1", + Content = CreateControlPanel() + }; + + var topTab2Content = new ContentPage + { + Title = "TopTab2", + Content = CreateControlPanel() + }; + + var topTab3Content = new ContentPage + { + Title = "TopTab3", + Content = CreateControlPanel() + }; + + tab1.Items.Add(topTab1Content); + tab1.Items.Add(topTab2Content); + tab1.Items.Add(topTab3Content); + + var tab2 = new Tab + { + Title = "Tab 2", + Items = + { + new ShellContent + { + Content = new ContentPage + { + Content = new Label { Text = "Tab 2 Content" } + } + } + } + }; + + var tab3 = new Tab + { + Title = "Tab 3", + Items = + { + new ShellContent + { + Content = new ContentPage + { + Content = new Label { Text = "Tab 3 Content" } + } + } + } + }; + + tabBar.Items.Add(tab1); + tabBar.Items.Add(tab2); + tabBar.Items.Add(tab3); + + Items.Add(tabBar); + } + + private View CreateControlPanel() + { + return new ScrollView + { + Content = new StackLayout + { + Spacing = 10, + Padding = new Thickness(20), + Children = + { + new Button + { + Text = "Hide Top Tab 3", + Command = new Command(() => + { + Items[0].Items[0].Items[2].IsVisible = false; + }), + AutomationId = "HideTop3" + } + } + } + }; + } + } +} \ No newline at end of file diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue25913.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue25913.cs new file mode 100644 index 000000000000..960a99fb9751 --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue25913.cs @@ -0,0 +1,27 @@ +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues +{ + public class Issue25913 : _IssuesUITest + { + public override string Issue => "Top Tab Visibility Changes Not Reflected Until Tab Switch"; + + public Issue25913(TestDevice device) + : base(device) + { } + + [Test] + [Category(UITestCategories.Shell)] + public void DynamicTabSectionVisibility() + { + App.WaitForElement("HideTop3"); + App.Tap("HideTop3"); +#if WINDOWS + App.Tap("Tab 1"); +#endif + VerifyScreenshot(); + } + } +} diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/DynamicTabSectionVisibility.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/DynamicTabSectionVisibility.png new file mode 100644 index 000000000000..adf44b2603e6 Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/DynamicTabSectionVisibility.png differ diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/DynamicTabSectionVisibility.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/DynamicTabSectionVisibility.png new file mode 100644 index 000000000000..63ae6d7460dc Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/DynamicTabSectionVisibility.png differ