Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,22 @@ protected virtual void OnItemsCollectionChanged(object sender, NotifyCollectionC
adapter.OnItemsCollectionChanged(sender, e);
SafeNotifyDataSetChanged();
}

if (e.OldItems is not null)
{
foreach (ShellContent item in e.OldItems)
{
item.PropertyChanged -= OnShellContentPropertyChanged;
}
}

if (e.NewItems is not null)
{
foreach (ShellContent item in e.NewItems)
{
item.PropertyChanged += OnShellContentPropertyChanged;
}
}
}

void SafeNotifyDataSetChanged(int iteration = 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Microsoft.Maui.Controls.Handlers
public partial class ShellContentHandler : ElementHandler<ShellContent, FrameworkElement>
{
public static PropertyMapper<ShellContent, ShellContentHandler> Mapper =
new PropertyMapper<ShellContent, ShellContentHandler>(ElementMapper) { [nameof(ShellContent.Title)] = MapTitle };
new PropertyMapper<ShellContent, ShellContentHandler>(ElementMapper);

public static CommandMapper<ShellContent, ShellContentHandler> CommandMapper =
new CommandMapper<ShellContent, ShellContentHandler>(ElementCommandMapper);
Expand All @@ -16,14 +16,6 @@ public ShellContentHandler() : base(Mapper, CommandMapper)
{
}

internal static void MapTitle(ShellContentHandler handler, ShellContent item)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mapper was not invoking the method never?

Copy link
Copy Markdown
Contributor Author

@devanathan-vaithiyanathan devanathan-vaithiyanathan Feb 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jsuarezruiz , Previously, the MapTitle method was only called when changing the title within the same ShellContent page, preventing title changes between different ShellContent pages. Since other platforms support this behavior, I removed MapTitle and applied the fix to the ShellSection. With this change, the title now updates correctly during the initial load, at runtime when adding ShellContent, and when changing title between ShellContent pages, ensuring consistency across all platforms

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One difference between Windows and the other platforms is that Windows is the only platform that has the handlers correctly built against shell. So, I think we can use that to our advantage a bit here.

Like we could move all this code to an extention method and then on the shellcontent if the Title property changes we just call that extention method

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PureWeen, Should we add the extension only for Windows ShellContent title changes, or should we consider applying this extension to other platforms as well

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will only currently apply to windows because of how the handlers are setup on Windows.

If it's straight forward to apply it to other platforms then you can try that, but, if it's not straight forward than just windows is fine

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PureWeen, Since applying this to other platforms is not straightforward, I have moved the Windows-specific changes to an extension method for now

{
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Specialized;
using System.Text;
using Microsoft.Maui.Controls.Internals;
using Microsoft.Maui.Controls.Platform;
using WFrame = Microsoft.UI.Xaml.Controls.Frame;


Expand Down Expand Up @@ -61,6 +62,14 @@ public override void SetVirtualView(Maui.IElement view)
{
shell.RemoveAppearanceObserver(this);
}

foreach (var item in _shellSection.Items)
{
if (item is ShellContent shellContent)
{
shellContent.PropertyChanged -= OnShellContentPropertyChanged;
}
}
_lastShell = null;
}

Expand Down Expand Up @@ -93,6 +102,14 @@ public override void SetVirtualView(Maui.IElement view)
_lastShell = new WeakReference(shell);
shell.AddAppearanceObserver(this, _shellSection);
}

foreach (var item in _shellSection.Items)
{
if (item is ShellContent shellContent)
{
shellContent.PropertyChanged += OnShellContentPropertyChanged;
}
}
}
}

Expand All @@ -110,6 +127,33 @@ void OnItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e
{
shellItemHandler.MapMenuItems();
}

if (e.OldItems is not null)
{
foreach (ShellContent item in e.OldItems)
{
item.PropertyChanged -= OnShellContentPropertyChanged;
}
}

if (e.NewItems is not null)
{
foreach (ShellContent item in e.NewItems)
{
item.PropertyChanged += OnShellContentPropertyChanged;
}
}
}

void OnShellContentPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (sender is not ShellContent shellContent)
return;

if (e.PropertyName == nameof(ShellContent.Title))
{
shellContent.UpdateTitle();
}
}

void SyncNavigationStack(bool animated, NavigationRequestedEventArgs? e)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Microsoft.Maui.Controls.Handlers;

namespace Microsoft.Maui.Controls.Platform
{
internal static class ShellContentExtension
{
internal static void UpdateTitle(this ShellContent shellContent)
{
if (shellContent.Parent is ShellSection shellSection && shellSection.Parent is ShellItem shellItem && shellItem.Handler is ShellItemHandler shellItemHandler)
{
shellItemHandler.UpdateTitle();
}
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Maui.Controls.Sample.Issues;

[Issue(IssueTracker.Github, 26049, "[iOS] Fix ShellContent Title Does Not Update at Runtime", PlatformAffected.iOS | PlatformAffected.macOS)]
[Issue(IssueTracker.Github, 26049, "Fix ShellContent Title Does Not Update at Runtime", PlatformAffected.All)]
public partial class Issue26049 : Shell
{
ShellContent _dynamicShellContent;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#if TEST_FAILS_ON_ANDROID && TEST_FAILS_ON_WINDOWS //More information - https://github.com/dotnet/maui/issues/27494
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;
Expand All @@ -11,36 +10,47 @@ public Issue26049(TestDevice device) : base(device)
{
}

public override string Issue => "[iOS] Fix ShellContent Title Does Not Update at Runtime";
public override string Issue => "Fix ShellContent Title Does Not Update at Runtime";

[Test, Order(1)]
[Category(UITestCategories.Shell)]
public void VerifyFirstShellContentTitle()
{
App.WaitForElement("ChangeShellContentTitle");
App.Click("ChangeShellContentTitle");
TabNavigationViewItemIfWindows();
VerifyScreenshot();
}

[Test, Order(2)]
[Category(UITestCategories.Shell)]
public void VerifyNewlyAddedShellContentTitle()
{
TabNavigationViewItemIfWindows();
App.WaitForElement("AddShellContent");
App.Click("AddShellContent");
App.Click("UpdateNewShellContentTitle");
TabNavigationViewItemIfWindows();
VerifyScreenshot();
}

[Test, Order(3)]
[Category(UITestCategories.Shell)]
public void VerifyExistingTabTitle()
{
TabNavigationViewItemIfWindows();
App.WaitForElement("RemoveShellContent");
App.Click("RemoveShellContent");
App.Click("UpdateThirdTabTitle");
TabNavigationViewItemIfWindows();
VerifyScreenshot();
}

void TabNavigationViewItemIfWindows()
{
#if WINDOWS
App.Tap("navViewItem");
#endif
}
}
}
#endif
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading