Skip to content
Merged
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
11 changes: 11 additions & 0 deletions src/Controls/src/Core/Shell/Shell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
8 changes: 8 additions & 0 deletions src/Controls/src/Core/Shell/ShellItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
11 changes: 10 additions & 1 deletion src/Controls/src/Core/Shell/ShellNavigationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down
23 changes: 23 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue13537.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<Shell xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://schemas.microsoft.com/dotnet/2021/maui/design"
xmlns:local="using:Maui.Controls.Sample.Issues"
xmlns:issues="using:Maui.Controls.Sample.Issues"
Shell.FlyoutBehavior="Disabled"
x:Class="Maui.Controls.Sample.Issues.Issue13537">

<TabBar AutomationId="TabBar13537" x:Name="TabBar13537">
<Tab Title="Home" AutomationId="Home">
<ShellContent
ContentTemplate="{DataTemplate local:Issue13537HomePage}"
Route="MainPage" />
</Tab>
<Tab Title="Favorite"
AutomationId="Favorite">
<ShellContent
ContentTemplate="{DataTemplate local:Issue13537FavoritePage}"
Route="FavoritesPage" />
</Tab>
</TabBar>
</Shell>
176 changes: 176 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue13537.xaml.cs
Original file line number Diff line number Diff line change
@@ -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<Issue13537HomePage>();
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<Issue13537FavoritePage>();
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<string, object>
{
{ $"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<Issue13537InnerPage>();
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<T> : 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<string, object> 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));
}
}

}
Original file line number Diff line number Diff line change
@@ -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"));
}
}

}
Loading