Prism でダイアログ表示したい
Prism が提供するダイアログ表示のための機能 DialogService
の使い方をまとめます。
画面遷移関連をを NavigationManager
で行うように、ダイアログ関連は DialogService
で行うことが可能です。
DialogServiceでダイアログ表示するサンプル
ドキュメントを見ると詳細に使い方が書いています。
実装の手順は以下の通りです。
- UserControll(+ViewModel) を作成する
- App.cs で ContainerRegister にダイアログとして登録する
- ViewModel に
IDialogAware
を実装する DialogService
でダイアログを表示する
ダイアログ表示する UserControll を作成する
ユーザーコントロールでダイアログ表示するための View と ViewModel を作成します。
MyDialog.xaml
<UserControl x:Class="PrismApp.Views.MyDialog"
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">
<StackPanel>
<TextBlock Text="{Binding Message}" />
<Button Command="{Binding OkCommand}">OK</Button>
<Button Command="{Binding CancelCommand}">Cancel</Button>
</StackPanel>
</UserControl>
単純にテキストとボタンが2つ配置されただけの画面です。呼び出し元から引数で渡した文字列を表示させようと思います。
IContainerRegistry にダイアログを登録する
App.cs
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
// ..
containerRegistry.RegisterDialog<MyDialog>();
}
ダイアログとしてレジスタに登録する必要があるみたいなので RegisterDialog()
で先ほど作成したダイアログ用の View を登録します。
IDialogAware を ViewModel を実装する
ダイアログ表示する ViewModel に IDialogAware
を実装する必要があります。
IDialogAware
は以下のようになっています。
public interface IDialogAware
{
// ダイアログのタイトル
string Title { get; }
// ダイアログを閉じたいときに呼び出す
event Action<IDialogResult> RequestClose;
// ダイアログが閉じれるかどうか
bool CanCloseDialog();
// ダイアログが閉じたときに呼ばれる
void OnDialogClosed();
// ダイアログが開くときに呼ばれる
void OnDialogOpened(IDialogParameters parameters);
}
これを ViewModel に実装します。
MyDialogViewModel.cs
public class MyDialogViewModel : BindableBase, IDialogAware
{
private string _Message;
public string Message { get => this._Message; set => base.SetProperty(ref this._Message, value); }
public DelegateCommand OkCommand { get; }
public DelegateCommand CancelCommand { get; }
public MyDialogViewModel()
{
this.OkCommand = new DelegateCommand(this.Ok);
this.CancelCommand = new DelegateCommand(this.Cancel);
}
public void Ok()
{
this.RequestClose.Invoke(new DialogResult(ButtonResult.OK));
}
public void Cancel()
{
this.RequestClose.Invoke(new DialogResult(ButtonResult.Cancel));
}
// ↓ IDialogAware の実装
public string Title => "サンプルダイアログ";
public event Action<IDialogResult> RequestClose;
public bool CanCloseDialog() => true;
public void OnDialogClosed() { }
public void OnDialogOpened(IDialogParameters parameters)
{
this.Message = parameters.GetValue<string>("message");
}
}
まず、OnDialogOpened()
がダイアログが開くタイミングで呼び出される処理になります。引数の IDialogParameters
は呼び出し元から渡される引数がキーバリューのペアで格納されています。ここでは “message” というキーの引数を文字列型で取得しています。
OnDialogClosed()
はダイアログが閉じられた後に呼び出されます。後処理が必要な場合などはここに実装します。
CanCloseDialog()
はダイアログが閉じられる状態かどうかを取得します。これが false
を返す場合、ダイアログを閉じることができません。うっかり false
にしていると何をやっても(×ボタンでも)閉じられなくなります。
RequestClose
はダイアログを閉じたいときにキックする event
です。これをキックするときに引数で IDialogResult
を渡します。これがダイアログの戻り値になります。
this.RequestClose.Invoke(new DialogResult(ButtonResult.OK));
こんな感じで閉じたいときに呼び出せばよいです。
IDialogResult
はボタン結果と呼び出し時と同じ型のパラメータとなります。
public interface IDialogResult
{
IDialogParameters Parameters { get; }
ButtonResult Result { get; }
}
DialogService でダイアログを表示する
Prism では IDialogService
というダイアログ関連の機能を提供してくれるサービスがあるので、これを使用して表示させることができます。
IDialogService
のインターフェースで DI してくれるので呼び出し元となる ViewModel で以下のような感じでコンストラクタ引数に定義しておけばよいです。
public MainWindowViewModel(IDialogService dialogService)
{
this.DialogService = dialogService;
}
あとは表示させたいタイミグで以下のようにしてサービスからダイアログを表示します。
this.DialogService.ShowDialog("MyDialog");
表示させたいダイアログのクラス名を引数に渡せばよいです。
呼び出し時に引数を渡し、コールバックでダイアログ表示の戻り値を受け取りたいときは以下のように実装します。
var message = "Hello World!";
var parameters = new DialogParameters($"message={message}");
this.DialogService.ShowDialog("MyDialog", parameters, result =>
{
// ダイアログ終了後のコールバック
});
上の例ではパラメータで “message” というキーで “Hello World” という値を引数で渡しています。クエリ文字列みたいなフォーマットで指定するみたいです。
複数指定したいときは “hoge=1&foo=2” みたいにすればよさそうです。
戻り値はコールバック関数で受け取って処理すればよいです。
Window のスタイルをいじる
UserControll をダイアログ表示させる場合に Window のスタイルをいじりたいときは以下のようにすればよいです。
<UserControl x:Class="PrismApp.Views.MyDialog"
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">
++ <prism:Dialog.WindowStyle>
++ <Style TargetType="Window">
++ <Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterScreen" />
++ <Setter Property="ResizeMode" Value="NoResize"/>
++ <Setter Property="ShowInTaskbar" Value="False"/>
++ <Setter Property="SizeToContent" Value="WidthAndHeight"/>
++ </Style>
++ </prism:Dialog.WindowStyle>
<StackPanel>
<TextBlock Text="{Binding Message}" />
<Button Command="{Binding OkCommand}">OK</Button>
<Button Command="{Binding CancelCommand}">Cancel</Button>
</StackPanel>
</UserControl>
以上。
コメントを書く