いい感じのMessageBox for WPF

WPF用のメッセージボックスです。

## 特徴
- 追加メッセージをエクスパンダーに配置して表示
- ヘルプボタンを表示
- メッセージの色を変更
- 影のエフェクトを表示可
- コンテキストメニューから、メッセージと追加メッセージをコピー可
- オーナーのウインドウを指定して薄暗くする。
- DIコンテナをサポート
- Modelからオーナーのウインドウを指定して表示

## スクリーンショット

![20240915 231819 MessageBoxEx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/f3c88b92-697b-14a7-904a-b14e52c577f3.png)

![20240915 232046 MessageBoxEx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/e25ef72e-cd61-7021-9e52-b2d865b8318d.png)

![20240915 232102 MessageBoxEx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/890fff2e-c01e-71f1-d9cd-3272cb0cb3cc.png)

![20240915 232121 MessageBoxEx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/b0f20170-2f40-29a4-0a02-dc834d515ba9.png)

##### メッセージをカラー化
![20240915 232645 MessageBoxEx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/de5e12a3-44a2-d6cb-0efd-6b59d7288a6b.png)

#### 指定したパラメータで外観を変更
![20240915 232429 MessageBoxEx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/a5a0aea3-2c49-4c4a-3317-1d8c0bcaa8c8.png)

##### デモ
![20240915 233130 ShowbyIDialogService.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/d55c5056-0d38-3c80-ef95-5bda6d9ae2a6.png)

## 使い方

##### staticなMessageExを直接呼び出し
``` csharp
MessageEx.ShowInformationDialog("Message");
MessageEx.ShowInformationDialog("Message", "AppendedMessage");
MessageEx.ShowInformationDialog("Message", "AppendedMessage", "HelpURL");
```

##### DIコンテナにセットしたDialogService経由で表示

``` csharp
private readonly IDialogService _dialogService = Ioc.Default.GetRequiredService<IDialogService>();

_dialogService.ShowInformation("Message");
_dialogService.ShowInformation("Message", "AppendedMessage");
_dialogService.ShowInformation("Message", "AppendedMessage", "HelpURL");
```  

詳しくは、コードを参照して下さい。

## ダウンロード
https://github.com/mikihiro-t/MessageBoxWPF

## アイコン
アイコンは、[Fluent UI System Icons](https://github.com/microsoft/fluentui-system-icons)を利用しました。

## 日本語化
``` csharp
public string OKCaption { get; set; } = "OK";
public string YesCaption { get; set; } = "Yes";
public string NoCaption { get; set; } = "No";
public string CancelCaption { get; set; } = "Cancel";
```

の部分で、OK以外を、「はい」「いいえ」「キャンセル」にして下さい。

## ModelからViewのWindowをオーナーにして表示する

MVVMのModelかViewModelで、オーナーのウインドウを指定してダイアログを表示するために利用できる。

#### 例：View(Window)でModelをnewする時の場合
- DialogServiceのプロパティWindowGuidを、WindowのTagにセット。
- CaluculateModelをnewする時に、Windowのタグを引数にして、CaluculateModelの_dialogServiceのWindowGuidにセット
- これにより、Windowのタグと、Modelの_dialogServiceのGuidとが一致する。
- そのDialogService経由でダイアログを表示する時は、一致するGuidがTagにセットされているWindowを検索し、そのWindowをオーナーにする。

``` csharp
public IDialogServiceView()
{
    InitializeComponent();

    Tag = _dialogService.WindowGuid; //for show OnWindow
}

private void CaluculateButton_Click(object sender, RoutedEventArgs e)
{
    var cls = new CaluculateModel(this.Tag.ToString());
    cls.Add(1, 2);
}
```

``` csharp
public CaluculateModel(string windowGuid)
{
    _dialogService.WindowGuid = windowGuid;
}
```

#### ModelのDialogServiceのWindowGuidを、ViewのWindowにセットする例
理屈では、次の通りで良い。

- Viewで、ModelのDialogServiceのWindowGuidを取得する。
- Viewで、そのGuidを、Windowのタグと、Viewの_dialogServiceのWindowGuidにセット

## 例外発生の可能性
``` csharp
if (owner is not null) this.Owner = owner;
```
のownerはWindowです。 ~~Windowが表示されていない時などの、ある条件下で、例外になる可能性があります。~~ 

次のようなコードに変更して、例外にならないように変更しました。
``` csharp
if (owner is not null && PresentationSource.FromVisual(owner) is not null) this.Owner = owner;
```
#### 参考
[ModernDialog.ShowMessage Error: "Cannot set Owner property to a Window that has not been shown previously."](https://stackoverflow.com/questions/28572331/moderndialog-showmessage-error-cannot-set-owner-property-to-a-window-that-has?rq=1)

## 機能作成方針
WPF用のメッセージボックスは、多く作成されています。ただ、次の要件に見合う物がなかったので、作成しました。

- メッセージボックスが表示されたと、認識しやすいこと。
- メッセージの追加情報は、隠しておいて、知りたい時は表示する。→　余分な情報があると分かりにくくなる。しかし、必要になる時があるので、その時は、表示したい。
- メッセージはコピーできる。

## 備考
- [WPF 対応の MessageBox クラス](http://www.kanazawa-net.ne.jp/~pmansato/wpf/wpf_custom_MessageBoxEx.htm)を参考にしました。

## 参照
次の記事で、DIコンテナの利用の仕方・OwnerのWindowを指定する方法・ユニットテスト、を解説しています。

https://qiita.com/hiro_t/items/b6ef800050897bd01f1b

## この記事の履歴
- 2022-02-06 この記事を公開。Ver 1.0を公開。
- 2024-09-15 Ver 2.0を公開したので、記事を修正