web-dev-qa-db-fra.com

Xamarin.Forms - Problème d'historique de navigation et de page maître/détail

J'ai une application qui utilise la page masterdetail pour afficher le menu dans toutes les pages. La navigation s'effectue dans les deux sens dans mon application. un dans le menu et la deuxième manière à partir du tableau de bord. Donc, si je navigue vers une autre page et que j'appuie sur le bouton "RETOUR", l'application se ferme. Il ne se souvient pas de l'historique de navigation. La page de détail principale est la suivante:

 public class RootPage : MasterDetailPage
    {
        public RootPage ()
        {
            var menuPage = new MenuPage ();

            menuPage.Menu.ItemSelected += (sender, e) => NavigateTo (e.SelectedItem as MenuItem);

            Master = menuPage;
            Detail = new NavigationPage (new ContractsPage ());
        }

        void NavigateTo (MenuItem menu)
        {
            Page displayPage = (Page)Activator.CreateInstance (menu.TargetType);
            Detail =    new NavigationPage (displayPage);
            IsPresented = false;
        }
    }

donc des idées comment surmonter ce problème?

10
SoftSan

Comme ce que @ Sten-Petrov a dit: vous remplacez la page de détail et ne déclenchez pas le mécanisme de l'historique. Pour déclencher le mécanisme de l'historique, vous devez créer une PushAsync (Page) dans la propriété Navigation de la page Détails.

Dans votre exemple, modifiez NavigateTo:

 void NavigateTo (MenuItem menu)
 {
     Page displayPage = (Page)Activator.CreateInstance (menu.TargetType);
     Detail.Navigation.PushAsync(displayPage);
 }

Cela ne remplacera pas le contenu mais ouvrira une nouvelle page avec la fonctionnalité de bouton Précédent souhaitée. 

Si vous souhaitez utiliser le bouton Précédent avec la page Master-Detail, vous devrez personnaliser le processus de pile arrière, ce qui, à mon avis, ne vaut pas la peine. Dans ce cas, déplacez-vous simplement vers une structure de page/navigation différente.

18
PlasmaEye

Le problème ici est que vous n'utilisez pas la pile de Navigation pour effectuer des transitions de vos pages, mais plutôt pour remplacer un élément sur votre propre page. Il n'y a donc pas d'historique de navigation à revenir "en arrière" autre que la page ayant accédé à votre MasterDetailPage.

Vous pouvez résoudre le problème en créant une nouvelle classe MenuMasterDetail.cs qui hérite de MasterDetailPage et initialise un menu, puis créez MenuItem_A_Page.xaml (ou .cs) qui hérite de votre base commune et de votre classe de base commune, vous utiliserez Navigation.PushAsync(...) pour la transition. entre les pages.

classe de base:

public class MenuDetailPage: MasterDetailPage{
  public MenuDetailPage(): base(){
    this.Master = BuildMyMenuListHere(); // the menu items will also define navigation targets
  }
}

sous-classe dans CS:

public class FirstDetailWithMenuPage: MenuDetailPage{
  public FirstDetailWithMenuPage()
    : base() // this creates the menu
  {
    this.Detail = new StackLayout{  // change this however you need
      Children = {
        new Label { Text = "This is the first page" },
        new Button { Text= "Ok"},
     }
  }
}

Sous-classe en XAML (avec le CS d'en haut, moins la partie où le détail est défini):

<local:FirstDetailWithMenuPage namespace:YourNamespace;Assembly=YourAssemblyName" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:local="clr-n xmlns:x="http://schemas.Microsoft.com/winfx/2009/xaml" x:Class="FirstDetailWithMenuPage">
    <local:FirstDetailWithMenuPage.Detail>
...

Mettez également à jour votre App.cs pour renvoyer une page de navigation avec la première page maître/détail que vous avez (et non la base):

App.cs:

public static Page GetMainPage ()
{
  return new NavigationPage(new FirstDetailWithMenuPage());
}
4
Sten Petrov

J'avais le même problème, Detail.Navigation.PushAsync(itemSelected) fait hamburger menu vanish et la création d'une autre sous-classe à conserver semblait bien travailler sur le code et les performances. J'ai donc décidé d'utiliser mon propre type de données de pile pour la page de détail principal. Il était un peu difficile de garder trace et le code, mais cela fonctionnait bien.

Initialisez-le lors du chargement de l'application avec la page de détails actuelle et pour chaque élément sélectionné. Placez une nouvelle page au-dessus de la pile.

public partial class MyMasterDetailPage: MasterDetailPage
    {
        private Stack navigationStack = new Stack();
        public MyMasterDetailPage()
        {
            InitializeComponent();
            navigationStack.Push(Detail);
            try
            {
                masterPage.listView.ItemSelected += OnItemSelected;

            }
            catch (Exception exc)
            {

                System.Diagnostics.Debug.WriteLine(exc.Message);
            }

        }

Remplacer OnBackButtonPressed() dans le même code de page derrière 

        protected override bool OnBackButtonPressed()
        {
            try
            {
                var lastPage = navigationStack.Pop();
                if (lastPage.Equals(Detail))
                    lastPage = navigationStack.Pop();

                Detail = (Page)lastPage;
                IsPresented = false;

               // to avoid app close when complete pop and new page is Push on top of it 
                if (navigationStack.Count == 0) 
                    navigationStack.Push(Detail);
                return true;
            }
            catch (Exception)
            {

                return base.OnBackButtonPressed();
            }
        }
0
Prateek