maui
maui copied to clipboard
Using ".." in route definition doesn't remove last navigated page(s) from nav stack
Description
Using await Shell.Current.GotoAsync("//../../nameof(MyPage)"); doesn't seem to remove from navigation stack the last detail page(s) that I've been on before navigating to MyPage.
Steps to Reproduce
Here's how to reproduce this using AppShell:
Define Page1, Page2 and Page3 as main tab in AppShell -- see below:
<FlyoutItem Title="Home" Icon="home.png">
<Tab Title="Page 1" Icon="icon1.png">
<ShellContent Route="Page1" ContentTemplate="{DataTemplate local: Page1}" />
</Tab>
<Tab Title="Page 2" Icon="icon2.png">
<ShellContent Route="Page2" ContentTemplate="{DataTemplate local: Page2}" />
</Tab>
<Tab Title="Page 3" Icon="icon3.png">
<ShellContent Route="Page3" ContentTemplate="{DataTemplate local: Page3}" />
</Tab>
</FlyoutItem>
Then add two detail pages Page4 and Page5 and define their routes in AppShell.xaml.cs as below:
Routing.RegisterRoute(nameof(Page4), typeof(Page4));
Routing.RegisterRoute(nameof(Page5), typeof(Page5));
Use a button or another element to help navigate to Page5. For example, add a button on Page3 that'll take you to Page4 and do the same to go to Page5.
Finally, add a way to invoke a navigation event on Page5 e.g. a button click, etc. The event should send the user to Page2 but remove the last two detail pages from navigation stack. Here's how I did it:
var route = $"//../../{nameof(Page2)}";
await Shell.Current.GotoAsync(route);
This does send the user to Page2 but doesn't remove Page4 and Page5 from the stack. So, if I tap on Page3 on the tab bar, I still end up on Page5 instead of Page3. That's because we got to Page5 through this path:
Page3 => Page4 => Page5.
Link to public reproduction project repository
n/a
Version with bug
7.0.49
Last version that worked well
6.0
Affected platforms
iOS, Android
Affected platform versions
iOS 16, Android 10
Did you find any workaround?
Manually removing pages from the stack does work but shouldn't be necessary. For example, the following code removes the last page from the stack and then sends the user to Page2:
var lastIndex = Shell.Current.Navigation.NavigationStack.Count - 1;
Shell.Current.Navigation.RemovePage(Shell.Current.Navigation.NavigationStack[lastIndex]);
var route = $"//{nameof(Page2)}";
await Shell.Current.GotoAsync(route);
Relevant log output
No response
@imsam67 what if you navigate to
var route = $"../../{nameof(Page2)}";
Hi @imsam67. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.
@PureWeen,
Liyun Zhang tested that. See https://stackoverflow.com/q/76277821/199364.
Also see my answer. Sam’s comment says the bug also happened with
await Shell.Current.GotoAsync($"//{nameof(Page2)}");
Therefore, the stack isn’t getting correctly cleared.
// isn’t replacing the stack, in this situation.
I'm experiencing the same bug: navigating away from a detailed page (page on a navigation stack in Shell) to a route registered in Shell.xaml doesn't remove the detailed page from the stack. Manually removing it with "Navigation.RemovePage" works though. Hope it can be fixed soon (along with other thousands of bugs? LOL)
Verified this issue with Visual Studio Enterprise 17.9.0 Preview 3, can repro this issue with repro steps.
This one is kind of a big deal. The only work around I've found is if the first page in the new stack is a shell page itself. But then you can't really navigate back because you're at the root.
This one is a big limiting factor - along with shell pages being maintained in memory forever once they are created. Please, please, please bump the priority of these basic issues that have a huge impact to the usability of the platform. It's terrible that these glaring issues sit for over a year with no movement.
Edit:
This is a horrible hack, but if you put a variable in the view model that says the page has finished what it needed to do, you can use Page.OnAppearing to pop to root. However, there is the other bug that keeps pages in memory even when they are closed, so you probably need to reset that variable after popping to the root. So ugly, but it seems to work.