search
LoginSignup
13
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

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

はじめに

いつもお世話になっている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を使用するようにしましょう。

まとめ

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
13
Help us understand the problem. What are the problem?