LoginSignup
9
10

More than 1 year has passed since last update.

WPF Prism の IDialogService で汎用的なダイアログを出せるものを作った

Last updated at Posted at 2020-03-19

はじめに

Prism7.2 から IDialogService が実装されてダイアログ表示がいい感じになった。
しかし、通知用や確認用などの汎用的なダイアログをプロジェクトごとにいちいち作るのも面倒くさい。
なので IDialogService で呼び出せる一般的に使いそうなダイアログを作ってライブラリ化して nuget に公開した。

できたもの

Prism.CommonDialogPack

機能

通知ダイアログ

Norification.png

確認ダイアログ

Confirmation.png

ファイル選択ダイアログ

単体選択
SingleFileSelect.png
複数選択
MultiFileSelect.png

フォルダ選択ダイアログ

単体選択
SingleFolderSelect.png
複数選択
MultiFolderSelect.png

ファイル保存ダイアログ

FileSave.png

アイコンなどのカスタマイズ

Customize.png

Window のカスタマイズ

MahApps.png

使い方

IDialogService 自体の使い方は公式ドキュメントを読むのが早い。
ここでは Prism.CommonDialogPack の使い方だけを記述する。

インストール

nuget に公開したのでパッケージマネージャーコンソールから簡単にインストールできる。
Install-Package PrismCommonDialogPack

登録

まずは App でモジュールとサービスの登録を行う。

App.xaml.cs
public partial class App
{
    protected override Window CreateShell()
    {
        return Container.Resolve<MainWindow>();
    }

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {

    }

    protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
    {
        base.ConfigureModuleCatalog(moduleCatalog);
        moduleCatalog.AddModule<CommonDialogPackModule>();
    }

    protected override void RegisterRequiredTypes(IContainerRegistry containerRegistry)
    {
        base.RegisterRequiredTypes(containerRegistry);
        containerRegistry.RegisterSingleton<Prism.Services.Dialogs.IDialogService, StyleableDialogService>();
    }
}

Prism が提供してくれている DialogService は Window の Style を DialogWindow を介してセットしているが、Window に単に代入するような実装になっているのでライブラリにした時に呼び出し側から Style を指定することができない。
Prism.CommonDialogPack では Dialog の呼び出し側から Style を指定できるようにするため、DialogService を継承したStyleableDialogService を作っている。
違いはConfigureDialogWindowContentメソッドだけで、ViewModel が IStyleableDialogAware だった場合は Style をバインディングするようにしている。
また、WindowStartupLocation もここで設定している。

IStyleableDialogAware は IDialogAware に WindowStyle や Height, Width などを追加したインターフェイスで、ダイアログとして表示する View の ViewModel に実装することでライブラリの呼び出し側からの Style 指定などを可能にしている。

RegisterRequiredTypes では標準の IDialogService の実態を DialogService ではなく StyleableDialogServiceにするようにコンテナに登録している。

呼び出し

呼び出しは IDialogService を介して行う。

MainWindowViewModel.cs
private void ShowNotificationDialog(IDialogService dialogService)
{
    var param = new DialogParameters
    {
        { DialogParameterNames.Title, "myNotification" }
    };
    dialogService.ShowDialog(DialogNames.Notification, param, res => 
    {
    });
}

こんな感じで通常の DialogService と変わらない。
呼び出せるダイアログの名前は DialogNamesに、
指定できるパラメーターの名前はDialogParameterNamesに、
受け取れるパラメーターの名前はDialogResultParameterNamesに定義してある。
パラメーターの受け取りは FileSelectDialog、FolderSelectDialog、FileSaveDialog でのみ可能で、コールバックで受け取れる IDialogResult の Parameters プロパティから取得する。

各ダイアログで指定できるパラメーターは以下の通り

共通

名前 内容
Title string Window のタイトル
Width double Window の幅
Height double Window の高さ
ContentWidth double Content の幅
ContentHeight double Content の高さ
WindowStyle System.Windows.Style Window の Style
StartupLocation System.Windows.StartupLocation Window の表示位置
ResizeMode System.Windows.ResizeMode Window のリサイズ可否と方法
SizeToContent System.Windows.SizeToContent コンテンツのサイズに Window を合わせるか

※SizeToContent を Manual 以外にした場合は Width, Height を指定していても指定した SizeToContent が優先されるので注意

NotificationDialog

名前 内容
Message string 表示するメッセージ
ButtonText sgring ボタンのテキスト

ConfirmationDialog

名前 内容
Message string 表示するメッセージ
OKButtonText sgring OK ボタンのテキスト
CancelButtonText sgring Cancel ボタンのテキスト

FileSelectDialog

名前 内容
ExplorerIcons Prism.CommonDialogPack.ExplorerIcons アイコン
FileNamePrefixText string ファイル名の前に表示されるテキスト
SelectButtonText string 選択ボタンのテキスト
CancelButtonText string Cancel ボタンのテキスト
Filters IEnumerable<Prism.CommonDialogPack.FileFilter> 表示するファイルのフィルター
TextResource Prism.CommonDialogPack.ExplorerBaseTextResource ExplorerBase に表示するテキスト
CanMultiSelect bool 複数選択可能かどうか
RootFolders IEnumerable<string> ルートにするフォルダーのパス

FolderSelectDialog

名前 内容
ExplorerIcons Prism.CommonDialogPack.ExplorerIcons アイコン
FolderNamePrefixText string フォルダー名の前に表示されるテキスト
SelectButtonText string 選択ボタンのテキスト
CancelButtonText string Cancel ボタンのテキスト
TextResource Prism.CommonDialogPack.ExplorerBaseTextResource ExplorerBase に表示するテキスト
CanMultiSelect bool 複数選択可能かどうか
RootFolders IEnumerable<string> ルートにするフォルダーのパス

FileSaveDialog

名前 内容
ExplorerIcons Prism.CommonDialogPack.ExplorerIcons アイコン
FileNamePrefixText string ファイル名の前に表示されるテキスト
FileTypePrefixText string ファイルの種類の前に表示されるテキスト
SaveButtonText string 保存ボタンのテキスト
CancelButtonText string Cancel ボタンのテキスト
DefaultSaveFileName string 初期ファイル名
Filters IEnumerable<Prism.CommonDialogPack.FileFilter> 表示するファイルのフィルター
TextResource Prism.CommonDialogPack.ExplorerBaseTextResource ExplorerBase に表示するテキスト
CanMultiSelect bool 複数選択可能かどうか
RootFolders IEnumerable<string> ルートにするフォルダーのパス
OverwriteConfirmationTitle string 上書き確認ダイアログのタイトル
OverwriteConfirmationMessageFunc Func<string, string> 上書き確認ダイアログのメッセージ生成関数
OverwriteConfirmationOKButtonText string 上書き確認ダイアログの OK ボタンのテキスト
OverwriteConfirmationCancelButtonText string 上書き確認ダイアログの Cancel ボタンのテキスト

OverwriteConfirmationMessageFunc にはファイルのフルパスが渡される。これを指定することで上書き確認ダイアログで表示するメッセージを呼び出し側から書き換えることが可能。

その他のクラスについて

ExplorerIcons

パラメーターで渡せば FileSelectDialog, FolderSelectDialog, FileSaveDialog のアイコンをカスタムできる。

FileFilter

パラメーターで渡せば FileSelectDialog, FileSaveDialog で表示するファイルの拡張子にフィルターをかけることができる。

new FileFilter("All Files (*.*)"),
new FileFilter("Text File (*.txt; *.csv)", new[] { ".txt", ".csv" }),
new FileFilter("Excel File (*.xlsx; *.xlsm; *.xls)", ".xlsx", ".xlsm", ".xls"),

使い方はこんな感じで、Text プロパティの文字列が ComboBox に表示され、Extensions プロパティの文字列が実際にフィルターする拡張子となる。
Extensions が空だとフィルターしない。
FileSaveDialog の場合は保存するファイルの拡張子を指定する意図で使用するため、Extensions を複数指定しても最初のものだけフィルターされる。

ExplorerBaseTextResource

パラメーターで渡せば ExplorerBase の各テキストをカスタムできる。

DialogServiceExtensions

ダイアログの呼び出しを簡素化した拡張メソッドを定義したクラス。

使用例
dialogService.ShowNotification("Notification", "Notification", res => Console.WriteLine(res.Result));

Window のカスタマイズ

これ自体は IDialogService の機能なので、やり方も同じ。
ダイアログに使いたい Window にコードビハインドでIDialogWindowを実装する
IDialogWindowIDialogResultプロパティを持っているだけ

MyMetroWindow.xaml.cs
public partial class MyMetroWindow : MetroWindow, IDialogWindow
{
    public IDialogResult Result { get; set; }

    public MyMetroWindow()
    {
        InitializeComponent();
    }
}

あとはRegisterDialogWindowでコンテナに登録する

App.xaml.cs
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
    containerRegistry.RegisterDialogWindow<MyMetroWindow>();
}

おわりに

Prism.CommonDialogPack にはサンプルもつけているので、詳細はそっちを見ればわかるかも。

9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10