diff --git a/src/Uno.Toolkit.RuntimeTests/Tests/TabBarTests.cs b/src/Uno.Toolkit.RuntimeTests/Tests/TabBarTests.cs index 217ecc9fe..e151c264a 100644 --- a/src/Uno.Toolkit.RuntimeTests/Tests/TabBarTests.cs +++ b/src/Uno.Toolkit.RuntimeTests/Tests/TabBarTests.cs @@ -318,8 +318,13 @@ public async Task Verify_Indicator_Display_On_Selection() SUT.SelectedIndex = i; await UnitTestsUIContentHelper.WaitForIdle(); + // When using an `ItemTemplate` with a `TabBarItem`, the container will be a `ContentPresenter` that wraps the `TabBarItem`. + // In that case, to access the `ContentPresenter` from a `TabBarItem`, you must first call `ContainerFromItem`. + // Afterward, pass the resulting `ContentPresenter` as a parameter to `GetInnerContainer`. + // See https://github.com/unoplatform/uno.toolkit.ui/pull/1261#discussion_r1799794554 for reference. var container = SUT.ContainerFromItem(SUT.SelectedItem); var selectedItem = SUT.GetInnerContainer(container); + Assert.IsNotNull(selectedItem); var renderer = await SUT.TakeScreenshot(); @@ -428,7 +433,7 @@ public async Task Verify_SelectedIndex_Not_Set_Unnecessarily() } [TestMethod] - public async Task Verify_ItemTemplated_Has_No_Nested_TabBarItem() + public async Task Verify_ItemTemplate_Has_No_Nested_TabBarItem() { var source = new[] { @@ -437,11 +442,11 @@ public async Task Verify_ItemTemplated_Has_No_Nested_TabBarItem() new TestRecord("True", true) }; - var dt = XamlHelper.LoadXaml(@" - - - - "); + var dt = XamlHelper.LoadXaml(""" + + + + """); var SUT = new TabBar { @@ -453,17 +458,20 @@ public async Task Verify_ItemTemplated_Has_No_Nested_TabBarItem() await UnitTestUIContentHelperEx.SetContentAndWait(SUT); - // Ensure the container is a `ContentPresenter` and not a `TabBarItem` + // When using an `ItemTemplate` with a `TabBarItem`, the container will be a `ContentPresenter` that wraps the `TabBarItem`. + // In that case, to access the `ContentPresenter` from a `TabBarItem`, you must first call `ContainerFromItem`. + // Afterward, pass the resulting `ContentPresenter` as a parameter to `GetInnerContainer`. + // See https://github.com/unoplatform/uno.toolkit.ui/pull/1261#discussion_r1799794554 for reference. + var container = SUT.ContainerFromItem(SUT.SelectedItem); Assert.IsInstanceOfType(container, typeof(ContentPresenter)); - // Ensure the inner container is a `TabBarItem` var selectedItem = SUT.GetInnerContainer(container); Assert.IsInstanceOfType(selectedItem, typeof(TabBarItem)); } [TestMethod] - public async Task Verify_ItemTemplated_Disabled_Not_Selectable() + public async Task Verify_ItemTemplate_Disabled_Not_Selectable() { var source = new[] { @@ -472,11 +480,11 @@ public async Task Verify_ItemTemplated_Disabled_Not_Selectable() new TestRecord("True", true) }; - var dt = XamlHelper.LoadXaml(@" - - - - "); + var dt = XamlHelper.LoadXaml(""" + + + + """); var SUT = new TabBar { diff --git a/src/Uno.Toolkit.UI/Controls/TabBar/TabBar.cs b/src/Uno.Toolkit.UI/Controls/TabBar/TabBar.cs index df31432ac..165458c9b 100644 --- a/src/Uno.Toolkit.UI/Controls/TabBar/TabBar.cs +++ b/src/Uno.Toolkit.UI/Controls/TabBar/TabBar.cs @@ -148,6 +148,10 @@ e is IVectorChangedEventArgs iVCE { var item = Items[(int)iVCE.Index]; + // When using an `ItemTemplate` with a `TabBarItem`, the container will be a `ContentPresenter` that wraps the `TabBarItem`. + // In that case, to access the `ContentPresenter` from a `TabBarItem`, you must first call `ContainerFromItem`. + // Afterward, pass the resulting `ContentPresenter` as a parameter to `GetInnerContainer`. + // See https://github.com/unoplatform/uno.toolkit.ui/pull/1261#discussion_r1799794554 for reference. if (GetInnerContainer(item as DependencyObject) is { IsSelected: true } selected) { SelectedItem = selected; @@ -355,6 +359,10 @@ private void SynchronizeSelection(TabBarItem? item) var containers = this.GetItemContainers(); foreach (var container in containers) { + // When using an `ItemTemplate` with a `TabBarItem`, the container will be a `ContentPresenter` that wraps the `TabBarItem`. + // In that case, to access the `ContentPresenter` from a `TabBarItem`, you must first call `ContainerFromItem`. + // Afterward, pass the resulting `ContentPresenter` as a parameter to `GetInnerContainer`. + // See https://github.com/unoplatform/uno.toolkit.ui/pull/1261#discussion_r1799794554 for reference. var tbi = GetInnerContainer(container); if (tbi is not { }) continue; @@ -407,6 +415,10 @@ private void RaiseSelectionChangedEvent(object? prevItem, object? nextItem) SelectionChanged?.Invoke(this, eventArgs); } + // When using an `ItemTemplate` with a `TabBarItem`, the container will be a `ContentPresenter` that wraps the `TabBarItem`. + // In that case, to access the `ContentPresenter` from a `TabBarItem`, you must first call `ContainerFromItem`. + // Afterward, pass the resulting `ContentPresenter` as a parameter to this method. + // See https://github.com/unoplatform/uno.toolkit.ui/pull/1261#discussion_r1799794554 for reference. internal TabBarItem? GetInnerContainer(DependencyObject? container) { if (IsUsingOwnContainerAsTemplateRoot && container is ContentPresenter cp) diff --git a/src/Uno.Toolkit.UI/Controls/TabBar/TabBarSelectionIndicatorPresenter.cs b/src/Uno.Toolkit.UI/Controls/TabBar/TabBarSelectionIndicatorPresenter.cs index b8a300444..ff4c3d228 100644 --- a/src/Uno.Toolkit.UI/Controls/TabBar/TabBarSelectionIndicatorPresenter.cs +++ b/src/Uno.Toolkit.UI/Controls/TabBar/TabBarSelectionIndicatorPresenter.cs @@ -224,7 +224,11 @@ private void UpdateSelectionIndicatorMaxSize() if (Owner is { } tabBar && GetSelectionIndicator() is { } indicator) { - var tabBarItems =tabBar.GetItemContainers() + var tabBarItems = tabBar.GetItemContainers() + // When using an `ItemTemplate` with a `TabBarItem`, the container will be a `ContentPresenter` that wraps the `TabBarItem`. + // In that case, to access the `ContentPresenter` from a `TabBarItem`, you must first call `ContainerFromItem`. + // Afterward, pass the resulting `ContentPresenter` as a parameter to `GetInnerContainer`. + // See https://github.com/unoplatform/uno.toolkit.ui/pull/1261#discussion_r1799794554 for reference. .Select(tabBar.GetInnerContainer) .OfType(); var visibleItems = tabBarItems.Count(x => x.Visibility == Visibility.Visible);