[WPF,Prism] ダイアログ表示をDialogServiceで行う方法 [C#]

[WPF,Prism] ダイアログ表示をDialogServiceで行う方法 [C#]

Prism でダイアログ表示したい

Prism が提供するダイアログ表示のための機能 DialogService の使い方をまとめます。

画面遷移関連をを NavigationManager で行うように、ダイアログ関連は DialogService で行うことが可能です。

DialogServiceでダイアログ表示するサンプル

Dialog Service | Prism

ドキュメントを見ると詳細に使い方が書いています。

実装の手順は以下の通りです。

  1. UserControll(+ViewModel) を作成する
  2. App.cs で ContainerRegister にダイアログとして登録する
  3. ViewModel に IDialogAware を実装する
  4. 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>

以上。

参考URL

C#カテゴリの最新記事