web-dev-qa-db-fra.com

Comment intercepter le bouton Précédent de la barre de navigation cliqué dans Xamarin Forms?

J'ai une page de formulaire xamarin où un utilisateur peut mettre à jour des données dans un formulaire. J'ai besoin d'intercepter la barre de navigation. Bouton Précédent Cliquez sur ce bouton pour avertir l'utilisateur si des données n'ont pas été sauvegardées. Comment le faire?

Je suis en mesure d'intercepter le bouton de barre de navigation cliqué dans Android à l'aide de la fonction Android.MainActivity.OnBackPressed(), mais cet événement est déclenché uniquement sur le bouton de barre d'arrière cliqué, pas sur le bouton de barre de navigation précédent.

J'ai aussi essayé d'ignorer Xamarin.Forms.NavigationPageOnBackButtonPressed() mais cela ne fonctionne pas. Pourquoi? Quelqu'un a-t-il déjà résolu ce problème? 

J'ai aussi essayé en surchargeant OnDisappear(), il y a deux problèmes:

  1. La page a déjà visuellement disparu alors le "Êtes-vous sûr?" La boîte de dialogue apparaît sur la page précédente.
  2. Impossible d'annuler l'action de retour. 

Alors, est-il possible d'intercepter la touche de retour de la barre de navigation?

12
Amrut

J'ai été en mesure d'afficher une boîte de dialogue de confirmation pouvant annuler la navigation en remplaçant les méthodes suivantes dans FormsApplicationActivity. 

  // navigation back button
  public override bool OnOptionsItemSelected(IMenuItem item)
  {
     if (item.ItemId == 16908332)
     {
        var currentViewModel = (IViewModel)navigator.CurrentPage.BindingContext;
        currentViewModel.CanNavigateFromAsync().ContinueWith(t =>
        {
           if (t.Result)
           {
              navigator.PopAsync();
           }
        }, TaskScheduler.FromCurrentSynchronizationContext());
        return false;
     }
     else
     {
        return base.OnOptionsItemSelected(item);
     }
  }

  // hardware back button
  public async override void OnBackPressed()
  {
     var currentViewModel = (IViewModel)navigator.CurrentPage.BindingContext;

     // could display a confirmation dialog (ex: "Cancel changes?")
     var canNavigate = await currentViewModel.CanNavigateFromAsync();
     if (canNavigate)
     {
        base.OnBackPressed();
     }
  }

Navigator.CurrentPage est un wrapper autour du service INavigation. Je n'ai pas à annuler la navigation à partir de pages modales, je ne gère donc que le NavigationStack.

this.navigation.NavigationStack[this.navigation.NavigationStack.Count - 1];
8
barry

Il s’agit là d’une tâche difficile en soi et la seule façon dont j’ai pu la maîtriser consistait à supprimer entièrement le bouton Précédent puis à gérer la navigation arrière à partir d’un bouton «Enregistrer». 

J'ai fait une brève recherche sur le forum Xamarin.Forms et les suggestions suivantes ont été suggérées:

public override bool OnOptionsItemSelected(Android.Views.IMenuItem item)
{
    return false;
}

Le lien pour le post est le suivant:

https://forums.xamarin.com/discussion/21631/is-there-nay-way-of-cancelling-the-back-button-event-from-the-navigationpage

0
JordanMazurke

Comme cela a déjà été dit - vous ne pouvez pas faire cela multi-plateforme. Cependant, vous pouvez le gérer de manière native avec un effort consi- dérable, sans beaucoup d'efforts: https://theconfuzedsourcecode.wordpress.com/2017/03/12/lets-override-navigation-bar-back-button-click-in-xamarin- formes/

L'article couvre iOS et Android. Si vous avez un projet UWP, vous devrez trouver votre propre solution.

Edit: Voici la solution UWP! En fait, il s’est avéré être assez simple: il n’ya qu’un bouton de retour et les formulaires sont pris en charge.

    protected override bool OnBackButtonPressed()
    {
        if (Device.RuntimePlatform.Equals(Device.UWP))
        {
            OnClosePageRequested();
            return true;
        }
        else
        {
            base.OnBackButtonPressed();
            return false;
        }
    }

    async void OnClosePageRequested()
    {
        var tdvm = (TaskDetailsViewModel)BindingContext;
        if (tdvm.CanSaveTask())
        {
            var result = await DisplayAlert("Wait", "You have unsaved changes! Are you sure you want to go back?", "Discard changes", "Cancel");

            if (result)
            {
                tdvm.DiscardChanges();
                await Navigation.PopAsync(true);
            }
        }
        else
        {
            await Navigation.PopAsync(true);
        }           
    }
0
AXE