Yisroel M. Olewski
Yisroel M. Olewski

Reputation: 1626

PopAsync causes ArgumentOutOfRangeException

I'm pretty new to Xamarin.Forms. I have a pretty simple function on main page appearing

async public Task BaseAppearing()
    {
        if (UserID == null)
        {
            var page = new LoginPage();
            await App.Navigate(page);
        }
        else
        {
            stopWatch.Restart();
        }
    }

Now the login page shows all right, problem is that in the login page when I click on Login and I try to pop the navigation stack, I get the following error

Unhandled Exception:

System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index

and the app crashes.

Exception happens only in Android (emulator and real). in UWP it works just fine

The popping code is also very simple

public static Task PopNavigation()
    {
        var nav = Current.MainPage.Navigation;
        Task ret;
        try
        {
            ret = nav.PopAsync();
        }
        catch (Exception ex)
        {
            ex.Log();
            ret = Navigate(Current.MainPage);
        }
        return ret;
    }

Not only does it throw the error, but it never reaches the exception handler.

Also, I've read that sometimes the navigation stack becomes corrupted/empty. But no, NavigationStack has 2 items. MainPage and LoginPage, which I believe is correct

All navigation is happening on the same stack, since I only have 1 navigation function in the app and that's all I ever call for navigation

Please advise what can be done

UPDATE I tried to change my code to use NavigationPage as follows, but did not help (also i got like 2 title bars on top)

public async static Task Navigate(Page Page)
    {
        //await Current.MainPage.Navigation.PushAsync( Page);
        await Current.MainPage.Navigation.PushAsync( new NavigationPage( Page));
    }

If this might help someone, here's my stack trace

at System.Collections.Generic.List`1[T].get_Item (System.Int32 index) [0x00009] in /Users/builder/jenkins/workspace/xamarin-android-d15-9/xamarin-android/external/mono/external/corefx/src/Common/src/CoreLib/System/Collections/Generic/List.cs:180 at Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer.GetFragment (Xamarin.Forms.Page page, System.Boolean removed, System.Boolean popToRoot) [0x00003] in D:\a\1\s\Xamarin.Forms.Platform.Android\AppCompat\NavigationPageRenderer.cs:865 at Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer.SwitchContentAsync (Xamarin.Forms.Page page, System.Boolean animated, System.Boolean removed, System.Boolean popToRoot) [0x0001a] in D:\a\1\s\Xamarin.Forms.Platform.Android\AppCompat\NavigationPageRenderer.cs:768 at Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer.OnPopViewAsync (Xamarin.Forms.Page page, System.Boolean animated) [0x00017] in D:\a\1\s\Xamarin.Forms.Platform.Android\AppCompat\NavigationPageRenderer.cs:592 at Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer.PopViewAsync (Xamarin.Forms.Page page, System.Boolean animated) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.Android\AppCompat\NavigationPageRenderer.cs:154 at Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer.OnPopped (System.Object sender, Xamarin.Forms.Internals.NavigationRequestedEventArgs e) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.Android\AppCompat\NavigationPageRenderer.cs:573 at Xamarin.Forms.NavigationPage+d__69.MoveNext () [0x0004c] in D:\a\1\s\Xamarin.Forms.Core\NavigationPage.cs:297 --- End of stack trace from previous location where exception was thrown --- at Xamarin.Forms.NavigationPage+d__68.MoveNext () [0x0004c] in D:\a\1\s\Xamarin.Forms.Core\NavigationPage.cs:280 --- End of stack trace from previous location where exception was thrown --- at Xamarin.Forms.NavigationPage+d__45.MoveNext () [0x000cb] in D:\a\1\s\Xamarin.Forms.Core\NavigationPage.cs:168 --- End of stack trace from previous location where exception was thrown --- at Qleeg.LoginPage+d__2.MoveNext () [0x003f8] in D:\Projects\Qleeg\Qleeg\Qleeg\Views\LoginPage.xaml.cs:70 --- End of stack trace from previous location where exception was thrown --- at (wrapper dynamic-method) System.Object.30(intptr,intptr) at (wrapper native-to-managed) System.Object.30(intptr,intptr)

What am I doing wrong?

UPDATE 2

Here is the app's constructor

public App()
    {
        InitializeComponent();

        AppDomain.CurrentDomain.UnhandledException += (sender, args) => OnError(sender, args.ExceptionObject as Exception);
        TaskScheduler.UnobservedTaskException += (sender, args) => OnError(sender, args.Exception);
        MainPage = new NavigationPage(new MainPage());
   ......
}

And here is my navigation code

From MainPage to LoginPage

async public static Task BaseAppearing(this ContentPage Input)
{
    if (App.Current.UserID == null)
    {
        var page = new LoginPage();
        await Input.Navigation.PushAsync(page);
    }
    else
    {
        App.Current.stopWatch.Restart();
    }
}

And Back

lblMessage.Text = "Welcome!";
lblMessage.TextColor = Color.Green;
Functions.WriteLog("Login", "pre nav pop");
//await App.PopNavigation();// App.Current.MainPage.Navigation.PopAsync();
await Navigation.PopAsync();//THIS IS LINE 70

UPDATE 3

I switched my MainPage code to this:

    async private void MainPage_Appearing(object sender, EventArgs e)
    {
        if (App.Current.UserID == null) {await App.Current.MainPage.Navigation.PushAsync(new NavigationPage(new LoginPage ())); }
    }

Now, The error disappeared (though I'm baffled as to the reason), but Navigaion.PopAsync() simply does nothing. No error, but no navigating either.

Also, LoginPage now appears with 2 title lines/headers on the top.

Upvotes: 4

Views: 2563

Answers (3)

James Westgate
James Westgate

Reputation: 11444

If you Push a page in OnAppearing on Android, it won't be initialised properly and subsequent calls to PopAsync or simply pressing the back button in the toolbar will cause this error. To bypass, you have to introduce a delay so that the main page can be initialised properly first.

protected override void OnAppearing()
{ 
    base.OnAppearing();

    Task.Factory.StartNew(() => Thread.Sleep(500)).ContinueWith(async (t) =>
    {
        await Navigation.PushAsync(new MyNewPage(), false);
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

Upvotes: 2

karan thakkar
karan thakkar

Reputation: 140

Add

Task.Delay(300)

before navigating page.

i know it's an hack but if you want to navigate to other page while on appearing then we have to do this. cause whole page is not initialized yet. so we have to wait for couple of seconds to initialize page properly in navigation stack

Upvotes: 6

nevermore
nevermore

Reputation: 15786

To add a NavigationPage to your root page:

public App ()
{
  MainPage = new NavigationPage (new Page1Xaml ());
}

To push a page simplily:

async void OnNextPageButtonClicked (object sender, EventArgs e)
{
  await Navigation.PushAsync (new Page2Xaml ());
}

To pop a page :

async void OnPreviousPageButtonClicked (object sender, EventArgs e)
{
  await Navigation.PopAsync ();
}

To pop to root page:

async void OnRootPageButtonClicked (object sender, EventArgs e)
{
  await Navigation.PopToRootAsync ();
}

Use the codes I listed above to push and pop pages in xamarin.forms. I can't understand what is await App.Navigate(page); in your project.

I tried to change my code to use NavigationPage as follows, but did not help (also i got like 2 title bars on top)

You only need one instance of NavigationPage in your project. Don't push to a new NavigationPage like this:

await Current.MainPage.Navigation.PushAsync( new NavigationPage( Page));

Just push to the page you want:

 await Current.MainPage.Navigation.PushAsync(Page);

Upvotes: 0

Related Questions