Показание диалогов в параметрах диалога MVVM и настройки

StackOverflow https://stackoverflow.com/questions/3919974

  •  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 не добавляя много аргументов в мой метод

Это было полезно?

Решение

Showing the dialog itself should not happen in a ViewModel. I usually provide a dialog service interface IDialogServices, with appropriate Dialog method calls. I then have one of the View classes (typically the MainWindow) implement this interface and perform the actual Show logic. This isolates your ViewModel logic from the specific View and, for instance, allows you to unit test code that wants to open a dialog.

The main task then is injecting the service interface into the ViewModel that needs it. This is easiest if you have a dependency-injection framework, but you can also do this with a service-locator (a static class where you can register interface implementations) or pass the interface to the ViewModel through its constructor (depends on how your ViewModels are constructed.)

Другие советы

I think using a DialogService is a heavy-weight approach. I like using Actions/Lambdas to handle this problem.

Your view model might have this as a declaration:

public Func<string, string, dynamic> OpenFileDialog { get; set; }

The caller then would create your view model like so:

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

You could then call it like:

dynamic res = myViewModel.OpenFileDialog("Select a file", "All files (*.*)|*.*");
var wasSuccess = res.Success;

This type of approach really pays off for testing. Because your tests can define the return on your view model to be whatever they like:

 myViewModelToTest.OpenFileDialog = (title, filter) =>
{
    dynamic result = new ExpandoObject();
    result.Success = true;
    result.Files = new string[1];
    result.Files[0] = "myexpectedfile.txt";

    return result;
};

Personally, I find this approach to be the most simplistic. I would love other's thoughts.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top