MahApps.Metroのダイアログを使ってみる
開発環境
- Visual Studio 2017 (C#)
- Visual Studioの拡張機能の「Prism Template Pack」
- Prism.Core 6.3.0
- Prism.Unity 6.3.0
- Prism.Wpf 6.3.0
- CommonServiceLocator 1.3.0
- Unity 4.0.1
- MahApps.Metro 1.5.0
初めに
WPFでシングルページアプリケーションを作成していても、やっぱりダイアログ表示がしたい!って時ありますよね?
でも、入力系のダイアログであれば、個人的には、カスタムダイアログではなく、フライアウトを推奨しますが、処理終了メッセージなんかは、やっぱりダイアログにしたいって時には、MahApps.Metroには、Metro風なダイアログがあるので、それを使ってみてはどうでしょうか?
※MahAppsのプロジェクトへのNuGet追加等の説明は省略
MahApps.Metro Dialogs
MahApps.Metroには、メッセージダイアログとプログレスダイアログがあります。
使用方法としては、非同期実行できるのでasync/await
を付けた上で、それぞれ記述は以下のようになります。
await this.ShowMessageAsync("This is the title", "Some message");
var controller = await this.ShowProgressAsync("Please wait...", "Progress message");
MVVMではそのままだとエラーになる
コードビハインドでの記述であれば、そのまま使用できますが、
Prism+Unityを使ったようなMVVM複合アプリケーションの場合は、UserControlもしくは、PageのViewModelに処理を記述するため、上記の書き方では、エラーになります。
- エラー画面
これは、MetroWindowの拡張機能で各メッセージダイアログのため、UserControlやPageからではエラーになります。
MVVMの場合は、公式のページでIDialogCoordinatorを使って例が出ています。
Support for viewmodels
You can open dialogs from your viewmodel by using the IDialogCoordinator.
Add the following code to your Window.xaml or UserControl.xaml:
MVVMの理屈からは崩れちゃうけど
そもそもM+V+VMでは、役割を分けましょうということで直接Viewに対しての指定は行わないのですが、
単純にダイアログは、MetroWindowから呼び出されるので、以下の方法でも表示できます。
-
public MetroWindow Metro { get; set; }
でプロパティを作り、カレントのMetroWindowを格納する -
Metro.ShowMessageAsync("This is the title", "Some message");
格納したMetroのShowMessageAsyncを指定する。
/// <summary>
/// MetroWindow
/// </summary>
public MetroWindow Metro { get; set; } = System.Windows.Application.Current.MainWindow as MetroWindow;
- メッセージダイアログの場合
/// <summary>
/// メッセージダイアログ コマンド
/// </summary>
private DelegateCommand showMessageCommand;
public DelegateCommand ShowMessageCommand =>
showMessageCommand ?? (showMessageCommand = new DelegateCommand(ShowMessageCommandExecute));
/// <summary>
/// メッセージダイアログ表示処理
/// </summary>
private async void ShowMessageCommandExecute()
{
await Metro.ShowMessageAsync("This is the title", "Some message");
}
- プログレスダイアログの場合
/// <summary>
/// プログレスダイアログ コマンド
/// </summary>
private DelegateCommand showProgressCommand;
public DelegateCommand ShowProgressCommand =>
showProgressCommand ?? (showProgressCommand = new DelegateCommand(ShowProgressCommandExecute));
/// <summary>
/// プログレスダイアログ表示処理
/// </summary>
private async void ShowProgressCommandExecute()
{
var controller = await Metro.ShowProgressAsync("Please wait...", "Progress message");
for (var i = 0; i < 10; i++)
{
controller.SetProgress(1.0 / 10 * i);
await Task.Delay(100);
}
await controller.CloseAsync();
}
実行結果
まとめ
MVVM複合アプリケーションでもMahApps.Metroのダイアログを使う場合に、公式にあるようにIDialogCoordinator
を使うのが良いのでしょうが、こんな方法でも一応表示はできます。
Window自体は、特に固定でView名を指定したわけではないので、このぐらいは許容範囲かなと個人的には思います。
既にQiita内でもViewModelから表示するIDialogCoordinatorを使用した方法を投稿されている方がすでにいらっしゃいました。
soiさんの投稿
こちらを参考にされたほうが良いかも?
補足情報
- 確認メッセージの場合は、以下のようにオプション指定をすることで可能です。
/// <summary>
/// メッセージダイアログ表示処理
/// </summary>
private async void ShowMessageCommandExecute()
{
var metroDialogSettings = new MetroDialogSettings()
{
AffirmativeButtonText = "はい",
NegativeButtonText = "いいえ",
AnimateHide = true,
AnimateShow = true,
ColorScheme = MetroDialogColorScheme.Theme,
};
var diagResult = await Metro.ShowMessageAsync("This is the title", "Some message", MessageDialogStyle.AffirmativeAndNegative, metroDialogSettings);
Console.WriteLine(diagResult);
}