В Xamarin.Forms-Master / подробная страница и история навигации

У меня есть приложение, которое использует страницу masterdetail для отображения меню на всей странице. Навигация происходит в двух направлениях в моем приложении. один из меню и второй способ от Dashboard. поэтому, если я перейду на другую страницу, а затем нажмите кнопку "назад", она закроет приложение. Он не помнит историю навигации. Страница мастер подробно, как показано ниже:

 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;
        }
    }

итак, есть идеи, как преодолеть эту проблему?

3 ответов


Как сказал @Sten-Petrov: вы заменяете страницу сведений и не запускаете механизм истории. Чтобы запустить механизм истории, Вам нужно будет выполнить PushAsync (Page) в свойстве навигации страницы сведений.

в вашем примере измените NavigateTo:

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

Это не заменит содержимое, но вызовет новую страницу с функцией кнопки "Назад", которую вы хотите.

Если вы хотите функциональность кнопки назад с Master-Detail page тогда вам нужно будет настроить процесс заднего стека, который, на мой взгляд, не стоит. В этом случае просто перейдите к другой структуре страницы/навигации.


проблема здесь в том, что вы не используете стек навигации для выполнения переходов ваших страниц, а вместо этого заменяете элемент на своей странице, поэтому нет истории навигации, чтобы вернуться "назад", кроме страницы, которая перешла на вашу MasterDetailPage.

вы можете решить проблему, создав новый MenuMasterDetail.класс cs, который наследует MasterDetailPage и инициализирует меню, затем создает MenuItem_A_Page.xaml (или .cs), которые наследуются от вашей общей базы и в вашем общем базовый класс вы будете использовать Navigation.PushAsync(...) для перехода между страницами.

базовый класс:

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

подкласс в 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"},
     }
  }
}

подкласс в XAML (вместе с CS сверху, минус часть, где установлена деталь):

<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>
...

также обновите приложение.cs для возврата страницы навигации с первой главной / подробной страницей, которая у вас есть (не базовая):

App.cs:

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

у меня была такая же проблема,Detail.Navigation.PushAsync(itemSelected) делает гамбургер меню исчезает а также создание другого подкласса для сохранения казалось большой работой над кодом и производительностью. Поэтому я решил использовать свой собственный тип данных стека для главной страницы сведений. Было немного сложно отслеживать и кодировать, но работать нормально.

инициализируйте его при загрузке приложения с текущей страницей сведений и для каждого выбранного элемента нажмите новую страницу поверх стека.

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);
            }

        }

переопределить OnBackButtonPressed() in же код страницы

        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();
            }
        }