MVVMパターンを大いに助けてくれるPrismフレームワークですが、意外とまだ情報が少ないです。

今回は基本的なところで、画面遷移と画面遷移によるパラメーターの受け渡しをさらっとご紹介します。

パラメーターの受け渡しに関しては、調べてもなかなか出てこなかった記憶があります。

Prismによる画面遷移

今回は簡単に下記のようなクラス構成で行っていきます。

※だいぶ端折りましたが、Prismのテンプレート(Blank App)でプロジェクトを作成し、Prismのアイテムテンプレートで「PrismContentPage1」を作成しています。

上記の流れで作成した場合、上記クラス構成の時点で「App.xaml.cs」の中身は下記のようになっています。

using Prism;
using Prism.Ioc;
using NavigationParameter.ViewModels;
using NavigationParameter.Views;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Prism.Unity;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace NavigationParameter
{
    public partial class App : PrismApplication
    {
        /* 
         * The Xamarin Forms XAML Previewer in Visual Studio uses System.Activator.CreateInstance.
         * This imposes a limitation in which the App class must have a default constructor. 
         * App(IPlatformInitializer initializer = null) cannot be handled by the Activator.
         */
        public App() : this(null) { }

        public App(IPlatformInitializer initializer) : base(initializer) { }

        protected override async void OnInitialized()
        {
            InitializeComponent();

            await NavigationService.NavigateAsync("NavigationPage/MainPage");
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterForNavigation<NavigationPage>();
            containerRegistry.RegisterForNavigation<MainPage>();
            containerRegistry.RegisterForNavigation<PrismContentPage1>();
        }
    }
}

この中で重要になるのが下記のコードです。

containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<MainPage>();
containerRegistry.RegisterForNavigation<PrismContentPage1>();

アプリ起動時にコンテナにページを登録しておくことで、ページ遷移の際にはそのコンテナからページが注入されているイメージです。

それでは実際の画面遷移を行うコードを見てみましょう。

下記のコードでページ遷移を実現することが出来ます。

using NavigationParameter.Views;
using Prism.Navigation;
using System.Threading.Tasks;

namespace NavigationParameter.ViewModels
{
    public class MainPageViewModel : ViewModelBase
    {
        public MainPageViewModel(INavigationService navigationService)
            : base(navigationService)
        {
            Title = "Main Page";
        }

        public async Task NavigationToNextPage()
        {
            await base.NavigationService.NavigateAsync(typeof(PrismContentPage1).Name);
        }
    }
}

INavigationServiceのNavigateAsyncメソッドで遷移先のページの名前を指定することで遷移が可能です。

ただ一点気を付けることが、厳密にはページの遷移ではなく、モーダルのページを生成している、ということです。

なのでPrismを利用してアプリを作成する際には、ページ遷移の数がパフォーマンスに影響してくる可能性があります。

ちなみに下記のように絶対パスからの指定を行うと、それまで生成してきたページを全て破棄して新たにルートからのページが生成されるようです。

await base.NavigationService.NavigateAsync("/NavigationPage/MainPage/PrismContentPage1");

文字列の指定でも可能ですが、保守容易なコードにしていく為にもルートパスは定数かリソースなどで指定しておき、ページ名もtypeof(ページクラス).Nameなどで指定するのがいいと思われます。

Prismで画面遷移によるパラメーターの受け渡し

画面間でパラメーターの受け渡しを行うには、遷移元のページは下記のように記述します。

using NavigationParameter.Views;
using Prism.Commands;
using Prism.Navigation;
using System.Threading.Tasks;

namespace NavigationParameter.ViewModels
{
    public class MainPageViewModel : ViewModelBase
    {
        public DelegateCommand Navigate { get; }

        public MainPageViewModel(INavigationService navigationService)
            : base(navigationService)
        {
            Title = "Main Page";
            Navigate = new DelegateCommand(async () => await NavigationToNextPage());
        }

        public async Task NavigationToNextPageContainParameter()
        {
            NavigationParameters parameters = new NavigationParameters();
            parameters.Add("parameter", "受け渡し完了!");
            await base.NavigationService.NavigateAsync(typeof(PrismContentPage1).Name, parameters);
        }
    }
}

NavigationParametersへの遷移パラメーターの追加は下記でも可能です。

NavigationParameters parameters = new NavigationParameters("parameter=受け渡し完了!");

遷移先のページでパラメーターを受け取るには、ViewModelBaseに実装されているINavigationAwareのメソッドを使います。

using Prism.Navigation;

namespace NavigationParameter.ViewModels
{
    public class PrismContentPage1ViewModel : ViewModelBase
    {
        public PrismContentPage1ViewModel(INavigationService navigationService) : base(navigationService)
        {

        }

        public override void OnNavigatedTo(NavigationParameters parameters)
        {
            base.OnNavigatedTo(parameters);

            var parameter = parameters.GetValue<string>("parameter");
        }
    }
}

INavigationAwareインターフェースの挙動に関しては下記がとても参考になりました。

とくに各メソッドがどのタイミングで動くか、は描画に大きく影響してきます。

ちょっとだけ書いておくと、受け取ったパラメーターで例えばリストデータを引き当てる場合、描画にはObservableCollectionではなく、BindableなList型のプロパティを使う必要がある、などです。

意外とObservableCollectionも万能ではありませんね。

まとめ

まとめ
  1. Prismでの画面遷移はINavigationServiceのNavigateAsyncを使う。
  2. Prismでのパラメーター受け渡しはNavigateAsyncの第2引数にNavigationParametersを渡し、遷移先ではINavigationAwareのメソッドで受け取る。
  3. ObservableCollectionを信用しまくってるとハマる。

以上です。

スポンサーリンク