diff --git a/src/Controls/src/Core/Shell/Shell.cs b/src/Controls/src/Core/Shell/Shell.cs
index 3e59dde42b40..694298a19950 100644
--- a/src/Controls/src/Core/Shell/Shell.cs
+++ b/src/Controls/src/Core/Shell/Shell.cs
@@ -1663,6 +1663,17 @@ static void OnCurrentItemChanged(BindableObject bindable, object oldValue, objec
shell.ShellController.AppearanceChanged(shell, false);
shell.ShellController.UpdateCurrentState(ShellNavigationSource.ShellItemChanged);
+ // If the new ShellItem is a FlyoutItem or a ShellGroupItem, we need to update the QueryAttributes
+ var existing = (ShellRouteParameters)shell.CurrentContent?.GetValue(ShellContent.QueryAttributesProperty);
+ bool isRelevantShellItem = shell.CurrentItem is FlyoutItem || shell.CurrentItem is ShellGroupItem;
+ bool isNewValueDifferent = oldValue is not null && newValue is not null && existing is null;
+
+ if (isNewValueDifferent && isRelevantShellItem)
+ {
+ ShellContent currentShellContent = shell.CurrentItem.CurrentItem?.CurrentItem;
+ currentShellContent?.SetValue(ShellContent.QueryAttributesProperty, new ShellRouteParameters());
+ }
+
if (shell.CurrentItem?.CurrentItem != null)
shell.ShellController.AppearanceChanged(shell.CurrentItem.CurrentItem, false);
}
diff --git a/src/Controls/src/Core/Shell/ShellItem.cs b/src/Controls/src/Core/Shell/ShellItem.cs
index 494bb5c3a7c3..27618634b027 100644
--- a/src/Controls/src/Core/Shell/ShellItem.cs
+++ b/src/Controls/src/Core/Shell/ShellItem.cs
@@ -300,6 +300,14 @@ static void OnCurrentItemChanged(BindableObject bindable, object oldValue, objec
shell.UpdateCurrentState(ShellNavigationSource.ShellSectionChanged);
}
+ //For TabBarItems itemchanged will fall in ShellItem class , we need to set the QueryAttributesProperty here
+ ShellContent currentShellContent = shellItem.CurrentItem?.CurrentItem;
+ var existing = (ShellRouteParameters)currentShellContent?.GetValue(ShellContent.QueryAttributesProperty);
+ if (oldValue is not null && newValue is not null && existing is null)
+ {
+ currentShellContent?.SetValue(ShellContent.QueryAttributesProperty, new ShellRouteParameters());
+ }
+
shellItem.SendStructureChanged();
if (shellItem.IsVisibleItem)
diff --git a/src/Controls/src/Core/Shell/ShellNavigationManager.cs b/src/Controls/src/Core/Shell/ShellNavigationManager.cs
index 9329bf1a5f11..009851a7afa6 100644
--- a/src/Controls/src/Core/Shell/ShellNavigationManager.cs
+++ b/src/Controls/src/Core/Shell/ShellNavigationManager.cs
@@ -309,7 +309,16 @@ public static void ApplyQueryAttributes(Element element, ShellRouteParameters qu
if (baseShellItem is ShellContent)
- baseShellItem.ApplyQueryAttributes(MergeData(element, filteredQuery, isPopping));
+ {
+ var mergedData = MergeData(element, filteredQuery, isPopping);
+
+ //if we are pop or navigating back, we need to apply the query attributes to the ShellContent
+ if (isPopping)
+ {
+ element.SetValue(ShellContent.QueryAttributesProperty, mergedData);
+ }
+ baseShellItem.ApplyQueryAttributes(mergedData);
+ }
else if (isLastItem)
element.SetValue(ShellContent.QueryAttributesProperty, MergeData(element, query, isPopping));
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue13537.xaml b/src/Controls/tests/TestCases.HostApp/Issues/Issue13537.xaml
new file mode 100644
index 000000000000..2e8f5f764fef
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue13537.xaml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue13537.xaml.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue13537.xaml.cs
new file mode 100644
index 000000000000..3674f3b4b8b4
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue13537.xaml.cs
@@ -0,0 +1,176 @@
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Controls.Internals;
+
+namespace Maui.Controls.Sample.Issues
+{
+ [Issue(IssueTracker.Github, 13537, "ApplyQueryAttributes should Trigger for all navigations",
+ PlatformAffected.All)]
+ public partial class Issue13537 : Shell
+ {
+
+ public Issue13537()
+ {
+ InitializeComponent();
+ Routing.RegisterRoute("NewPage", typeof(Issue13537InnerPage));
+ Application.Current.Windows[0].Page = new NavigationPage(new Issue13537HomePage());
+ }
+ }
+
+ public class Issue13537HomePage : ContentPage
+ {
+ public Issue13537HomePage()
+ {
+ Title="Home"; // Setting the title of the page
+ var viewModel = new Issue13537ViewModel();
+ this.BindingContext = viewModel;
+
+ var Label = new Label
+ {
+ AutomationId = "HomePageTestLabel",
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center
+ };
+ Label.SetBinding(Label.TextProperty, nameof(viewModel.DisplayText));
+
+ var button = new Button
+ {
+ Text = "Navigate using PushAsync",
+ AutomationId = "PushAsyncButton",
+ HorizontalOptions =LayoutOptions.Center,
+ VerticalOptions=LayoutOptions.Center
+ };
+ button.Clicked += OnNavigationWithPushAsync;
+
+ var stack = new StackLayout();
+ stack.Children.Add(Label);
+ stack.Children.Add(button);
+
+ this.Content = stack;
+ }
+ private void OnNavigationWithPushAsync(object sender, EventArgs e)
+ {
+ Navigation.PushAsync(new Issue13537InnerPage());
+ }
+ }
+ public class Issue13537FavoritePage : ContentPage
+ {
+
+ public Issue13537FavoritePage()
+ {
+ Title = "Favorite"; // Setting the title of the page
+ var viewModel = new Issue13537ViewModel();
+ this.BindingContext = viewModel;
+
+ var Label = new Label
+ {
+ AutomationId = "FavouritePageTestLabel",
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center
+ };
+ Label.SetBinding(Label.TextProperty, nameof(viewModel.DisplayText));
+ var button = new Button
+ {
+ Text = "Navigate using GoToAsync",
+ AutomationId = "GoToAsyncButton",
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center
+ };
+ button.Clicked += OnGoToAsync;
+ var stack = new StackLayout();
+ stack.Children.Add(Label);
+ stack.Children.Add(button);
+ this.Content = stack;
+ }
+ private void OnGoToAsync(object sender, EventArgs e)
+ {
+
+ var Parameter = new Dictionary
+ {
+ { $"Parameter From {Shell.Current.CurrentPage.Title} Page", $"to New Page" },
+
+ };
+ Shell.Current.GoToAsync("NewPage",parameters:Parameter);
+ }
+ }
+ public class Issue13537InnerPage : ContentPage
+ {
+ public Issue13537InnerPage()
+ {
+ Title = "NewPage"; // Setting the title of the page
+ var viewModel = new Issue13537ViewModel();
+ this.BindingContext = viewModel;
+
+ var Label = new Label
+ {
+ AutomationId = "InnerPageTestLabel",
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center
+ };
+ Label.SetBinding(Label.TextProperty, nameof(viewModel.DisplayText));
+ var button = new Button
+ {
+ Text = "Navigate using PopAsync back",
+ AutomationId = "PopAsyncButton",
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center
+ };
+ button.Clicked += OnNavigatingPopButton;
+
+ var stack = new StackLayout();
+ stack.Children.Add(Label);
+ stack.Children.Add(button);
+
+
+ stack.AutomationId = "NewInnerPage";
+
+ this.Content = stack;
+ }
+
+ private void OnNavigatingPopButton(object sender, EventArgs e)
+ {
+ Navigation.PopAsync();
+ }
+ }
+ public class Issue13537ViewModel : IQueryAttributable, INotifyPropertyChanged where T : Page
+ {
+ // Property to hold formatted query attributes as a string
+ private string _displayText = "Default Query" ;
+ public string DisplayText
+ {
+ get => _displayText;
+ set
+ {
+ _displayText = value;
+ OnPropertyChanged(nameof(DisplayText));
+ }
+ }
+
+ public void ApplyQueryAttributes(IDictionary query)
+ {
+ if(query == null)
+ {
+ return;
+ }
+
+ if( query.Count > 0)
+ {
+ DisplayText = $"{string.Join(",\n", query.Select(q => $"{q.Key} {q.Value}"))}";
+ }
+ else
+ {
+ DisplayText= $"{typeof(T).Name} QueryAttribute is triggered";
+ }
+ }
+
+ // Implement INotifyPropertyChanged to support binding
+ public event PropertyChangedEventHandler PropertyChanged;
+ protected virtual void OnPropertyChanged(string propertyName)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue13537.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue13537.cs
new file mode 100644
index 000000000000..733ad2c34fb5
--- /dev/null
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue13537.cs
@@ -0,0 +1,65 @@
+using NUnit.Framework;
+using UITest.Appium;
+using UITest.Core;
+
+namespace Microsoft.Maui.TestCases.Tests.Issues
+{
+ public class Issue13537 : _IssuesUITest
+ {
+#if ANDROID
+ const string backButtonIdentifier = "";
+#else
+ const string backButtonIdentifier = "Home";
+#endif
+ public Issue13537(TestDevice testDevice) : base(testDevice)
+ {
+ }
+
+ public override string Issue => "ApplyQueryAttributes should Trigger for all navigations";
+
+ [Test]
+ [Category(UITestCategories.Shell)]
+ public void ApplyQueryAttributeShouldTriggerforPushAndPopButton()
+ {
+ App.WaitForElement("HomePageTestLabel");
+ App.Tap("PushAsyncButton");
+ App.WaitForElement("InnerPageTestLabel");
+ App.Tap("PopAsyncButton");
+ var result = App.WaitForElement("HomePageTestLabel").GetText();
+ Assert.That(result, Is.EqualTo("Issue13537HomePage QueryAttribute is triggered"));
+ }
+
+#if TEST_FAILS_ON_CATALYST
+ //App.TapBackArrow doesnot actually tab the back arrow button instead it taps the first tab element on the screen as both have the same access identifier.
+ [Test]
+ [Category(UITestCategories.Shell)]
+ public void ApplyQueryAttributeShouldTriggerforPushAndBackButton()
+ {
+ App.WaitForElement("HomePageTestLabel");
+ App.Tap("PushAsyncButton");
+ App.WaitForElement("InnerPageTestLabel");
+#if IOS
+ App.Back();
+#else
+ App.TapBackArrow(backButtonIdentifier);
+#endif
+ var result = App.WaitForElement("HomePageTestLabel").GetText();
+ Assert.That(result, Is.EqualTo("Issue13537HomePage QueryAttribute is triggered"));
+ }
+#endif
+
+
+ [Test]
+ [Category(UITestCategories.Shell)]
+ public void ApplyQueryAttributeShouldTriggerforTab()
+ {
+ App.WaitForElement("Favorite");
+ App.Tap("Favorite");
+ App.WaitForElement("FavouritePageTestLabel");
+ App.Tap("GoToAsyncButton");
+ var result = App.WaitForElement("InnerPageTestLabel").GetText();
+ Assert.That(result, Is.EqualTo("Parameter From Favorite Page to New Page"));
+ }
+ }
+
+}