nuits.jp blog

C#, Xamarin, WPFを中心に書いています。Microsoft MVP for Development Technologies。

Prism for Xamarin.Forms入門 NavigationService Quickstart

さて、今回のお題目はNavigationService、つまり画面遷移です。
Prismは非常に強力な画面遷移の機構を提供しています。

  • Viewから完全に分離された、ViewModel主体の画面遷移
  • DeepLinkingサポート
  • アプリケーション再開時のナビゲーションスタックの再構築

などなど。(正直にいうと3つ目は私も正しくまだ理解しきれていませんが)
このため、とても一度で紹介しきれないため、何回かに分けて解説していきたいと思います。
ざっくり以下のように分ける予定です。

  • Quickstart
  • Deep Dive
  • Case Study(ここはさらに複数回に分けるかも?)

今回はQuickstartということで、新しい画面の追加と画面遷移を解説したいと思います。

なお本エントリーは連載記事「Prism for Xamarin.Forms入門」の一部となっております。
以下に目次がありますので、他のエントリーもご覧いただけると嬉しいです。
【Xamarin】Prism.Forms入門 目次 - nuits.jp blog

それでは行きましょう!

目的と手順

本エントリーでは、以下を達成することを目的としています。

  1. 新しい画面(ViewとViewModel)の追加
  2. 既存画面から新しい画面への画面遷移の実装
  3. 新しい画面から既存画面へ「前へ戻る」画面遷移の実装
  4. NavigationPageの適用

前提条件

本エントリーでは、事前に「Prism Template Pack」を利用して、プロジェクトが作成済みであることを前提としています。
「Prism Template Pack」を利用したプロジェクトの作成については、以下のリンクに詳しく記載していますので良かったらご覧ください。

www.nuits.jp

新しい画面(ViewとViewModel)の追加

それでは早速行きましょう。

新しい画面の追加は、以下の手順で実施します。

  1. 新しいView(Page)の作成
  2. 対応するViewModelの作成
  3. DI Containerへ作成したViewの登録

新しいView(Page)の作成

まずはプロジェクトへ新しいView(Page)を追加します。
この時、PrismではPageを作成するテンプレートをいくつか用意してくれています。
今回は以下の画面のように、ContentPageのテンプレートから「SecondPage」という名前で作成してください。

f:id:nuitsjp:20160821155224p:plain

作成して中身を見てみると、デフォルトでViewModelLocatorのAutowireViewModelが設定されているのが見て取れるかと思います。

f:id:nuitsjp:20160821155644p:plain

テンプレートでやってくれることは、これだけですが地味に楽ですw

さて、このままだと新しい画面に遷移しても正常に遷移できたのか、できていないのか分かり難いので、画面に画面名を表示するようにすこしXAMLへコードを追加しておきましょう。
こんな感じです。

Titleも追加していますので、お気を付けください。

対応するViewModelの作成

それでは続いて、ViewModelを作成します。
ViewModelもテンプレートが用意されているので、そちらから作成しましょう。
「SecondPage」のViewModelなので「SecondPageViewModel」にします。

f:id:nuitsjp:20160821155725p:plain

この辺りのViewModelの詳細については、以下に記載していますので良かったらご覧ください。

www.nuits.jp

さて、作成されたクラスを見てみましょう。

ベースクラスとして、BindableBaseが指定されているかと思います。
これはPrismが提供する、INotifyPropertyCangedを実装した、ViewModelなどの標準の基底クラスになります。

DI Containerへ作成したViewの登録

Prismでは画面遷移の際、遷移先の画面をDI Containerから取得します。
その為、新しい画面を作成した場合、DI Containerへ登録してあげる必要があります。
PCLプロジェクトのApp.xaml.csを開いてください。

RegisterTypesメソッド内で、MainPageがすでに登録されていると思いますが、同様に新しく追加したSecondPageも登録してあげましょう。

こんな感じです。
簡単ですね!

既存画面から新しい画面への画面遷移の実装

それでは、既存のMainPageから新しいSecondPageへの画面遷移を実装します。
画面遷移を実装する場合、多くは以下の手順で実施します。

  1. 遷移元のViewModelでINavigationServiceの受け取り
  2. 遷移元のViewModelに画面遷移処理の実装
  3. 遷移元画面から、画面遷移処理の実装

今回は、MainPageにボタンを追加して、ボタンをクリックするとSecondPageへ遷移するよう、実装していきます。

遷移元のViewModelでINavigationServiceの受け取り

Prismでは画面遷移を行う際に、INavigationServiceを利用します。
INavigationServiceはコンテナからViewModelにインジェクションしてもらって利用します。
今回はMainPageからの画面遷移なので、MainPageViewModelでINavigationServiceを受け取ります。

MainPageViewModelのコンストラクタを以下のように修正します。
この時に、受け取るパラメータ名がnavigationServiceである必要がありますので注意してください。

遷移元のViewModelに画面遷移処理の実装

今回は、MainPageにボタンを追加して、それを起点に画面遷移します。
その為、ボタンに対応するCommandを作成し、コマンドの処理として画面遷移を実装します。

INavigationServiceのNavigationAsyncメソッドで画面遷移を呼び出します。
この時、引数としてデフォルトでは遷移先の画面名を指定します。
画面遷移指定が文字列なところなど、ちょっと気に入らないと思われる方もいらっしゃると思いますが、DeepLinkingやアプリケーション再開時のナビゲーションスタックの再構築を考えると、致し方がない処かとは思います。
ただ、個別に文字列指定するのもどうかと思いますので、いくつかのアイディアをいずれ紹介したいと思います。

遷移元画面から、画面遷移処理の実装

続いて、MainViewに画面遷移ボタンを追加し、作成したCommandを呼び出すように実装します。

ボタンに先ほど作成たNavigateSecondCommandをバインドしましょう。

これでこんな感じに画面遷移が実現できたはずです。

f:id:nuitsjp:20160821160150g:plain

新しい画面から既存画面へ「前へ戻る」画面遷移の実装

それでは続いてアプリケーション内から戻る処理を追加してみましょう。
手順としては以下のようになります。

  1. SecondPageViewModelへ前画面へ戻る処理の実装
  2. SecondPageに戻る処理呼び出しの実装

こちらも同様にボタンから遷移できるようにします。

SecondPageViewModelへ前画面へ戻る処理の実装

戻る処理も同様にINavigationServiceを利用します。
SecondPageViewModelに次の処理を施します。

  1. INavigationServiceの受け取り
  2. GoBackCommandの定義
  3. GoBackCommandの振る舞いとして、戻る処理の実装

具体例は以下の通りです。

SecondPageに戻る処理呼び出しの実装

説明の必要もないかもしれませんが、SecondPageにボタンを追加し、GoBackCommandの呼び出しを実装します。

f:id:nuitsjp:20160821160348g:plain

こんな感じで動作するはずです。

さて、MainPageとSecondPageで行ったり来たりできるようになりました。
こうなったら次に欲しくなるのはやはり、画面上部のナビゲーションですよね?

f:id:nuitsjp:20160821160459p:plain

Xamarin.Formsでは、NavigationPageを利用することで実現できます。
そしてPrism.Formsでは非常に簡単にそれらを組み込むことが可能です。

具体的な手順は以下の通りです。

  1. DI ContainerへNavigationPageを登録する
  2. App.xaml.csからの画面遷移をNavigationPage経由で遷移するように指定する

1.の登録ですが、Xamarin.Formsで提供されているNavigationPageをそのまま登録するだけでかまいません。
いずれも、App.xaml.csへの実装になりますので、一度に見てみましょう。

まず、RegisterTypesメソッド内で、NavigationPageのDI Containerへの登録が追加されています。
繰り返しになりますが、ここで登録するNavigationPageはXamarin.Formsで提供されている素のNavigationPageクラスです。

そしてOnInitialized内の画面遷移を

NavigationService.NavigateAsync("MainPage?~

から

NavigationService.NavigateAsync("NavigationPage/MainPage?~

へ変更しています。
これだけでNavigationPageが適用されます。

f:id:nuitsjp:20160821160658g:plain

と言う分けで、新しい画面の追加と、それに伴った画面遷移の実装方法を紹介してきました。
今回紹介した内容は、以下に公開していますので良かったら参考にご覧ください。

github.com

一先ず今回はここまでで、次はNavigationServiceをもう少し掘り下げて説明していきたいと思います。
それではまた!