Reputation: 1626
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
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
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
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