階層ナビゲーションHierarchical Navigation

サンプルのダウンロードサンプルのダウンロードDownload Sample Download the sample

NavigationPage クラスは、ユーザーが前後を希望どおりにページを移動することができる階層ナビゲーション エクスペリエンスを提供します。このクラスは、Page オブジェクトの後入れ先出し (LIFO) スタックとしてナビゲーションを提供します。この記事では、NavigationPage クラスを使用してページのスタックでナビゲーションを実行する方法について説明します。The NavigationPage class provides a hierarchical navigation experience where the user is able to navigate through pages, forwards and backwards, as desired. The class implements navigation as a last-in, first-out (LIFO) stack of Page objects. This article demonstrates how to use the NavigationPage class to perform navigation in a stack of pages.

1 つのページから別のページに移動するには、次の図に示すように、アプリケーションは新しいページを、そこでアクティブなページとなるナビゲーション スタックにプッシュします。To move from one page to another, an application will push a new page onto the navigation stack, where it will become the active page, as shown in the following diagram:

ナビゲーション スタックにページをプッシュする

次の図に示すように、前のページに戻るには、アプリケーションは現在のページをナビゲーション スタックからポップします。そして新しい最上位のページがアクティブ ページになります。To return back to the previous page, the application will pop the current page from the navigation stack, and the new topmost page becomes the active page, as shown in the following diagram:

ナビゲーション スタックからページをポップする

ナビゲーション メソッドは、任意の Page 派生型の Navigation プロパティによって公開されます。Navigation methods are exposed by the Navigation property on any Page derived types. これらのメソッドには、ページをナビゲーション スタックにプッシュし、ナビゲーション スタックからページをポップし、スタック操作を実行する機能があります。These methods provide the ability to push pages onto the navigation stack, to pop pages from the navigation stack, and to perform stack manipulation.

ナビゲーションを実行するPerforming Navigation

階層ナビゲーションでは、NavigationPage クラスは ContentPage オブジェクトのスタック間をナビゲートするために使用されます。In hierarchical navigation, the NavigationPage class is used to navigate through a stack of ContentPage objects. 次のスクリーンショットは、各プラットフォームでの NavigationPage のメイン コンポーネントを示します。The following screenshots show the main components of the NavigationPage on each platform:

NavigationPage コンポーネント

NavigationPage のレイアウトは、プラットフォームによって異なります。The layout of a NavigationPage is dependent on the platform:

  • iOS では、ナビゲーション バーがページの上部にあり、タイトルが表示され、前のページに戻る [戻る] ボタンがあります。On iOS, a navigation bar is present at the top of the page that displays a title, and that has a Back button that returns to the previous page.
  • Android では、ナビゲーション バーがページの上部にあり、タイトル、アイコンと、前のページに戻る [戻る] ボタンが表示されています。On Android, a navigation bar is present at the top of the page that displays a title, an icon, and a Back button that returns to the previous page. Android プラットフォーム固有プロジェクトでは、アイコンは MainActivity クラスを修飾する [Activity] 属性で定義されています。The icon is defined in the [Activity] attribute that decorates the MainActivity class in the Android platform-specific project.
  • ユニバーサル Windows プラットフォームでは、ナビゲーション バーはページの上部にあり、タイトルが表示されています。On the Universal Windows Platform, a navigation bar is present at the top of the page that displays a title.

いずれのプラットフォームでも、Page.Title プロパティの値がページ タイトルとして表示されます。On all the platforms, the value of the Page.Title property will be displayed as the page title. さらに、IconColor プロパティを、ナビゲーション バーのアイコンに適用される Color に設定できます。In addition, the IconColor property can be set to a Color that's applied to the icon in the navigation bar.

注意

NavigationPageContentPage インスタンスのみで作成することをお勧めします。It's recommended that a NavigationPage should be populated with ContentPage instances only.

ルート ページを作成するCreating the Root Page

ナビゲーション スタックに追加された最初のページは、アプリケーションの ルート ページとなります。次のコード例に、これを実現する方法を示しています。The first page added to a navigation stack is referred to as the root page of the application, and the following code example shows how this is accomplished:

public App ()
{
  MainPage = new NavigationPage (new Page1Xaml ());
}

これにより、Page1Xaml ContentPage インスタンスがナビゲーション スタックにプッシュされるようになります。そこがアクティブ ページであり、アプリケーションのルート ページとなります。This causes the Page1Xaml ContentPage instance to be pushed onto the navigation stack, where it becomes the active page and the root page of the application. これを次のスクリーンショットに示します。This is shown in the following screenshots:

ナビゲーション スタックのルート ページ

注意

NavigationPage インスタンスの RootPage プロパティを使用すると、ナビゲーション スタック内の最初のページにアクセスできます。The RootPage property of a NavigationPage instance provides access to the first page in the navigation stack.

ナビゲーション スタックにページをプッシュするPushing Pages to the Navigation Stack

Page2Xaml にナビゲートするには、次のコード例で示すように、現在のページの Navigation プロパティで PushAsync メソッドを起動する必要があります。To navigate to Page2Xaml, it is necessary to invoke the PushAsync method on the Navigation property of the current page, as demonstrated in the following code example:

async void OnNextPageButtonClicked (object sender, EventArgs e)
{
  await Navigation.PushAsync (new Page2Xaml ());
}

これにより、Page2Xaml インスタンスがナビゲーション スタックにプッシュされるようになり、そこがアクティブ ページとなります。This causes the Page2Xaml instance to be pushed onto the navigation stack, where it becomes the active page. これを次のスクリーンショットに示します。This is shown in the following screenshots:

ナビゲーション スタックにプッシュされるページ

PushAsync メソッドが呼び出されると、次のイベントが発生します。When the PushAsync method is invoked, the following events occur:

  • PushAsync を呼び出すページでは、OnDisappearing のオーバーライドが呼び出されます。The page calling PushAsync has its OnDisappearing override invoked.
  • ナビゲート先のページでは、OnAppearing のオーバーライドが呼び出されます。The page being navigated to has its OnAppearing override invoked.
  • PushAsync タスクが完了します。The PushAsync task completes.

ただし、これらのイベントが発生する正確な順序はプラットフォームによって異なります。However, the precise order in which these events occur is platform dependent. 詳細については、Charles Petzold 氏著作の :::no-loc(Xamarin.Forms)::: ブックの第 24 章を参照してください。For more information, see Chapter 24 of Charles Petzold's :::no-loc(Xamarin.Forms)::: book.

注意

OnDisappearing および OnAppearing のオーバーライドの呼び出しは、ページ ナビゲーションを示す保証として扱うことはできません。Calls to the OnDisappearing and OnAppearing overrides cannot be treated as guaranteed indications of page navigation. たとえば、iOS では、アプリケーションの終了時にアクティブ ページで OnDisappearing のオーバーライドが呼び出されます。For example, on iOS, the OnDisappearing override is called on the active page when the application terminates.

ナビゲーション スタックからページをポップするPopping Pages from the Navigation Stack

アクティブ ページは、これが物理的なボタンであるか画面上のボタンであるかどうかにかかわらず、デバイスの [戻る] ボタンを押すことによってナビゲーション スタックからポップすることができます。The active page can be popped from the navigation stack by pressing the Back button on the device, regardless of whether this is a physical button on the device or an on-screen button.

元のページにプログラムを使用して戻るには、Page2Xaml インスタンスが、次のコード例のとおり PopAsync メソッドを起動する必要があります。To programmatically return to the original page, the Page2Xaml instance must invoke the PopAsync method, as demonstrated in the following code example:

async void OnPreviousPageButtonClicked (object sender, EventArgs e)
{
  await Navigation.PopAsync ();
}

これにより、ナビゲーション スタックから Page2Xaml インスタンスが削除され、新しい最上位のページがアクティブ ページとなります。This causes the Page2Xaml instance to be removed from the navigation stack, with the new topmost page becoming the active page. PopAsync メソッドが呼び出されると、次のイベントが発生します。When the PopAsync method is invoked, the following events occur:

  • PopAsync を呼び出すページでは、OnDisappearing のオーバーライドが呼び出されます。The page calling PopAsync has its OnDisappearing override invoked.
  • 戻り先のページでは、OnAppearing のオーバーライドが呼び出されます。The page being returned to has its OnAppearing override invoked.
  • PopAsync タスクが復帰します。The PopAsync task returns.

ただし、これらのイベントが発生する正確な順序はプラットフォームによって異なります。However, the precise order in which these events occur is platform dependent. 詳細については、Charles Petzold 氏著作の :::no-loc(Xamarin.Forms)::: ブックの第 24 章を参照してください。For more information see Chapter 24 of Charles Petzold's :::no-loc(Xamarin.Forms)::: book.

各ページの Navigation プロパティには、PushAsync および PopAsync メソッドだけでなく、次のコード例に示すように、PopToRootAsync メソッドも用意されています。As well as PushAsync and PopAsync methods, the Navigation property of each page also provides a PopToRootAsync method, which is shown in the following code example:

async void OnRootPageButtonClicked (object sender, EventArgs e)
{
  await Navigation.PopToRootAsync ();
}

このメソッドは、ルート Page 以外のすべてをナビゲーション スタックからポップします。そのため、アプリケーションのルート ページがアクティブ ページになります。This method pops all but the root Page off the navigation stack, therefore making the root page of the application the active page.

ページ遷移をアニメーション化するAnimating Page Transitions

各ページの Navigation プロパティには、次のコード例に示すように、ナビゲーション中にページ アニメーションを表示するかどうかを制御する boolean パラメーターを含むオーバーライドされたプッシュおよびポップ メソッドも用意されています。The Navigation property of each page also provides overridden push and pop methods that include a boolean parameter that controls whether to display a page animation during navigation, as shown in the following code example:

async void OnNextPageButtonClicked (object sender, EventArgs e)
{
  // Page appearance not animated
  await Navigation.PushAsync (new Page2Xaml (), false);
}

async void OnPreviousPageButtonClicked (object sender, EventArgs e)
{
  // Page appearance not animated
  await Navigation.PopAsync (false);
}

async void OnRootPageButtonClicked (object sender, EventArgs e)
{
  // Page appearance not animated
  await Navigation.PopToRootAsync (false);
}

boolean パラメーターを false に設定すると、ページ遷移アニメーションが無効になります。また、パラメーターを true に設定すると、基となるプラットフォームでサポートされている場合はページ遷移アニメーションが有効になります。Setting the boolean parameter to false disables the page-transition animation, while setting the parameter to true enables the page-transition animation, provided that it is supported by the underlying platform. ただし、プッシュとポップのメソッドでこのパラメーターが指定されていない場合は、既定でアニメーションが有効になります。However, the push and pop methods that lack this parameter enable the animation by default.

ナビゲーション時にデータを渡すPassing Data when Navigating

場合によっては、ナビゲーション中に、あるページから別のページにデータを渡す必要があります。Sometimes it's necessary for a page to pass data to another page during navigation. これを実現する 2 つの手法では、ページ コンストラクターを介してデータを渡し、新しいページの BindingContext をデータに設定しています。Two techniques for accomplishing this are passing data through a page constructor, and by setting the new page's BindingContext to the data. これから、それぞれについて順番に説明します。Each will now be discussed in turn.

ページ コンストラクターを介してデータを渡すPassing Data through a Page Constructor

ナビゲーション中に別のページにデータを渡す最も簡単な手法は、次のコード例で示すように、ページ コンストラクター パラメーターを使用することです。The simplest technique for passing data to another page during navigation is through a page constructor parameter, which is shown in the following code example:

public App ()
{
  MainPage = new NavigationPage (new MainPage (DateTime.Now.ToString ("u")));
}

このコードでは、現在の日付と時刻を ISO8601 形式で渡す MainPage インスタンスを作成します。これは NavigationPage インスタンスでラップされています。This code creates a MainPage instance, passing in the current date and time in ISO8601 format, which is wrapped in a NavigationPage instance.

MainPage インスタンスは、次のコード例に示すように、コンストラクター パラメーターを使用してデータを受け取ります。The MainPage instance receives the data through a constructor parameter, as shown in the following code example:

public MainPage (string date)
{
  InitializeComponent ();
  dateLabel.Text = date;
}

次のスクリーンショットに示すように、Label.Text プロパティを設定することでデータがページに表示されます。The data is then displayed on the page by setting the Label.Text property, as shown in the following screenshots:

ページ コンストラクターを介して渡されるデータ

BindingContext を介してデータを渡すPassing Data through a BindingContext

ナビゲーション中に別のページにデータを渡すもう 1 つの方法は、次のコード例に示すように、新しいページの BindingContext をデータに設定することです。An alternative approach for passing data to another page during navigation is by setting the new page's BindingContext to the data, as shown in the following code example:

async void OnNavigateButtonClicked (object sender, EventArgs e)
{
  var contact = new Contact {
    Name = "Jane Doe",
    Age = 30,
    Occupation = "Developer",
    Country = "USA"
  };

  var secondPage = new SecondPage ();
  secondPage.BindingContext = contact;
  await Navigation.PushAsync (secondPage);
}

このコードでは、SecondPage インスタンスの BindingContextContact インスタンスに設定し、SecondPage にナビゲートします。This code sets the BindingContext of the SecondPage instance to the Contact instance, and then navigates to the SecondPage.

次の XAML コード例に示すように、SecondPage ではデータ バインディングを使用して Contact インスタンス データを表示します。The SecondPage then uses data binding to display the Contact instance data, as shown in the following XAML code example:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="PassingData.SecondPage"
             Title="Second Page">
    <ContentPage.Content>
        <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
            <StackLayout Orientation="Horizontal">
                <Label Text="Name:" HorizontalOptions="FillAndExpand" />
                <Label Text="{Binding Name}" FontSize="Medium" FontAttributes="Bold" />
            </StackLayout>
            ...
            <Button x:Name="navigateButton" Text="Previous Page" Clicked="OnNavigateButtonClicked" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

次のコード例は、C# でデータ バインディングを実行する方法を示しています。The following code example shows how the data binding can be accomplished in C#:

public class SecondPageCS : ContentPage
{
  public SecondPageCS ()
  {
    var nameLabel = new Label {
      FontSize = Device.GetNamedSize (NamedSize.Medium, typeof(Label)),
      FontAttributes = FontAttributes.Bold
    };
    nameLabel.SetBinding (Label.TextProperty, "Name");
    ...
    var navigateButton = new Button { Text = "Previous Page" };
    navigateButton.Clicked += OnNavigateButtonClicked;

    Content = new StackLayout {
      HorizontalOptions = LayoutOptions.Center,
      VerticalOptions = LayoutOptions.Center,
      Children = {
        new StackLayout {
          Orientation = StackOrientation.Horizontal,
          Children = {
            new Label{ Text = "Name:", FontSize = Device.GetNamedSize (NamedSize.Medium, typeof(Label)), HorizontalOptions = LayoutOptions.FillAndExpand },
            nameLabel
          }
        },
        ...
        navigateButton
      }
    };
  }

  async void OnNavigateButtonClicked (object sender, EventArgs e)
  {
    await Navigation.PopAsync ();
  }
}

次のスクリーンショットに示すように、一連の Label コントロールによってデータがページに表示されます。The data is then displayed on the page by a series of Label controls, as shown in the following screenshots:

BindingContext を介して渡されるデータ

データ バインディングの詳細については、「Data Binding Basics」 (データ バインディングの基礎) を参照してください。For more information about data binding, see Data Binding Basics.

ナビゲーション スタックの操作Manipulating the Navigation Stack

Navigation プロパティは、ナビゲーション スタックのページを取得する NavigationStack プロパティを公開します。The Navigation property exposes a NavigationStack property from which the pages in the navigation stack can be obtained. :::no-loc(Xamarin.Forms)::: はナビゲーション スタックへのアクセスを維持していますが、Navigation プロパティには、ページを挿入または削除することでスタックを操作するための InsertPageBefore および RemovePage メソッドが用意されています。While :::no-loc(Xamarin.Forms)::: maintains access to the navigation stack, the Navigation property provides the InsertPageBefore and RemovePage methods for manipulating the stack by inserting pages or removing them.

次の図に示すように、InsertPageBefore メソッドによって、ナビゲーション スタック内の指定されたページが既存の指定されたページの前に挿入されます。The InsertPageBefore method inserts a specified page in the navigation stack before an existing specified page, as shown in the following diagram:

ナビゲーション スタックにページを挿入する

次の図に示すように、RemovePage メソッドによって、指定されたページがナビゲーション スタックから削除されます。The RemovePage method removes the specified page from the navigation stack, as shown in the following diagram:

ナビゲーション スタックからページを削除する

これらのメソッドを使用すると、ログインに成功した後に、ログイン ページを新しいページに置き換えるなど、カスタムのナビゲーション エクスペリエンスを実現できます。These methods enable a custom navigation experience, such as replacing a login page with a new page, following a successful login. 次のコード例はこのシナリオを示しています。The following code example demonstrates this scenario:

async void OnLoginButtonClicked (object sender, EventArgs e)
{
  ...
  var isValid = AreCredentialsCorrect (user);
  if (isValid) {
    App.IsUserLoggedIn = true;
    Navigation.InsertPageBefore (new MainPage (), this);
    await Navigation.PopAsync ();
  } else {
    // Login failed
  }
}

ユーザーの資格情報が正しい場合、MainPage インスタンスは、ナビゲーション スタック内の現在のページの前に挿入されます。Provided that the user's credentials are correct, the MainPage instance is inserted into the navigation stack before the current page. 次に PopAsync メソッドによってナビゲーション スタックから現在のページが削除され、MainPage インスタンスがアクティブ ページになります。The PopAsync method then removes the current page from the navigation stack, with the MainPage instance becoming the active page.

ナビゲーション バーにビューを表示するDisplaying Views in the Navigation Bar

すべての :::no-loc(Xamarin.Forms):::View は、NavigationPage のナビゲーション バーに表示できます。Any :::no-loc(Xamarin.Forms)::: View can be displayed in the navigation bar of a NavigationPage. これを実現するには、NavigationPage.TitleView 添付プロパティを View に設定します。This is accomplished by setting the NavigationPage.TitleView attached property to a View. この添付プロパティは任意の Page に設定できます。また、PageNavigationPage にプッシュされると、NavigationPage ではプロパティの値が反映されます。This attached property can be set on any Page, and when the Page is pushed onto a NavigationPage, the NavigationPage will respect the value of the property.

タイトル ビュー サンプルから取り上げた次の例は、NavigationPage.TitleView 添付プロパティを XAML から設定する方法を示しています。The following example, taken from the Title View sample, shows how to set the NavigationPage.TitleView attached property from XAML:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="NavigationPageTitleView.TitleViewPage">
    <NavigationPage.TitleView>
        <Slider HeightRequest="44" WidthRequest="300" />
    </NavigationPage.TitleView>
    ...
</ContentPage>

C# での同等のコードを次に示します。Here is the equivalent C# code:

public class TitleViewPage : ContentPage
{
    public TitleViewPage()
    {
        var titleView = new Slider { HeightRequest = 44, WidthRequest = 300 };
        NavigationPage.SetTitleView(this, titleView);
        ...
    }
}

この結果、NavigationPage でナビゲーション バーに Slider が表示されます:This results in a Slider being displayed in the navigation bar on the NavigationPage:

スライダーの TitleViewSlider TitleView

重要

ビューのサイズが WidthRequest およびHeightRequest のプロパティで指定されていない場合、多くのビューはナビゲーション バーに表示されません。Many views won't appear in the navigation bar unless the size of the view is specified with the WidthRequest and HeightRequest properties. または、HorizontalOptions および VerticalOptions プロパティを適切な値に設定してビューを StackLayout にラップすることができます。Alternatively, the view can be wrapped in a StackLayout with the HorizontalOptions and VerticalOptions properties set to appropriate values.

Layout クラスは View クラスから派生しているため、複数のビューを含むレイアウト クラスを表示するように TitleView 添付プロパティを設定することができます。Note that, because the Layout class derives from the View class, the TitleView attached property can be set to display a layout class that contains multiple views. iOS およびユニバーサル Windows プラットフォーム (UWP) では、ナビゲーション バーの高さを変更できないため、ナビゲーション バーに表示されるビューがナビゲーション バーの既定サイズより大きい場合、クリップが発生します。On iOS and the Universal Windows Platform (UWP), the height of the navigation bar can't be changed, and so clipping will occur if the view displayed in the navigation bar is larger than the default size of the navigation bar. 一方 Android では、NavigationPage.BarHeight バインディング可能プロパティを新しい高さを表す double に設定することで、ナビゲーション バーの高さを変更できます。However, on Android, the height of the navigation bar can be changed by setting the NavigationPage.BarHeight bindable property to a double representing the new height. 詳細については、「Setting the Navigation Bar Height on a NavigationPage」(NavigationPage でナビゲーション バーの高さを設定する) を参照してください。For more information, see Setting the Navigation Bar Height on a NavigationPage.

また、ナビゲーション バーにコンテンツの一部を配置し、ナビゲーション バーと色を合わせたビューの一部をページ コンテンツの上部に配置して、拡張ナビゲーション バーを提案することもできます。Alternatively, an extended navigation bar can be suggested by placing some of the content in the navigation bar, and some in a view at the top of the page content that you color match to the navigation bar. さらに、iOS では、NavigationPage.HideNavigationBarSeparator バインド可能プロパティを true に設定することで、ナビゲーション バーの下部にあるセパレーターと影を削除できます。In addition, on iOS the separator line and shadow that's at the bottom of the navigation bar can be removed by setting the NavigationPage.HideNavigationBarSeparator bindable property to true. 詳細については、「Hiding the Navigation Bar Separator on a NavigationPage」(NavigationPage でナビゲーション バーのセパレーターを非表示にする) を参照してください。For more information, see Hiding the Navigation Bar Separator on a NavigationPage.

注意

BackButtonTitleTitleTitleIconTitleView のプロパティのいずれでも、ナビゲーション バー上の領域を占める値を定義できます。The BackButtonTitle, Title, TitleIcon, and TitleView properties can all define values that occupy space on the navigation bar. ナビゲーション バーのサイズはプラットフォームや画面サイズによって変わりますが、これらのプロパティをすべて設定すると、領域が限られているために競合が発生します。While the navigation bar size varies by platform and screen size, setting all of these properties will result in conflicts due to the limited space available. これらのプロパティの組み合わせを使用するのではなく、TitleView プロパティのみ設定して目的のナビゲーション バーのデザインを改善することをお勧めします。Instead of attempting to use a combination of these properties, you may find that you can better achieve your desired navigation bar design by only setting the TitleView property.

制限事項Limitations

NavigationPage のナビゲーション バーに View を表示するときに注意が必要な制限事項がいくつかあります。There are a number of limitations to be aware of when displaying a View in the navigation bar of a NavigationPage:

  • iOS では、NavigationPage のナビゲーション バーに配置されるビューは、大きなタイトルが有効かどうかによって表示される位置が変わります。On iOS, views placed in the navigation bar of a NavigationPage appear in a different position depending on whether large titles are enabled. 大きなタイトルを有効にする方法については、「Displaying Large Titles」(大きなタイトルの表示) を参照してください。For more information about enabling large titles, see Displaying Large Titles.
  • Android では、NavigationPage のナビゲーション バーにビューを配置することは、app-compat を使用するアプリでのみ実現できます。On Android, placing views in the navigation bar of a NavigationPage can only be accomplished in apps that use app-compat.
  • ListViewTableView などの大きくて複雑なビューを NavigationPage のナビゲーション バーに配置することはお勧めしません。It's not recommended to place large and complex views, such as ListView and TableView, in the navigation bar of a NavigationPage.