Xamarin.Forms - 主/详细页面和导航历史记录问题

时间:2015-01-08 09:31:45

标签: c# master-detail xamarin.forms

我有一个应用程序,它使用masterdetail页面在所有页面中显示菜单。导航在我的应用程序中以两种方式发生。一个来自菜单,另一个来自仪表板。所以如果我导航到另一个页面,然后按" BACK"按钮,它关闭应用程序。它不记得导航历史记录。 主详细信息页面如下:

 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 个答案:

答案 0 :(得分:18)

就像@ Sten-Petrov所说:你正在取代细节页面而不是触发历史机制。要触发历史记录机制,您需要在详细信息页面的导航属性上执行PushAsync(页面)。

在您的示例中,更改NavigateTo:

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

这不会替换内容,但会打开一个带有所需后退按钮功能的新页面。

如果您想要使用Master-Detail页面返回按钮功能,那么您需要自定义后台堆栈过程,在我看来,这是不值得的。在这种情况下,只需移动到不同的页面/导航结构。

答案 1 :(得分:4)

这里的问题是你没有使用导航堆栈来执行页面的转换,而是替换你自己页面上的项目,因此除了导航到你的MasterDetailPage的页面之外,没有导航历史记录可以“返回”

您可以通过创建一个继承MasterDetailPage并初始化菜单的新MenuMasterDetail.cs类来解决此问题,然后创建从您的公共库继承的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,减去设置Detail的部分):

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

同时更新您的App.cs以返回包含您拥有的第一个主/详细页面的导航页面(不是基本页面):

App.cs:

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

答案 2 :(得分:0)

我遇到了同样的问题,Detail.Navigation.PushAsync(itemSelected)使汉堡包菜单消失,并且创建了另一个子类来保留似乎在代码和性能方面的巨大工作。因此,我决定将自己的堆栈数据类型用于Master detail页面。保持跟踪和编码有点棘手,但工作正常。

在应用程序加载时使用当前的“详细信息”页面将其初始化,并针对所选的每个项目将其推入堆栈顶部。

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