Prism.Wpf 7.2 Regionへの初期表示指定と画面遷移をしてみる
WPFの初心者です。WPFのなんたるやも知らないまま、Prism & ReactivePropertyで MVVM に挑んでいるところですが・・・全然わかりません。まずはPrismのHello world的なサンプルを作ることにしました。
目標
PrismのRegionで、「Window(枠)は1つで内側の表示を切り替える」だけのサンプルアプリを作る。
ところが、Regionの使い方がわからない、ビルドが通らない、Viewを表示してもRegionに何も表示されない・・・なかなかにハマってしまいました。さんざん調べまくり、ようやく、参考になる記事と公式サンプルに・・・たどり着いた、というよりは、記事の使い方が分かった、という感じです。結果としてどうすればよかったのか、ほかの初心者の方の参考になれば幸いです。
- MainWindowに、Buttonを2つ、Region(ContentControl)を1つ配置。
- Buttonによって、Regionに表示されるView(UserControl)を切り替える。
- Regionに初期表示されるView(UserControl)を指定する。
Prismの公式サンプル
「17-BasicRegionNavigation」とやっていることは同じですが、Moduleを使わずに簡易化したものです。
Module化しないように作り変えるなんてMVVMの方向性に逆行しているのでしょうが、RegionManagerでNavigateすることだけを切り取るためにあえてそうしました。
環境
VisualStudio 2019
Prism Template Packインストール
Prism.Unity 7.2
プロジェクト作成
Prism Template Pack
Prismはライブラリでもあり、プロジェクト構築サポート機能??でもあるようです。
WPF(Prism)アプリ作成に先立ち、Prism Template Packをインストールしておきます。VisualStudio自体をグレードアップするようなイメージです。これにより、VisualStudioから Prismのプロジェクトテンプレートが使えるようになります。
VisualStudio MarketPlace
VS2017だとPrism公式サンプルが開けないようです。VS2019にしておきましょう。 (Prismのインストールがうまくいってなかっただけかも)
プロジェクト作成
VisualStudioのプロジェクト新規作成で、Prism Blank App (WPF)を選択。
DIコンテナにUnityを選択します。
一度ビルドすると、プロジェクトにPrism.Unityが組み込まれます(Prism Template Packのおかげらしい)。
公式サンプル「17-BasicRegionNavigation」では別プロジェクトにRegion埋め込み用のViewを作っていますが、ここでは簡略して同プロジェクトにします。
Regionに埋め込むView(UserControl)
プロジェクト内のフォルダ Views に対し、[追加]>[新しい項目の追加]で、Prism UserControlを選択します。クラス名(コントロール名)をViewAとします。同様にViewBを作成します。
Prismが、Viewに対応するViewModelのクラスの自動生成と、Viewのxamlにprism:ViewModelLocator.AutoWireViewModel="True"
の付け足しをしてくれます。
Viewの作成
ViewA,ViewBの内容
公式サンプル「17-BasicRegionNavigation」と同様、それぞれ単にViewA, ViewB と表示するTextBlockを一つあるだけとします。下記はViewAのxamlのサンプル。
<UserControl x:Class="BlankApp3.Views.ViewA"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid>
<TextBlock Text="ViewA" FontSize="48" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</UserControl>
このサンプルではViewModelでは何もしません。コードも自動生成のままでよいです。INavigationAwareを実装しなくてもとりあえずNavigationされるようです。
MainWindowのxaml
公式サンプル「17-BasicRegionNavigation」と同様、MainWindowに、Buttonを2つ、Regionを1つ配置します。ButtonによってRegionの内容をViewA⇔ViewB切り替えできるようにします。
自動生成されたMainWindowView.xamlに対し、Buttonを2つ追加します。ContentControlは大きさだけ調整します。
ButtonのCommandには、ViewModelに定義するNavigateCommandというプロパティをバインドします。さらにCommandParameterには、切り替えるViewのクラス名を指定します。ViewA.xamlならViewAです。
<Window x:Class="BlankApp3.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="{Binding Title}" Height="200.784" Width="334.091">
<DockPanel LastChildFill="True">
<StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Margin="5" >
<Button Command="{Binding NavigateCommand}" CommandParameter="ViewA" Margin="5">Navigate to View A</Button>
<Button Command="{Binding NavigateCommand}" CommandParameter="ViewB" Margin="5">Navigate to View B</Button>
</StackPanel>
<ContentControl prism:RegionManager.RegionName="ContentRegion" Margin="5" />
</DockPanel>
</Window>
RegionManagerとDI
【備考】Prism7.1 以降でアプリ起動時のコードが変更されています。過去の人気記事とは少し違うことに注意してください。
Region上のViewを切り替えることとDI(Dependency injection)とは関係ありませんが、Prismを使うにあたってDIコンテナの使用が前提となります。RegionManagerのクラス登録はPrismが作ってくれるらしく、自分のコード上では何も指定しません。一方で、自分で作るViewはクラス登録が必要です。Viewの切り替え(Navigation)に使えるように、DIコンテナに、ViewA, ViewBのクラスを登録します。※ViewA,ViewBのインスタンスの生成・破棄のタイミングは別途指定が必要になるはずです。未調査&割愛。
using BlankApp3.Views;
using Prism.Ioc;
using Prism.Modularity;
using System.Windows;
namespace BlankApp3
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App
{
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<Views.ViewA>();
containerRegistry.RegisterForNavigation<Views.ViewB>();
}
}
}
ViewA, ViewBを切り替える仕組みとして、MainWindowViewModel内でRegionManagerを使います。そのRegionManagerはDIでもらいます。
ところで、PrismでViewModelがRegionManagerをDIコンテナからもらう(サンプルの)コードには2種類あります。プロパティでもらう場合と、コンストラクタでもらう場合です。
プロパティでもらうには、Prism.Unityとは別に、NuGetでUnity(作成者: Unity Container Project)をインストールします。[Dependency]を指定するにはusing Unity
が必要です。ちなみに過去の人気記事ではusing Microsoft.Practices.Unity
となっていますが、2016年頃にdllが変わったようです。
using Unity;
略
namespace BlankApp3.ViewModels
{
public class MainWindowViewModel : BindableBase
{
[Dependency]
Prism.Regions.IRegionManager RegionManager { get; }
略
のようにします。ただし、この場合はMainWindowViewModelのコンストラクタの時点では RegionManagerプロパティがnullです。従ってコンストラクタでRegionの初期表示Viewを指定することはできません。インスタンスが作成された後、何かのイベントで初めて使えるようになるようです。この記事には、MainWindowの(コードビハインドの)Activateイベントで行う例が紹介されています。
もう一つの方法、コンストラクタでもらう場合には、NuGetでUnityを取得する必要はありません。このサンプルはこちらを使います。
public class MainWindowViewModel : BindableBase
{
private readonly IRegionManager _regionManager;
public MainWindowViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
Regionに表示されるViewの切り替え(Navigation)と、初期表示指定
サンプルはMainWindow上のButtonでViewA, ViewBを切り替える、という仕様です。MainWindow.xamlの側ではButtonでCommand="{Binding NavigateCommand}"
としています。そのNavigateCommandを、MainWindowViewModelに定義します。さらにCommandParameterを受け渡すためにstringを引数としたCommandとしています。public DelegateCommand<string> NavigateCommand { get; private set; }
このDelegateCommandでNavigate()メソッドを呼び出し、RegionManagerに対しViewを切り替える要求を出します。
初期表示の指定にはRegisterViewWithRegion()を使えるようです。切り替えの要求(RequestNavigateメソッド)では、初期表示を指定できませんでした。
まとめて、MainWindowViewModel.csはこのようになります。
using Prism.Mvvm;
using Prism.Regions;
using Prism.Commands;
namespace BlankApp3.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private string _title = "Prism Application";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
private readonly IRegionManager _regionManager;
public DelegateCommand<string> NavigateCommand { get; private set; }
public MainWindowViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
_regionManager.RegisterViewWithRegion("ContentRegion", typeof(Views.ViewA));
NavigateCommand = new DelegateCommand<string>(Navigate);
}
private void Navigate(string navigatePath)
{
if (navigatePath != null)
_regionManager.RequestNavigate("ContentRegion", navigatePath);
}
}
}
参考
WPF PRISM 入門エントリまとめ
Prism公式サンプル
[WPF/C#]Prism(6.3.0)のRegionで画面遷移をする
Prism-Samples-Wpfの勉強メモ
Author And Source
この問題について(Prism.Wpf 7.2 Regionへの初期表示指定と画面遷移をしてみる), 我々は、より多くの情報をここで見つけました https://qiita.com/sampo-cure/items/220136e3c35c142cfa4d著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .