0
votes

I have an event that fires on Android Hardware back button pressed. This is how its implemented in the AppShell class:

public event EventHandler<CancelEventArgs> BackButtonPressed;

protected override bool OnBackButtonPressed()
{
    var cancelArgs = new CancelEventArgs();
    BackButtonPressed?.Invoke(this, cancelArgs);
    return (cancelArgs.Cancel) ? true : base.OnBackButtonPressed();
}

Elsewhere I have subscribed to this event in a view model. Here is the code:

private async void _AppShell_BackButtonPressed(object sender, CancelEventArgs e)
{
     if (!await App.Current.MainPage.DisplayAlert(
          "My App",
          "Are you sure you want to cancel, you have unsaved changes",
          "ok",
          "cancel"))
          {
               e.Cancel = true;
          }
}

Some other stuff happens before DisplayAlert, but for simplicity I have removed all that.

The issue is that when DisplayAlert is called, the execution returns to OnBackButtonPressed and because of this the cancel argument is not set accordingly. So it seems that DisplayAlert is not waiting for the user to respond. How can this problem be solved?

Apologies if I've been unclear, I can provide further clarification.. just ask:)

Any help on this would be much appreciated.

2

2 Answers

0
votes

By design my solution is not feasible. The answer is to always cancel out of the OnBackButtonPressed() method and raise a MessagingCenter event like so:

protected override bool OnBackButtonPressed()
{
     MessagingCenter.Send(this, "ANDROID_HARDWARE_BACK_BUTTON_TAPPED");
     return true;
}

Then when you handle the event call:

await Shell.Current.Navigation.PopAsync(true);

instead of:

await Shell.Current.SendBackButtonPressed

From this I ascertain the best practice is to always use PopAsync instead of SendBackButtonPressed to save you from unwanted recursion.

0
votes

What about using Display Alert by overriding the OnAppearing() method?

protected async override void OnAppearing() {
  var result = await App.Current.MainPage.DisplayAlert(
    "My App",
    "Are you sure you want to cancel, you have unsaved changes",
    "ok",
    "cancel"
  )
  base.OnAppearing();
  if (!result)
  {
    e.Cancel = true;
  }
}