Having a bit of a weird one with Shell navigation and the timing of ApplyQueryAttributes
relative to other page lifecycle events.
My app navigates to a MainPage with a menu that then navigates through other pages in the app until it reaches a page that requires a Flyout Menu (at which point I set the Shell.Current.FlyoutContent
).
So
MainPage > PageA > PageB > PageWithFlyoutMenu
I'm performing the navigation as follows
MainPage to PageA: await Shell.Current.GoToAsync($"PageA", true);
Lifecycle event order:
Constructor
> ApplyQueryAttributes
> OnAppearing
> OnNavigatedTo
PageA to PageB: await Shell.Current.GoToAsync($"PageB");
Lifecycle event order:
Constructor
> ApplyQueryAttributes
> OnAppearing
> OnNavigatedTo
PageB to PageWithFlyoutMenu:
Shell.Current.FlyoutContent = IPlatformApplication.Current?.Services.GetService<MenuPage>(); await Shell.Current.GoToAsync($"///PageWithFlyoutMenu-1");
Lifecycle event order:
Constructor
> OnAppearing
> OnNavigatedTo
> ApplyQueryAttributes
The issue here is that ApplyQueryAttributes
is the last to be invoked.
AppShell is as follows:
<Shell
x:Class="****.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:****.Views"
xmlns:localDetail="clr-namespace:****.Views.DetailPages"
Title="****">
<ShellContent
Title="MainPage"
ContentTemplate="{DataTemplate local:MainPage}"
FlyoutItemIsVisible="False"
Route="MainPage"
Shell.FlyoutItemIsVisible="False" />
<ShellContent
Title="PageWithFlyoutMenu-1"
ContentTemplate="{DataTemplate localDetail:PageWithFlyoutMenu-1}"
Route="PageWithFlyoutMenu-1" />
<ShellContent
Title="PageWithFlyoutMenu-2"
ContentTemplate="{DataTemplate localDetail:PageWithFlyoutMenu-2}"
Route="PageWithFlyoutMenu-2" />
</Shell>
And I have the following routes registered:
Routing.RegisterRoute("PageA", typeof(PageA));
Routing.RegisterRoute("PageB", typeof(PageB));
EDIT: ApplyQueryAttributes in PageB as requested in comments:
public override void ApplyQueryAttributes(IDictionary<string, object> query)
{
Tracker.WriteLine();
if (query.ContainsKey("MyDto"))
{
var myParameter = query["MyDto"] as MyDto;
if (myParameter != null) MyId = new Guid(myParameter.MyId);
}
base.ApplyQueryAttributes(query);
}
Can anyone shed any light on why this would be?
After some attempts, I concluded that if you want to use the default Shell structure in your project first, and then change the Shell to the Flyout structure through Shell.Current.FlyoutContent = IPlatformApplication.Current?.Services.GetService<FlyoutMenu>();
, this will not work.
This will disrupt the internal operation logic of the Shell
, and therefore cause ApplyQueryAttributes
not to be triggered first when the pageB jumps.
I suggest that Mainpage, 、PageA, and PageB do not use the Shell structure, and set AppShell.xaml
to the Flyout structure, add PageWithFlyoutMenu1ViewModel
and PageWithFlyoutMenu2ViewModel
in it, and then change the logic of jumping from pageB to PageWithFlyoutMenu1ViewModel
in your project to jump from pageB to AppShell.
The following is the general implementation steps:
Step1: change the code in App.xaml.cs:
Public App(MainPageViewModel mainPageViewModel)
{
InitializeComponent();
MainPage = new NavigationPage(new Mainpage(mainPageViewModel));
}
Step2: Change the MainPage->PageA and PageA->PageB jump logic to the following code:
await Navigation.PushAsync(new PageA(pageAViewModel));
Step3:Set the code in the appshell to Flyout structure, which means you don't need to use FlyoutMenu anymore.
<Shell ...>
<FlyoutItem Title="Page With Flyout Menu_1">
<Tab>
<ShellContent ContentTemplate="{localDetail:PageWithFlyoutMenu1}" />
</Tab>
</FlyoutItem>
<FlyoutItem Title="Page With Flyout Menu_2"">
<Tab>
<ShellContent ContentTemplate="{localDetail:PageWithFlyoutMenu2}" />
</Tab>
</FlyoutItem>
</Shell>
Step4: change the code of Navigate method in PageBViewModel.cs:
App.Current.MainPage = new AppShell();