【问题标题】:Xamarin.Forms - Master/detail page and navigation history issueXamarin.Forms - 主/详细页面和导航历史记录问题
【发布时间】:2015-03-06 08:55:13
【问题描述】:

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

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

那么有什么想法可以解决这个问题吗?

【问题讨论】:

    标签: c# master-detail xamarin.forms


    【解决方案1】:

    就像@Sten-Petrov 所说的那样:您正在替换详细信息页面而不是触发历史记录机制。要触发历史机制,您需要在 Detail 页面的 Navigation 属性上执行 PushAsync(Page)。

    在您的示例中,更改 NavigateTo:

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

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

    如果您想要主-详细信息页面的后退按钮功能,那么您需要自定义后退堆栈过程,在我看来,这是不值得的。在这种情况下,只需移动到不同的页面/导航结构即可。

    【讨论】:

    • 这正是我解决问题所需要的——谢谢!!
    【解决方案2】:

    这里的问题是您没有使用导航堆栈来执行页面的转换,而是替换您自己页面上的项目,因此除了导航到您的 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());
    }
    

    【讨论】:

    • 感谢@Sten Petrov。如果我使用 push aync 使用导航堆栈,那么问题是菜单消失了。而我想在所有页面中保留菜单。所以我在详细页面中加载每个页面。你能提供一个关于你提到的方法的样本或类似的东西吗?
    • 这就是为什么我的建议是在基类中定义菜单,然后继承它来更改细节,这样你就可以得到 MasterDetailPage 的菜单,但你仍然可以使用导航堆栈
    • 感谢@Sten Petrov 提供样品。我试图实现,但我得到一个错误,比如 Android 不支持 PushAsync。我尝试使用 Navigation.PushAsync() 推送页面。另外我必须先设置详细信息页面,因为它不允许我只使用主页面。详情页需要在 Menudetailpage() 中添加。否则会抛出错误。
    • 嗨@Sten Petrov 非常感谢您的投入。通过您提供的代码和方向,我几乎接近我想要实现的目标。我现在只有一个问题是,当您转到任何详细信息页面,然后按返回按钮或单击菜单时,它将首先显示 FirstPage(在我的情况下为主页),然后我需要再次单击菜单才能实际显示图标。您可以在github.com/softsan/MasterDetailMenu 找到样品。你能看看它并指导我做错了什么吗?非常感谢您的支持。另外,在 iOS 上我看不到菜单。
    • 嗨@Sten Petrov - 你发现那个样本有什么问题吗?
    【解决方案3】:

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

    在应用加载时使用当前详细信息页面初始化它,并为每个选定的项目将新页面推送到堆栈顶部。

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

    【讨论】:

      猜你喜欢
      • 2019-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-13
      • 1970-01-01
      相关资源
      最近更新 更多