Johnathon Sullinger
Johnathon Sullinger

Reputation: 7414

Root Page is not part of the Navigation.NavigationStack collection

When my app starts, I so some logic in my AppDelegate and assign the MainPage a page based on the results of that logic.

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    global::Xamarin.Forms.Forms.Init ();

    // .....

    if(authorizationStatus == PhotoLibraryAuthorizationStatus.Authorized)
    {
        bokehApp.SetStartupView(serviceLocator.GetService<AlbumsPage>());
    }
    else
    {
        bokehApp.SetStartupView(serviceLocator.GetService<StartupPage>());
    }
}

In my app.cs, I assign the MainPage the given view from the AppDelegate

public class App : Xamarin.Forms.Application
{
    public void SetStartupView(ContentPage page)
    {
        this.MainPage = new NavigationPage(page);
    }
}

In this instance, I am passing StartupPage into the SetStartupView(Page) method. When the user does something, I navigate to the AlbumsPage.

this.Navigation.PushAsync(new AlbumPage());

When I do this, the AlbumPage is created and navigated to; it's Navigation.NavigationStack collection only contains itself, not the Page that it just navigated from. What I want to do, is prevent a call to this.Navigation.PopAsync() navigating back to the StartupPage, which is what currently happens.

Initially I was going to just run a loop and pop the original Page off, and then remove all of the remaining pages, in this case StartupPage.

// Grab the current page, as it is about to become our new Root.
var navigatedPages = this.Navigation.NavigationStack.ToList();
Page newRootPage = navigatedPages.Last();

// Dont include the current item on the stack in the removal.
navigatedPages.Remove(newRootPage);

while(navigatedPages.Count > 0)
{
    Page currentPage = navigatedPages.Last();
    this.Navigation.RemovePage(currentPage);
}

However, when I look, the Navigation.NavigationStack collection only contains the AlbumsPage. Yet, calling this.Navigation.PopAsync() navigates back to the StartupPage.

What do I need to do in order to reset this navigation stack, so that popping will not navigate back to the initial page?

Update

When I navigate, I've been able to use this:

App.Current.MainPage = new NavigationPage(viewModelPage);

as suggested by @Daniel but this prevents the animation from taking place. I have also tried

await App.Current.MainPage.Navigation.PushAsync(fooPage);
App.Current.MainPage = new NavigationPage(fooPage);

When I do this, I see the new page transitioned to, but once the await call on PushAsync finishes, and the MainPage is replaced, the Page disappears and I'm left with an empty screen.

I really don't want to lose the animations during transitioning from my setup Page to the actual app.

Upvotes: 2

Views: 6766

Answers (3)

Murat &#214;zbayraktar
Murat &#214;zbayraktar

Reputation: 152

This is fix my problem.

    protected override bool OnBackButtonPressed()
    {
        foreach (Page page in Navigation.ModalStack)
        {
            page.Navigation.PopModalAsync();
        }

        return true;
    }

Upvotes: 1

Johnathon Sullinger
Johnathon Sullinger

Reputation: 7414

I was able to solve the issue. This mostly came down to my lack of understanding how the NavigationPage worked. It would seem that each Page is given their own Navigation stack. As I navigated between Pages and examined their NavigationStack collections, they always just had one item in them.

I then started looking at App.Current.MainPage.Navigation and discovered that it actually had the entire stack (both StartupPage and FooPage). I was able to then grab the StartupPage prior to pushing the FooPage onto the navigation stack, and then removing the StartupPage once the navigation to FooPage was completed. This essentially let me reset the root page, while keeping the transition animation between the views.

Page originalRootPage = App.Current.MainPage.Navigation.NavigationStack.Last();
await App.Current.MainPage.Navigation.PushAsync(new FooPage());
App.Current.MainPage.Navigation.RemovePage(originalRootPage);

I'll mark this as answered when the time-period has expired and i'm allowed to.

Upvotes: 6

Daniel Luberda
Daniel Luberda

Reputation: 7454

I think what you're looking for is setting:

App.Current.MainPage

to a new NavigationPage. It replaces main page of application.

Upvotes: 5

Related Questions