diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs index 32c8a6b7a12b..24ceab4a95cf 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs @@ -149,6 +149,30 @@ public override AView OnCreateView(LayoutInflater inflater, ViewGroup container, return _rootView = root; } + void OnShellContentPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + if (e.PropertyName == ShellContent.TitleProperty.PropertyName && sender is ShellContent shellContent) + { + UpdateTabTitle(shellContent); + } + } + + void UpdateTabTitle(ShellContent shellContent) + { + if (_tablayout == null || SectionController.GetItems().Count == 0) + return; + + int index = SectionController.GetItems().IndexOf(shellContent); + if (index >= 0) + { + var tab = _tablayout.GetTabAt(index); + if (tab != null) + { + tab.SetText(new string(shellContent.Title)); + } + } + } + void OnTabLayoutChange(object sender, AView.LayoutChangeEventArgs e) { if (_disposed) @@ -327,6 +351,10 @@ void HookEvents() SectionController.ItemsCollectionChanged += OnItemsCollectionChanged; ((IShellController)_shellContext.Shell).AddAppearanceObserver(this, ShellSection); ShellSection.PropertyChanged += OnShellItemPropertyChanged; + foreach (var item in SectionController.GetItems()) + { + item.PropertyChanged += OnShellContentPropertyChanged; + } } void UnhookEvents() @@ -334,6 +362,10 @@ void UnhookEvents() SectionController.ItemsCollectionChanged -= OnItemsCollectionChanged; ((IShellController)_shellContext?.Shell)?.RemoveAppearanceObserver(this); ShellSection.PropertyChanged -= OnShellItemPropertyChanged; + foreach (var item in SectionController.GetItems()) + { + item.PropertyChanged -= OnShellContentPropertyChanged; + } } protected virtual void OnPageSelected(int position) diff --git a/src/Controls/src/Core/Handlers/Shell/ShellContentHandler.Windows.cs b/src/Controls/src/Core/Handlers/Shell/ShellContentHandler.Windows.cs index 776e69c38373..3ae9eb434f34 100644 --- a/src/Controls/src/Core/Handlers/Shell/ShellContentHandler.Windows.cs +++ b/src/Controls/src/Core/Handlers/Shell/ShellContentHandler.Windows.cs @@ -7,7 +7,7 @@ namespace Microsoft.Maui.Controls.Handlers public partial class ShellContentHandler : ElementHandler { public static PropertyMapper Mapper = - new PropertyMapper(ElementMapper); + new PropertyMapper(ElementMapper) { [nameof(ShellContent.Title)] = MapTitle }; public static CommandMapper CommandMapper = new CommandMapper(ElementCommandMapper); @@ -16,6 +16,14 @@ public ShellContentHandler() : base(Mapper, CommandMapper) { } + internal static void MapTitle(ShellContentHandler handler, ShellContent item) + { + var shellSection = item.Parent as ShellSection; + var shellItem = shellSection?.Parent as ShellItem; + var shellItemHandler = shellItem?.Handler as ShellItemHandler; + shellItemHandler?.UpdateTitle(); + } + protected override FrameworkElement CreatePlatformElement() { return (VirtualView as IShellContentController).GetOrCreateContent().ToPlatform(MauiContext); diff --git a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt index 7dc5c58110bf..815c92006af7 100644 --- a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt @@ -1 +1 @@ -#nullable enable +#nullable enable \ No newline at end of file diff --git a/src/Controls/src/Core/Shell/BaseShellItem.cs b/src/Controls/src/Core/Shell/BaseShellItem.cs index c1593aafcf2f..25aa1605e65c 100644 --- a/src/Controls/src/Core/Shell/BaseShellItem.cs +++ b/src/Controls/src/Core/Shell/BaseShellItem.cs @@ -51,7 +51,7 @@ public class BaseShellItem : NavigableElement, IPropertyPropagationController, I /// Bindable property for . public static readonly BindableProperty TitleProperty = - BindableProperty.Create(nameof(Title), typeof(string), typeof(BaseShellItem), null, BindingMode.OneTime, propertyChanged: OnTitlePropertyChanged); + BindableProperty.Create(nameof(Title), typeof(string), typeof(BaseShellItem), null, BindingMode.TwoWay, propertyChanged: OnTitlePropertyChanged); /// Bindable property for . public static readonly BindableProperty IsVisibleProperty = diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ChangeShellContentTitle.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ChangeShellContentTitle.png new file mode 100644 index 000000000000..ab55034b484c Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ChangeShellContentTitle.png differ diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue7453.xaml b/src/Controls/tests/TestCases.HostApp/Issues/Issue7453.xaml new file mode 100644 index 000000000000..487e80aa0e6f --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue7453.xaml @@ -0,0 +1,29 @@ + + + + + + + + + +