Help us understand the problem. What is going on with this article?

Prism.WpfでRequestNavigateと戻る、進む(IRegionNavigationService, IRegionNavigationJournal)

More than 1 year has passed since last update.

はじめに

いつもお世話になっているPrismなんですけど、使い方を習熟するべく元のソースを見ていたら知らない機能があったため、勉強がてら投稿させていただきます。

機能確認用プロジェクト

Prism7Sample(自作)
Prism-Samples-Wpf(公式) 24-NavigationJournal

環境

Prism.DryIoc.7.1.0.172-pre
Prism.Wpf.7.1.0.172-pre
Prism.Core.7.1.0.172-pre
.NET Framework: 4.7.2

IRegionNavigationServiceについて

皆様はIRegionNavigationServiceの存在はご存知でしたでしょうか。INavigationAwareOnNavigatedToOnNavigatedFromの仮引数であるNavigationContextのメンバであるNavigationServiceから取得できます。

xxxViewModel.cs
        private IRegionNavigationService RegionNavigationService { get; set; }

        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            RegionNavigationService = navigationContext.NavigationService;
        }

このIRegionNavigationServiceINavigateAsyncを継承しているため、IRegionManagerをDIコンテナから注入しなくてもRequestNavigateすることができます。しかもIRegionManagerRequestNavigateするときは毎回RegionNameを指定する必要がありましたがIRegionNavigationServiceRequestNavigateでは記述する必要がありません。

IRegionManager例
RegionManager.RequestNavigate("ContentRegion", nameof(yyyView));
IRegionNavigationService例
RegionNavigationService.RequestNavigate(nameof(yyyView));

同一Region内で画面遷移をするのならばIRegionNavigationService、別のRegionの画面を操作する必要がある場合はIRegionManagerと使い分けできます。

IRegionNavigationJournalについて

また、IRegionNavigationServiceJournalというメンバも持っています。このJournalIRegionNavigationJournalの型で名前の通り、Region内のナビゲーションの履歴を管理してくれています。IRegionNavigationServiceRequestNavigateを使用して画面遷移しているとGoBackGoForwardを使用して戻る進む機能を実現できます。例えば段階的に画面が遷移するようなシステムでひとつ前に戻るようなボタンを実装する際はRequestNavigateで個別のView名を記述するよりもGoBackで実装するほうが問題になりにくいのではないかと思います。
以下に戻る、進むボタンの実装例を記載します。

ContentViewModel.cs
    public class ContentViewModel : BindableBase, INavigationAware
    {
        private IRegionNavigationService RegionNavigationService { get; set; }

        public DelegateCommand BackCommand { get; }
        public DelegateCommand ForwardCommand { get; }

        public ContentViewModel()
        {
            BackCommand = new DelegateCommand(() => RegionNavigationService.Journal.GoBack(), () => RegionNavigationService?.Journal?.CanGoBack ?? false);
            ForwardCommand = new DelegateCommand(() => RegionNavigationService.Journal.GoForward(), () => RegionNavigationService?.Journal?.CanGoForward ?? false);
        }

        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            RegionNavigationService = navigationContext.NavigationService;
            BackCommand.RaiseCanExecuteChanged();
            ForwardCommand.RaiseCanExecuteChanged();
        }

        public bool IsNavigationTarget(NavigationContext navigationContext) => true;

        public void OnNavigatedFrom(NavigationContext navigationContext){}
    }

IJournalAwareについて

ViewModelにIJournalAwareを継承しているとIRegionNavigationJournalでの履歴の保存可否を指定することができます。
例えばメニュー画面->認証画面->詳細画面と遷移するようなシステムにおいて、詳細画面からメニュー画面に戻りたい(認証画面にGoBackしたくない)等で必要になるかと思います。ViewModelにてIJournalAwareを継承していない場合は保存する(true)を返すようになっていました。

IJournalAware例
    public class ContentViewModel : BindableBase, IJournalAware
    {
        public bool PersistInHistory() => true;
    }

RecordNavigationについて

履歴の記録はIRegionNavigationJournalRecordNavigationを実行することで自分で保存することもできます。しかしIRegionNavigationServiceの実装であるRegionNavigationServiceRequestNavigateにてRecordNavigationしてくれているので自分で実行する機会はあんまりないかと思います。
またIRegionManagerの実装であるRegionManagerRequestNavigateではRecordNavigationしていないので注意が必要です。
戻る進む機能を利用する際は、RegionNavigationServiceRequestNavigateを使用するようにしましょう。

まとめ

kwhrkzk
業務系に従事。WPF,PRISM,C#,F#,.NET Core,Laravel,Vue,TypeScript,DDD,CQRS,SOLIDらへんに興味有。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away