96

I have the following method in an Xamarin.Forms.ContentPage wired to a button click event

public class LoginPage : ContentPage
{
    private Button _loginButton = null;
    private Entry _PasswordInput = null;
    private Entry _UsernameInput = null;

    public LoginPage()
    {
        _UsernameInput = new Entry { Placeholder = "Username" };
        _PasswordInput = new Entry { Placeholder = "Password", IsPassword = true };

        _loginButton = new Button
        {
            Text = "Login",
            BorderRadius = 5
        }

        _loginButton.Clicked += LogIn;

        Content = new StackLayout 
        {
            VerticalOptions = LayoutOptions.Center,
            Children = 
            {
                 _UsernameInput, _PasswordInput, _loginButton, 
            },
            Spacing = 15
        };
    }

    public async void LogIn(object sender, EventArgs eventsArgs)
    {
        //do authenticate stuff here
        SSO.MyAuthentication client = new SSO.MyAuthentication();

        bool isAuthenticated = client.Authenticate(_UsernameInput.Text, _PasswordInput.Text);

        if(isAuthenticated)
        {
             //Push home page to top of navigation stack
             Navigation.PushAsync(new HomePage());
        }
    }
}

On the following line of code Navigation.PushAsync(new HomePage());, I am getting the following exception while debugging:

PushAsync is not supported globally on Android, please use a NavigationPage

How do I resolve this issue using a Xamarin.Forms.NavigationPage object?

Stephane Delcroix
  • 16,134
  • 5
  • 57
  • 85
Michael Kniskern
  • 24,792
  • 68
  • 164
  • 231

10 Answers10

156

You are calling "PushAsync":

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    private void btnCourseList_Clicked(object sender, EventArgs e)
    {
        Navigation.PushAsync(new PageB());
    }
}

but you did not start the NavigationPage, which normally is done in the App.cs class, or at least it should be started before any call to "PushAsync":

MainPage = new NavigationPage(new PageA());
Reader Man San
  • 2,159
  • 1
  • 15
  • 9
61

In app.xaml.cs file,

Replace

 MainPage = new <namespace>.MainPage();

With

 MainPage = new NavigationPage(new <namespace>.MainPage());

Then Use

 await Navigation.PushAsync(new NavigationPage(new MainPage2()));
Amar Mathur
  • 845
  • 7
  • 9
  • 1
    You don't need to use new NaigationPage() inside PushAsync. You can have await Navigation.PushAsync(new MainPage2()); A bit less code :) – Eldlabs May 02 '18 at 03:38
  • await Navigation.PushAsync(new MainPage()); not working with ContentPage i am getting System.InvalidOperationException: PushAsync is not supported globally on Android, please use a NavigationPage. – Shweta Nandha May 18 '18 at 13:05
  • 3
    This mess up the design since it adds an navigation bar in the top of the page. – Ola Ström Apr 26 '20 at 22:59
  • The Navigation Bar is what our users desire to see. :) – abhi Jan 07 '22 at 16:25
  • 2
    @OlaStröm and others who want to remove the navigation bar at the main page, go to the xaml and in the ContentPage tag add in `NavigationPage.HasNavigationBar="False"` – UnidentifiedX Sep 03 '22 at 10:52
16

You need to enclose your LoginPage in a NavigationPage. This will fix your error, but will leave you with the LoginPage contained on your navigation stack.

An alternate approach would be to make your HomePage the root of the application, then display the LoginPage modally on top of it. Only when the user successfully logs in do you dismiss the LoginPage modal so they can see the HomePage.

Jason
  • 86,222
  • 15
  • 131
  • 146
  • Would I enclose my `LoginPage` within a `NavigationPage` in my `App.GetMainPage` method? Also, could I use the 'Navigation.PopAsync()' method to remove the loginpage from the navigation stack? – Michael Kniskern Jul 08 '14 at 00:20
  • Yes, you make NavPage your outermost page. I don't think you can use PopAsync() when there is only one page on the stack, but I haven't tried it. – Jason Jul 08 '14 at 01:10
  • Other approach is to have the `LoginPage` as main page for the application, and `PushModalAsync` a new `NavigationPage` with the content of the app on successful login. – Stephane Delcroix Jul 08 '14 at 05:51
  • 1
    The best approach is to load the app normally and `PushModalAsync()` the login page. Just be sure to prevent the user from pressing the hardware back button on Android. `public override void OnBackPressed(){ if(user.IsAuthenticated(){base.OnBackPressed();}}` – Chase Florell Jul 15 '14 at 20:12
  • I have the same problem when I try to call PushAsync in a Modal Page. Something like - PushAsync - PushModalAsync - PushAsync (here I have the problem and your workarounds does not work) – Alessandro Caliaro Aug 21 '16 at 15:27
  • I preferred to use this approach instead of using some "isLoggedIn" logic in App.cs to show MainPage or LoginPage – hamdanjz4 Apr 16 '17 at 03:34
12

First make setting in "Main App Page" then do in "Content page" to go other page:

enter image description here

Juri Noga
  • 4,363
  • 7
  • 38
  • 51
Abdul Khaliq
  • 2,139
  • 4
  • 27
  • 31
11

I only change pushAsync with pushModalAsync :)

public async void LogIn(object sender, EventArgs eventsArgs)
{
    //do authenticate stuff here
    SSO.MyAuthentication client = new SSO.MyAuthentication();

    bool isAuthenticated = client.Authenticate(_UsernameInput.Text, _PasswordInput.Text);

    if(isAuthenticated)
    {
         //Push home page to top of navigation stack
         //Navigation.PushAsync(new HomePage());
           Navigation.PushModalAsync(new HomePage());
    }
}
T M
  • 221
  • 3
  • 15
5

Check that in the previous navigation you use NavigationPage:

Incorrect: Application.Current.MainPage = new LoginPage();

Correct: Application.Current.MainPage = new NavigationPage(new LoginPage());

JSON C11
  • 11,272
  • 7
  • 78
  • 65
4

When you add (in "public partial class App"):

public App()
{
    InitializeComponent();

    MainPage = new NavigationPage(new MainPage());
}

You can use:

await Navigation.PushAsync(new BleBleBle());

3

As you usually don't want the Login to be part of the page stack or for the user to be able to return after having authenticated correctly, you can do the following:

Inside the method that is executed when pressing login button

Application.Current.MainPage = new NavigationPage (new HomePage ());

This will take as the main screen of the NavigationPage your main screen and not the LoginPage. Also the user will not be able to return to the login unless you place a button to log out.

2

I got one problem mixing Rg.Plugins.Popup and ZXin.Net.Mobile Scanner.

Calling the scanner inside a popup was triggering this same error. PushModalAsync solved the error, but the popup was over the scan so easy solution was make the popup invisible until the scanner was on.

    private async void FrmQrCode_Tapped(object sender, EventArgs e)
    {
        ZXingScannerPage scanPage = new ZXingScannerPage();
        scanPage.OnScanResult += (result) =>
        {
            scanPage.IsScanning = false;
            ZXing.BarcodeFormat barcodeFormat = result.BarcodeFormat;
            string type = barcodeFormat.ToString();
            Device.BeginInvokeOnMainThread(() =>
            {
                Navigation.PopModalAsync();

                this.IsVisible = true;

                Token = result.Text.Trim();
            });
        };
        this.IsVisible = false;
        await Navigation.PushModalAsync(scanPage);
    }
2

Verify that the previous page is not using a PushModalAsync. If later you use a PushAsync, you will have the error "PushAsync is not supported globally on Android, please use a NavigationPage."

kalitsov
  • 1,319
  • 3
  • 20
  • 33