web-dev-qa-db-ja.com

Xamarin.Forms-マスター/詳細ページとナビゲーション履歴の問題

Masterdetailページを使用してすべてのページにメニューを表示するアプリがあります。私のアプリでは、ナビゲーションは2つの方法で行われます。 1つはメニューから、もう1つはダッシュボードからです。そのため、別のページに移動してから[戻る]ボタンを押すと、アプリケーションが閉じます。ナビゲーション履歴は記憶していません。マスター詳細ページは以下のとおりです。

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

だから、この問題を克服する方法はありますか?

10
SoftSan

@ Sten-Petrovが言ったことのように:あなたは詳細ページを置き換えており、履歴メカニズムをトリガーしていません。履歴メカニズムをトリガーするには、詳細ページのナビゲーションプロパティでPushAsync(Page)を実行する必要があります。

あなたの例では、NavigateToを変更します。

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

これはコンテンツを置き換えるものではありませんが、必要な戻るボタン機能を備えた新しいページを表示します。

マスター-詳細ページで戻るボタン機能が必要な場合は、バックスタックプロセスをカスタマイズする必要がありますが、私の意見では、それだけの価値はありません。その場合は、別のページ/ナビゲーション構造に移動するだけです。

18
PlasmaEye

ここでの問題は、ナビゲーションスタックを使用してページの遷移を実行するのではなく、代わりに自分のページのアイテムを置き換えるため、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から、詳細が設定されている部分を除く):

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

私は同じ問題を抱えていました、Detail.Navigation.PushAsync(itemSelected) make hamburger menuvanishそしてまた別のサブクラスを作成してコードとパフォーマンスに関する大きな作業のように思われました。そこで、マスター詳細ページに独自のスタックデータ型を使用することにしました。追跡とコードを維持するのは少し注意が必要でしたが、正常に機能していました。

アプリの読み込み時に現在の詳細ページで初期化し、選択したアイテムごとにスタックの一番上に新しいページをプッシュします。

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