2

我只是想知道这是在 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,而无需向我的方法添加大量参数

4

2 回答 2

5

我认为使用 DialogService 是一种重量级的方法。我喜欢使用 Actions/Lambdas 来处理这个问题。

您的视图模型可能将其作为声明:

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;
};

就个人而言,我发现这种方法是最简单的。我会喜欢别人的想法。

于 2010-10-13T20:56:52.767 回答
5

显示对话框本身不应该发生在 ViewModel 中。我通常提供一个对话服务接口 IDialogServices,带有适当的 Dialog 方法调用。然后我有一个 View 类(通常是 MainWindow)实现这个接口并执行实际的 Show 逻辑。这将您的 ViewModel 逻辑与特定视图隔离开来,例如,允许您对想要打开对话框的代码进行单元测试。

然后主要任务是将服务接口注入到需要它的 ViewModel 中。如果您有一个依赖注入框架,这是最简单的,但您也可以使用服务定位器(一个可以注册接口实现的静态类)或通过其构造函数将接口传递给 ViewModel(取决于您的 ViewModels被构造。)

于 2010-10-13T00:19:11.793 回答