Using PopAsync to pop two or more pages at once?

DevinRoseDevinRose USMember ✭✭

I have created a Forms Shared Project solution and have multiple pages that go Page1 to Page2 to Page3 to Page4. From Page4 I want to pop out to Page1 or Page2 on the click of a button. But anything I have tried to PopAsync multiple times at once has failed (either an exception is thrown or it just doesn't pop more than one page).

My code in Page4 looks like this (Pages 1, 2, and 3 are on the page stack):

public class Page4 : ContentPage { public Page4 () { var button = new Button () { Text = "Pop Two Pages" }; button.Clicked += async delegate { await Navigation.PopAsync (); await Navigation.PopAsync (); }; Content = button; } }
The above code throws InvalidOperationException:

System.InvalidOperationException: Operation is not valid due to the current state of the object
at System.Collections.Generic.Stack`1[Xamarin.Forms.Page].Pop () [0x0000b] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Collections.Generic/Stack.cs:120
at Xamarin.Forms.NavigationProxy.OnPopAsync () [0x00000] in :0
at Xamarin.Forms.NavigationProxy.PopAsync () [0x00000] in :0
at NavigationTest.Page4+c__async0.MoveNext () [0x0007b] in /Users/devinrose/Dropbox/KetraProject/MobileExperiments/NavigationTest/NavigationTest/Page4.cs:15

My guess is that the second PopAsync is not valid because it has already popped this page off the stack. Using a single PopToRootAsync doesn't work due to a known Xamarin bug on iOS. Any ideas?

Best Answer

Answers

  • DevinRoseDevinRose USMember ✭✭

    Thanks Craig. Is there a place to download that preview? Or is it better to wait for it to be officially released?

  • CraigDunnCraigDunn USXamarin Team Xamurai

    @DevinRose‌ in the Manage NuGet Packages... window there is an option to allow you see 'see/download' pre-release packages. In Xamarin Studio it is a tickbox in the bottom-left of the window, in Visual Studio it is a drop-down item at the top of the window. When you enable this option and search for Xamarin.Forms you'll be able to install the pre-release version.

    It's up to you whether you want to test it now or wait. You can 'roll back' to the release version by removing the NuGet packages from your solution, then re-adding them after un-selecting the pre-release option.

  • ChaseFlorellChaseFlorell CAInsider, University mod

    Easiest way to update to the latest pre-release is from the Package Manager Console.

     > Get-Project -All | Install-Package Xamarin.Forms -pre
    

    or to update

     > Get-Project -All | Update-Package Xamarin.Forms -pre
    

    and lastly, if you don't want it installed in your tests, you can get your projects one at a time

     > Get-Project MyFooProject | Install-Package Xamarin.Forms -pre
    
  • chris_riesgochris_riesgo USUniversity ✭✭✭

    What if you wanted to pop 2 pages, where that page is not the root? Currently, Forms exceptions if you attempt this.

    Thoughts? Or should I log a bug?

  • ChaseFlorellChaseFlorell CAInsider, University mod

    One option would be to roll this yourself (for now). Simply create your own wrapper around PushAsync and PopAsync that includes a counter, and the ability to PopAsync(int). This doesn't seem like a very difficult approach.

  • MichaelStrongMichaelStrong AUUniversity

    It would be nice to have PopAsync(int levels) but in the meantime I've implemented this using the MessageCenter.

    await Navigation.PopAsync(); MessagingCenter.Send<MyForm,AnObject>(this, "Pop", item);

    Then in the form that is popped back to:

    MessagingCenter.Subscribe<MyForm,AnObject>(this, "Pop", (s,a) => { Navigation.PopAsync(); });

    Certainly not the most elegant solution but it works for now.

  • SandyMonkSandyMonk USMember

    NavigationPage

  • sunil.8167sunil.8167 USMember ✭✭

    Thanks LeoRodri,

    That works great !!!

    Thanks,
    Sunil

  • LCungLCung USMember

    Thanks LeoRodri,
    It's great!

  • kyurkchyankyurkchyan AMMember ✭✭

    @LeoRodri you're awesome, thanks!

  • AmitSingh6789AmitSingh6789 USMember

    @LeoRodri thanks,It saves me :blush: !

  • oguzhanorhaanoguzhanorhaan TRMember ✭✭

    @LeoRodri thanks, this is awesome

  • BehroozTorkiBehroozTorki HUMember ✭✭

    With this function you can simplify poping out multiple pages

    void PopUntilDestination(Type DestinationPage)
    {
    int LeastFoundIndex = 0;
    int PagesToRemove = 0;

            for (int index = Navigation.NavigationStack.Count - 2; index > 0; index--)
            {
                if (Navigation.NavigationStack[i].GetType().Equals(DestinationPage))
                {
                    break;
                }
                else
                {
                    LeastFoundIndex = index;
                    PagesToRemove++;
                }
            }
    
            for (int index = 0; index < PagesToRemove; index++)
            {
                Navigation.RemovePage(Navigation.NavigationStack[LeastFoundIndex]);
            }
    
            Navigation.PopAsync();
        }
    

    Call it like this
    PopUntilDestination(typeof(ProductSelectionPage));

    Basically it removes the pages between the current page and the destination page and then perform a PopAsync

Sign In or Register to comment.