RegionManagerを使ったMainWindowへの他のViewの表示(Parameter付き)
1. UserControlViewプロジェクトに対し、MainWindowからViewにパラメータを渡して表示する機能を追加していきます。(リポジトリでは、変更済みのプロジェクトの名称をNavigateToViewWithParametersとしています。)
以降の手順の準備として、UserControlViewプロジェクトと構成が同じでプロジェクト名がNavigateToViewWithParametersのプロジェクトを作成しておきます。
2. 作成したプロジェクトのViewsフォルダを右クリックし、新しい項目を追加します。
3. 新しい項目の追加でPrism UserControl (WPF)を選択します。追加する項目の名前はViewWithParametersViewにしました。この画面で追加をクリックします。
4. NavigateToViewWithParametersプロジェクトにViews/ViewWithParametersView.xaml(およびViewWithParametersView.xaml.cs)とViewModels/ViewWithParametersViewModel.csが追加されます。
5. Viewへのパラメータ渡しとは関係ありませんが、Material Design In XAMLのAccentのカラーを下記のApp.xamlのようにLightGreenからYellowに変更しました。変更した行をハイライト表示しています。
<prism:PrismApplication x:Class="NavigateToViewWithParameters.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:NavigateToViewWithParameters" xmlns:prism="http://prismlibrary.com/" > <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <!-- MahApps --> <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" /> <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" /> <!-- Theme setting --> <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Green.xaml" /> <!-- Material Design --> <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" /> <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" /> <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.LightGreen.xaml" /> <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Yellow.xaml" /> <!-- Material Design: MahApps Compatibility --> <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.MahApps;component/Themes/MaterialDesignTheme.MahApps.Fonts.xaml" /> <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.MahApps;component/Themes/MaterialDesignTheme.MahApps.Flyout.xaml" /> </ResourceDictionary.MergedDictionaries> <!-- MahApps Brushes --> <SolidColorBrush x:Key="HighlightBrush" Color="{DynamicResource Primary700}"/> <SolidColorBrush x:Key="AccentBaseColorBrush" Color="{DynamicResource Primary600}" /> <SolidColorBrush x:Key="AccentColorBrush" Color="{DynamicResource Primary500}"/> <SolidColorBrush x:Key="AccentColorBrush2" Color="{DynamicResource Primary400}"/> <SolidColorBrush x:Key="AccentColorBrush3" Color="{DynamicResource Primary300}"/> <SolidColorBrush x:Key="AccentColorBrush4" Color="{DynamicResource Primary200}"/> <SolidColorBrush x:Key="WindowTitleColorBrush" Color="{DynamicResource Primary700}"/> <SolidColorBrush x:Key="AccentSelectedColorBrush" Color="{DynamicResource Primary500Foreground}"/> <LinearGradientBrush x:Key="ProgressBrush" EndPoint="0.001,0.5" StartPoint="1.002,0.5"> <GradientStop Color="{DynamicResource Primary700}" Offset="0"/> <GradientStop Color="{DynamicResource Primary300}" Offset="1"/> </LinearGradientBrush> <SolidColorBrush x:Key="CheckmarkFill" Color="{DynamicResource Primary500}"/> <SolidColorBrush x:Key="RightArrowFill" Color="{DynamicResource Primary500}"/> <SolidColorBrush x:Key="IdealForegroundColorBrush" Color="{DynamicResource Primary500Foreground}"/> <SolidColorBrush x:Key="IdealForegroundDisabledBrush" Color="{DynamicResource Primary500}" Opacity="0.4"/> <SolidColorBrush x:Key="MahApps.Metro.Brushes.ToggleSwitchButton.OnSwitchBrush.Win10" Color="{DynamicResource Primary500}" /> <SolidColorBrush x:Key="MahApps.Metro.Brushes.ToggleSwitchButton.OnSwitchMouseOverBrush.Win10" Color="{DynamicResource Primary400}" /> <SolidColorBrush x:Key="MahApps.Metro.Brushes.ToggleSwitchButton.ThumbIndicatorCheckedBrush.Win10" Color="{DynamicResource Primary500Foreground}" /> </ResourceDictionary> </Application.Resources> </prism:PrismApplication>
6. デザインの変更とViewへのParameter渡しの準備のため、Views/MainWindow.xamlを下記のように変更します。
<metro:MetroWindow x:Class="NavigateToViewWithParameters.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" > <StackPanel> <TextBox FontSize="16" Text="{Binding DateTimeText}" /> <Button Content="Update Time" Command="{Binding DateTimeUpdateButton}"/> <UniformGrid Columns="2"> <Button Content="Show Huge Label View" Command="{Binding ShowHugeLabelButton}" Style="{StaticResource MaterialDesignRaisedLightButton}"/> <Button Content="Show View with Parameters" Command="{Binding ShowViewWithParametersButton}" Style="{StaticResource MaterialDesignRaisedSecondaryButton}"/> </UniformGrid> <ContentControl prism:RegionManager.RegionName="ContentRegion" /> </StackPanel> </metro:MetroWindow>
一番外側のGridタグを外し、全体をStackPanel内に配置するようにしました。StackPanel内の三行目にコラム数が2のUniformGridを用意し、同じ大きさのボタンを左右に並べて配置するようにしました。
ViewWithParametersViewに渡す変数をDateTimeLabelからDateTimeTextに変更しました。DateTimeTextの文字列をユーザーが書き換えられるよう、LabelからTextBoxに変更しました。
Show Huge Label ViewボタンのStyleをStyle=”{StaticResource MaterialDesignRaisedLightButton}”のように指定しました。デフォルトのButtonより少し薄い配色のボタンになっています。また、Show View with ParametersボタンのStyleをStyle=”{StaticResource MaterialDesignRaisedSecondaryButton}”としました。アクセントとして指定した黄色のボタンになっています。
7. ViewWithParametersViewをMainWindowViewModel.csからRequestNavigateメソッドで表示できるようにするため、App.xaml.csにハイライトした行を追加します。
using NavigateToViewWithParameters.Views; using Prism.Ioc; using System.Windows; namespace NavigateToViewWithParameters { /// <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>(); containerRegistry.RegisterForNavigation<ViewWithParametersView>(); } } }
8. MainWindowViewModel.csの下記のハイライトした行を変更または追加します。
using Prism.Commands; using Prism.Mvvm; using Prism.Regions; using NavigateToViewWithParameters.Views; namespace NavigateToViewWithParameters.ViewModels { public class MainWindowViewModel : BindableBase { private readonly IRegionManager _regionManager; private string _title = "Prism NavigateToViewWithParameters"; public string Title { get { return _title; } set { SetProperty(ref _title, value); } } private string _dateTimeText = System.DateTime.Now.ToString(); public string DateTimeText { get { return _dateTimeText; } set { SetProperty(ref _dateTimeText, value); } } public DelegateCommand DateTimeUpdateButton { get; } public DelegateCommand ShowHugeLabelButton { get; } public DelegateCommand ShowViewWithParametersButton { get; } public MainWindowViewModel(IRegionManager regionManager) { DateTimeUpdateButton = new DelegateCommand(DateTimeUpdateButtonExecute); ShowHugeLabelButton = new DelegateCommand(ShowHugeLabelButtonExecute); ShowViewWithParametersButton = new DelegateCommand(ShowViewWithParametersButtonExecute); _regionManager = regionManager; } private void DateTimeUpdateButtonExecute() { DateTimeText = System.DateTime.Now.ToString(); } private void ShowHugeLabelButtonExecute() { _regionManager.RequestNavigate("ContentRegion", nameof(HugeLabelView)); } private void ShowViewWithParametersButtonExecute() { var parameters = new NavigationParameters(); parameters.Add(nameof(ViewWithParametersViewModel.ParameterText), DateTimeText); _regionManager.RequestNavigate("ContentRegion", nameof(ViewWithParametersView), parameters); } } }
19-24行目では変数名の末尾をLabelからTextに変更しています。MainWindow.xamlでLabelからTextBoxに変更したため、変更後のプログラムではDateTimeTextに現在時刻をセットして表示するだけでなく、TextBoxの内容を編集することもできます。
28行目でViewWithParametersViewを表示するボタンのCommandにバインドするDelegateCommandを用意しています。34行目でボタンが押されたときに呼び出されるメソッドShowViewWithParametersButtonExecuteをパラメータとしてこのDelegateCommandをインスタンス化しています。
48-53行目がメソッドShowViewWithParametersButtonExecuteです。50行目でパラメータを格納するNavigationParameters型のparametersオブジェクトを生成しています。51行目でparametersオブジェクトにnameof(ViewWithParametersViewModel.ParameterText)をKey、DateTimeTextをValueとするパラメータを格納しています。52行目でRequestNavigateを呼んでViewWithParametersViewをMainWindow.xamlのContentControlに表示します。このとき、第3引数としてparametersオブジェクトを与え、パラメータをViewWithParametersViewに渡しています。
9. ViewWithParametersViewModel.csの下記のハイライトした行を変更または追加します。
using Prism.Mvvm; using Prism.Regions; namespace NavigateToViewWithParameters.ViewModels { public class ViewWithParametersViewModel : BindableBase, INavigationAware { public ViewWithParametersViewModel() { } private string _parameterText = string.Empty; public string ParameterText { get { return _parameterText; } set { SetProperty(ref _parameterText, value); } } public bool IsNavigationTarget(NavigationContext navigationContext) { return true; } public void OnNavigatedFrom(NavigationContext navigationContext) { } public void OnNavigatedTo(NavigationContext navigationContext) { ParameterText = navigationContext.Parameters.GetValue<string>(nameof(ParameterText)); } } }
MainWindowViewModelのメソッド_regionManager.RequestNavigate(“ContentRegion”, nameof(ViewWithParametersView), parameters)で渡された引数parametersを受け取ることができるようにするため、6行目でインターフェイスINavigationAwareを実装しています。
21-24, 26-29, 31-34行目でINavigationAwareの3つのメソッドを実装しています。
OnNavigatedToメソッドはRequestNavigateでViewが表示されるときに実行されるメソッドです。33行目のようにキーをnameof(ParameterText)として、string型のValueを取得してParameterTextにセットしています。MainWindowViewModel.csの51-52行目でparametersインスタンスにセットしたKey、Value形式のパラメータのValueを取得しています。
IsNavigationTargetメソッドはViewが表示されなくなった後も以前の値を保持するか否かをbool値で返します。今回の実装の場合、どちらでも結果は変わりませんが、値を保持するtrueを返すことにしました。
OnNavigatedFromはViewが表示されなくなる直前に実行されるメソッドです。Viewの終了処理等を記述します。今回の実装では何も行いません。
13-18行目はViewWithParametersViewが受け取ったパラメータ文字列を格納する変数とプロパティを用意しています。プロパティParameterTextをViewWithParametersView.xamlでTextBlockのTextとバインドし、受け取ったパラメータ文字列をViewWithParametersViewに表示するようにします。
10. ViewWithParametersView.xamlに下記のハイライトした行を追加します。
<UserControl x:Class="NavigateToViewWithParameters.Views.ViewWithParametersView" 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="{Binding ParameterText}" FontSize="50" Foreground="{StaticResource AccentColorBrush4}" TextWrapping="Wrap"/> </Grid> </UserControl>
- プロパティParameterTextをTextBlockのTextとバインドし、ParameterTextの値が表示されるようにしています。
- Foreground=”{StaticResource AccentColorBrush4}”で表示する文字の色を指定しています。
- TextWrapping=”Wrap”で、文字列がViewからはみ出すときは折り返すようにしています。
- FontSize=”50″でフォントサイズを指定しています。
11. プログラムをデバッグ実行し、Show Huge Label Viewボタンをクリックすると下記のように表示されます。
12. Show View with Parametersボタンをクリックすると下記のように表示されます。DateTimeTextの文字列がMainWindowからViewWithParametersViewに渡され、ViewWithParametersView内に表示されます。
13. 時刻を表示しているTextBoxに適当な文字列を追加します。
14. もう一度Show View with Parametersボタンをクリックすると下記のように表示されます。文字列を追加されたDateTimeTextの文字列がMainWindowからViewWithParametersViewに渡され、ViewWithParametersView内に表示されます。