Domanda

Mi chiedo solo è questo il modo per mostrare le finestre di dialogo in 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];
    }
}

Se sì, come dovrei permettere a me stesso di dire modificare le opzioni di dialogo che sto mostrando. Esempio, voglio un'altra finestra di avere diversi opzioni di dialogo dialog.something = something_else senza l'aggiunta di un sacco di argomenti per il mio metodo

È stato utile?

Soluzione

Mostra la finestra di per sé non dovrebbe accadere in un ViewModel. Io di solito fornire un servizio di dialogo IDialogServices interfaccia, con le appropriate chiamate di metodo di dialogo. Ho poi avuto una delle classi di Vista (in genere il MainWindow) implementare questa interfaccia ed eseguire il Salone logica attuale. Questa isola la logica ViewModel dalla specifica View e, per esempio, permette di codice di unit test che vuole aprire una finestra di dialogo.

Il compito principale viene quindi iniettare l'interfaccia di servizio nella ViewModel che ne ha bisogno. Questo è più facile se si dispone di un quadro di dipendenza-iniezione, ma è anche possibile fare questo con un servizio-locator (una classe statica in cui è possibile registrare le implementazioni di interfaccia) o passare l'interfaccia per il ViewModel attraverso il suo costruttore (dipende da come i tuoi ViewModels sono costruiti.)

Altri suggerimenti

Credo che utilizzando un DialogService è un approccio pesante. Mi piace usare azioni / Lambda per gestire questo problema.

Il tuo modello di vista potrebbe avere questo come una dichiarazione:

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

Il chiamante quindi creerebbe il tuo modello di vista in questo modo:

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

È quindi possibile chiamare come:

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

Questo tipo di approccio realmente paga per il test. Poiché i test possono definire il ritorno del modello al fine di essere ciò che vogliono:

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

    return result;
};

Personalmente, trovo questo approccio per essere il più semplice. Mi piacerebbe altri pensieri.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top