RegionManagerを使ったMainWindowへの他のViewの表示

1. DataBindingプロジェクトに対し、ボタンをクリックしてMainWindow内に他のViewを表示する機能を追加していきます。(リポジトリでは、変更済みのプロジェクトの名称をUserControlViewとしています。)

以降の手順の準備として、DataBindingプロジェクトと構成が同じでプロジェクト名がUserControlViewのプロジェクトを作成しておきます。

2. 作成したプロジェクトのViewsフォルダを右クリックし、新しい項目を追加します。

3. 新しい項目の追加でPrism UserControl (WPF)を選択します。追加する項目の名前はHugeLabelViewにしました。この画面で追加をクリックします。

4. UserControlViewプロジェクトにViews/HugeLabelView.xamlとViewModels/HugeLabelViewModel.csが追加されます。

5. Views/HugeLabelView.xamlに下記のように表示するLabelを追加します。このViewはHugeLabelというフォントサイズ50の大きな文字を灰色で表示するだけのViewになります。

<UserControl x:Class="UserControlView.Views.HugeLabelView"
             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>
        <Label Content="HugeLabel" FontSize="50" Foreground="Gray"/>
    </Grid>
</UserControl>

6. Views/MainWindow.xamlに下記のようにHugeLabelViewを表示するボタンを追加します。このボタンをクリックすると先ほど作成したHugeLabelViewが表示されるように実装を進めていきます。

<metro:MetroWindow x:Class="UserControlView.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:metro="http://metro.mahapps.com/winfx/xaml/controls"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525" >
    <Grid>
        <StackPanel>
            <Label FontSize="16" Content="{Binding DateTimeLabel}" />
            <Button Content="Update Time" Command="{Binding DateTimeUpdateButton}"/>
            <Button Content="Show Huge Label View" Command="{Binding ShowHugeLabelButton}"/>
            <ContentControl prism:RegionManager.RegionName="ContentRegion" />
        </StackPanel>
    </Grid>
</metro:MetroWindow>

7. ViewModels/MainWindowViewModel.csを下記のように変更します。ハイライトした行が変更した行または追加した行になります。

using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using UserControlView.Views;

namespace UserControlView.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        private readonly IRegionManager _regionManager;

        private string _title = "Prism UserControlView";
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        private string _dateTimeLabel = System.DateTime.Now.ToString();
        public string DateTimeLabel
        {
            get { return _dateTimeLabel; }
            set { SetProperty(ref _dateTimeLabel, value); }
        }

        public DelegateCommand DateTimeUpdateButton { get; }
        public DelegateCommand ShowHugeLabelButton { get; }

        public MainWindowViewModel(IRegionManager regionManager)
        {
            DateTimeUpdateButton = new DelegateCommand(DateTimeUpdateButtonExecute);
            ShowHugeLabelButton = new DelegateCommand(ShowHugeLabelButtonExecute);
            _regionManager = regionManager;
        }

        private void DateTimeUpdateButtonExecute()
        {
            DateTimeLabel = System.DateTime.Now.ToString();
        }

        private void ShowHugeLabelButtonExecute()
        {
            _regionManager.RequestNavigate("ContentRegion", nameof(HugeLabelView));
        }
    }
}

12行目で表示するMainWindowのタイトルに”Prism UserControlView”をセットしています。

27行目でMainWindow.xamlで追加したButtonのCommandにバインドするShowHugeLabelButtonを宣言しています。
32行目でメソッドShowHugeLabelButtonExecuteをコンストラクタの引数として渡し、ShowHugeLabelButtonオブジェクトを生成しています。ボタンがクリックされるとメソッドShowHugeLabelButtonExecuteが実行されます。

41-44行目はHugeLabelViewを表示するメソッドShowHugeLabelButtonExecuteです。このメソッドは43行目でMainWindowのContentControlにHugeLabelViewを表示します。

43行目で参照されている_regionManagerは、29行目のようにMainWindowViewModelが生成されるときにコンストラクタで受け取るIRegionManager型のオブジェクトになります。Prismでは、ViewModelのコンストラクタにIRegionManager型の引数を記述することでこの型のオブジェクトを受け取ることができます。33行目でregionManagerをメンバ変数_regionManagerにセットしています。

8. App.xaml.csの19行目に下記のような記述を追加します。

using Prism.Ioc;
using System.Windows;
using UserControlView.Views;

namespace UserControlView
{
    /// <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<HugeLabelView>();
        }
    }
}

このように記述しておくことで、MainWindowViewModel.csで_regionManager.RequestNavigate(“ContentRegion”, nameof(HugeLabelView))を実行したときにMainWindowのContentControlにHugeLabelViewが表示されるようになります。

9. UserControlViewプロジェクトを選択して右クリックし、ビルドを選択してプロジェクトをビルドします。

10. 図の青枠のようにデバッグ実行するプロジェクトとしてUserControlViewを選択します。緑枠のボタンをクリックしてプロジェクトUserControlViewのデバッグ実行を開始します。

11. 図のようなウィンドウが表示されます。

12. Show Huge Label Viewボタンをクリックすると、ボタンの下の領域にHugeLabelという大きな文字を含むViewが表示されます。