Xamarin Forms: Exit prompt is not working when use Navigation.PushAsync for loading a new page.

Sreejith Sree 1,251 Reputation points
2021-01-12T08:18:43.193+00:00

I am showing a prompt for the exit when a user taps the device back button on the home page.

My code:

private bool AcceptBack;
public static Action EmulateBackPressed;

protected override bool OnBackButtonPressed()
{
    bool value = true;
    var i = this.Children.IndexOf(this.CurrentPage);
    if (i == 0)
    {
        if (AcceptBack)
            return false;
        PromptForExit();
        value = true;
    }
    else
    {
        CurrentPage = Children[0];
        value = true;
    }
    return value;
}

private async void PromptForExit()
{
    if (await DisplayAlert("Confirm to Quit?", "Are you sure you want to quit?", "Yes", "No"))
    {
        AcceptBack = true;
        EmulateBackPressed();
    }
}

On MainActivity:

Pages.CarouselHomePage.EmulateBackPressed = OnBackPressed;

It was working fine when I use the Navigation.PushModalAsync to load new pages. Currently, I am using Navigation.PushAsync for loading new pages; after that, the exit prompt is not showing. When I tap the backbutton it showing the previous page. In my case the homepage is a CarouselPage having 3 children.

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,310 questions
0 comments No comments
{count} votes

Accepted answer
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 70,466 Reputation points Microsoft Vendor
    2021-01-12T11:22:46.18+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    You need to move the logic of handling navigation to the method OnAppearing .As in the constructor the page has not finished loading yet .

       protected override void OnAppearing()  
               {  
                   base.OnAppearing();  
         
                   try  
                   {  
                       string login = Application.Current.Properties["islogin"].ToString();  
         
                       if (login == "true")  
                       {  
                           Navigation.PushAsync(new CarouselHomePage(), true);  
                       }  
                   }  
                   catch (Exception e)  
                   {  
                       Debug.WriteLine("IsLogin::" + e);  
                   }  
               }  
    

    n addition , it should be noted that adding or updating a value in the App.Current.Properties dictionary does not automatically persist it to permanent storage.

    So you need to called the method SavePropertiesAsync()

       Application.Current.Properties["islogin"] = "true";  
       Application.Current.SavePropertiesAsync();  
    

    Best Regards,

    Leon Lu


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

2 additional answers

Sort by: Most helpful
  1. Alessandro Caliaro 4,181 Reputation points
    2021-01-12T12:01:54.837+00:00

    I have created a sample for you
    I have removed Navigation because is a problem with Login to have a good Navigation. You could add Navigation to CarouselViewPage if you need to open other pages.

    Take a look

    https://www.dropbox.com/s/qjbp8zej8fi0ako/MapDemo.rar?dl=0

    1 person found this answer helpful.

  2. Alessandro Caliaro 4,181 Reputation points
    2021-01-12T08:54:53.193+00:00

    maybe (but I am not sure) you have to await PromptForExit();

    This works for me:

    protected override bool OnBackButtonPressed()
        {
            Device.BeginInvokeOnMainThread(async () =>
            {
                var ret = await Application.Current.MainPage.DisplayAlert("Attention", "Close the page?", "Yes", "No");
    
                if (ret)
                    await Application.Current.MainPage.Navigation.PopAsync();
            });
            return true;
    
            //return base.OnBackButtonPressed();
        }