[C#][Prism][備忘録]PrismのIDialogServiceを使用してダイアログを表示する

# はじめに

PrismのDialogServiceを使用してダイアログを表示する方法の備忘録です。

## IDialogServiceを使用してダイアログを表示する

PrismにはIContainerRegistryというサービスやダイアログ等の型をDIコンテナへ登録できるI/Fがあります。
これを使用して、ダイアログをPrismに登録しておきます。

登録はPrismのアプリやモジュールの初期化の際に呼ばれる、RegisterTypesメソッドをオーバーライドして登録します。
表示するダイアログの要素として、ViewはSampleDialog, ViewModelはSampleDialogViewModelとします。

```cs

namespace XX

public partial class App : PrismApplication
{
    /// <summary>
    /// 型の登録
    /// </summary>
    /// <param name="containerRegistry"></param>
    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
        // Viewのみの登録で良い。
        // 理由は後述します。
        // （ViewとViewModel両方の型を登録することもできます。）
        containerRegistry.RegisterDialog<SampleDialog>()
    }
}

```

上記で、Viewのみの登録ですませるには、Viewで以下の設定が必要です。
UserContorlで`ViewModelLocator.AutoWireViewModel="True"`を設定します。
この設定をすることで、Prism側でViewとViewModelを紐づけてくれます。紐づけは[公式文書](https://prismlibrary.com/docs/viewmodel-locator.html)によると、以下のルールで行われます。

- ViewModelがビュータイプと同じアセンブリにあること
- ViewModelsが.ViewModels子名前空間にあること
- そのビューが.Views子名前空間にあること
- ViewModel名がビュー名に対応し、「ViewModel」で終わること。

```xml

<UserControl x:Class="XX.Views.SampleDialog"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:prism="http://prismlibrary.com/"
             mc:Ignorable="d" 
             prism:ViewModelLocator.AutoWireViewModel="True">

    <!--Prismのダイアログは、UserContorolに以下のスタイルを適用している-->
    <prism:Dialog.WindowStyle>
        <Style TargetType="Window">
            <Setter Property="ResizeMode" Value="CanResizeWithGrip" />
            <Setter Property="ShowInTaskbar" Value="False" />
            <Setter Property="SizeToContent" Value="WidthAndHeight" />
        </Style>
    </prism:Dialog.WindowStyle>

```

ViewModelにははPrismのIDialogAwareを実装しておく必要があります。
また、PrismにはIDialogParametersというI/Fがあります。
これを使用して、ダイアログを開く際、また、閉じる際にダイアログの呼び出し元と、ダイアログでパラメーターの受け渡しができます。
IDialogAware.OnDialogOpenedというダイアログを開いた後に実行する処理を書けるメソッドの引数や、ダイアログの結果を表すDialogResultというオブジェクトがもつため、それらで取得・追加して利用します。

```cs

namespace XX.ViewModels

public class SampleDialogViewModel : IDialogAware
{
	#region IDialogAwareの実装

	/// <summary>
    /// ダイアログを閉じれるか
    /// </summary>
	public bool CanCloseDialog()
	{
		return true;
	}

	/// <summary>
    /// ダイアログを閉じた後の処理
    /// </summary>	public void OnDialogClosed()
	{
	}

	/// <summary>
    /// ダイアログを開いた後の処理
    /// </summary>
	public void OnDialogOpened(IDialogParameters parameters)
	{
        // IDialogParametersを利用すれば、ダイアログの呼び出し元で登録したパラメーターをキーを指定して取得できます。
        // 以下は"paramKey"というキーで登録されたstring型のパラメーターを取得しています。
        // 登録部分は後述します。
        var param = parameters.GetValue<string>("paramKey");

		// ダイアログの初期化等
        // ...
	}

	/// <summary>
    /// ダイアログのタイトル
    /// </summary>
	public string Title => "サンプル";

	/// <summary>
    /// ダイアログの閉じるを要求するイベント
    /// </summary>
	public event Action<IDialogResult>? RequestClose;

	#endregion

    #reagion コマンド

	/// <summary>
	/// OKコマンド
	/// </summary>
	public DelegateCommand OkCommand => new DelegateCommand(() => 
    {
        // ダイアログの結果オブジェクトを作成
        var result = new DialogResult(ButtonResult.OK);

        // ダイアログのOKボタンが押下された際の処理
        // ...
        
        // DialogResultオブジェクトのパラメーターを追加しています。
        // ダイアログの呼び出し元で、ここで追加したパラメーターを参照できます。
        // 以下は"resultKey"というキーで"結果のパラメーター"という文字列をパラメーターとして追加しています。
        result.Parameters.Add("resultKey", "結果のパラメーター");

        // ダイアログを閉じる
        RequestClose?.Invoke(result);
    });

	#endregion
}
```

PrismのIDialogService.ShowDialogメソッドを使用して、ダイアログを表示できます。

```cs

public class MainWindowViewModel
{
    /// <summary>
	/// ダイアログサービス
	/// </summary>
    private IDialogService m_DialogService;

    /// <summary>
	/// コンストラクタ
	/// </summary>
    public MainWindowViewModel(IDialogService dialogService)
    {
        m_DialogService = dialogService;
    }

    public ICommand ShowSampleDialogCommand => new DelegateCommand(() =>
    {
        // ダイアログが開く際の処理（SampleDialogViewModel.OnDialogOpened）で取得できるパラメーターを追加しています。
        // 以下は"paramKey"というキーで"パラメーター"という文字列を追加しています。
        var parameters = new DialogParameters
        {
            { "paramKey", "パラメーター"}
        };

        // ダイアログを表示
        // ダイアログ名を指定すれば、ダイアログに紐づくViewModelをPrism側で解決（インスタンス化）し、
        // ダイアログのDataContextに設定して、表示してくれます。
        m_DialogService.ShowDialog(nameof(SampleDialog), parameters, dialogResult =>
        {
            // ダイアログの結果がOKなら値を取得
            if (dialogResult.Result == ButtonResult.OK)
            {
                // 以下のresultでは、"SampleDialogViewModel"のOKコマンドで追加した
                // "結果のパラメーター"という文字列が取得できます。
                var result = dialogResult.Parameters.GetValue<string>("resultParam");
            }
        });
    });
}

```

# さいごに

Prismはまだ使い慣れていないですが、徐々に習得していきたいです。