MVVMでダイアログを表示し、ダイアログオプションを設定します
-
29-09-2019 - |
質問
これがMVVMでダイアログを表示する方法だと思っていますか?
public ICommand OpenFileCommand
{
get
{
if (_openFileCommand == null) {
_openFileCommand = new RelayCommand(delegate
{
var strArr = DialogsViewModel.GetOpenFileDialog("Open a file ...", "Text files|*.txt | All Files|*.*");
foreach (string s in strArr) {
// do something with file
}
});
}
return _openFileCommand;
}
}
public class DialogsViewModel {
public static string[] GetOpenFileDialog(string title, string filter)
{
var dialog = new OpenFileDialog();
dialog.Title = title;
dialog.Filter = filter;
dialog.CheckFileExists = true;
dialog.CheckPathExists = true;
dialog.Multiselect = true;
if ((bool)dialog.ShowDialog()) {
return dialog.SafeFileNames;
}
return new string[0];
}
}
もしそうなら、私が示しているダイアログのオプションを変更することを自分自身に言うことをどのように許すべきですか。たとえば、別のダイアログに別のダイアログオプションがあることを望んでいます dialog.something = something_else
私の方法にたくさんの引数を追加することなく
解決
ダイアログ自体を表示することは、ViewModelで発生しないでください。私は通常、適切なダイアログメソッド呼び出しを使用して、ダイアログサービスインターフェイスIdialogServicesを提供します。次に、このインターフェイスを実装し、実際のshowロジックを実行するビュークラス(通常、MainWindow)の1つを使用します。これにより、ViewModelロジックが特定のビューから分離され、たとえば、ダイアログを開きたいユニットテストコードが可能になります。
主なタスクは、サービスインターフェイスを必要なViewModelに注入することです。これは、依存関係の噴出フレームワークがある場合に最も簡単ですが、サービスロケーター(インターフェイスの実装を登録できる静的クラス)でこれを行うか、コンストラクターを介してインターフェイスをビューモデルに渡すこともできます(ViewModelsに依存する方法構築されています。)
他のヒント
DialogServiceを使用することは重いアプローチだと思います。私はこの問題を処理するためにアクション/ラムダを使用するのが好きです。
あなたのビューモデルはこれを宣言として持っているかもしれません:
public Func<string, string, dynamic> OpenFileDialog { get; set; }
その後、発信者は次のようなビューモデルを作成します。
var myViewModel = new MyViewModel();
myViewModel.OpenFileDialog = (title, filter) =>
{
var dialog = new OpenFileDialog();
dialog.Filter = filter;
dialog.Title = title;
dynamic result = new ExpandoObject();
if (dialog.ShowDialog() == DialogResult.Ok) {
result.Success = true;
result.Files = dialog.SafeFileNames;
}
else {
result.Success = false;
result.Files = new string[0];
}
return result;
};
その後、次のように呼ぶことができます。
dynamic res = myViewModel.OpenFileDialog("Select a file", "All files (*.*)|*.*");
var wasSuccess = res.Success;
このタイプのアプローチは、テストのために本当に報われます。テストでは、ビューモデルのリターンを好きなものに定義できるため:
myViewModelToTest.OpenFileDialog = (title, filter) =>
{
dynamic result = new ExpandoObject();
result.Success = true;
result.Files = new string[1];
result.Files[0] = "myexpectedfile.txt";
return result;
};
個人的には、このアプローチは最も単純なものであると思います。他の考えが大好きです。