MVVM ViewModel e comandi

6

Ho bisogno di un po 'di aiuto per capire la relazione tra un viewmodel e un comando e la responsabilità del viewmodel.

Proverò a dare un esempio (usando Caliburn Micro).

Ho una classe viewmodel, una classe di comando e una vista con un pulsante Salva.

public class EditViewModel : Screen
{
    public bool CanSave
    {
        get { return IsDirty; }
    }

    public void Save()
    {
        var command = new SaveCommand(this); // command gets reference to VM
        command.Execute();
    }
}

public class SaveCommand
{
    private readonly EditViewModel _viewModel;

    public SaveCommand(EditViewModel viewModel)
    {
        _viewModel = viewModel;
    }

    public void Execute()
    {
       var work = _viewModel.Work;
       ..
       _viewModel.IsDirty = false;
    }
}

Quando l'utente fa clic su Salva. Il metodo Save () viene chiamato e genera un comando che salva il lavoro.

Ora la mia domanda è, se il comando avesse un riferimento al viewmodel?

No) Il viewmodel dovrà passare il lavoro al comando, che dovrà restituire il risultato del salvataggio al viewmodel, che si aggiornerà da sé.

Sì) Il comando richiede un riferimento a viewmodel e le proprietà devono essere rese pubbliche.

No sembra il modo più pulito, ma richiede anche un lavoro extra, quando il lavoro o il risultato non sono un semplice bool o simili.

Credo che la radice sia tutto. Qual è la relazione tra un viewmodel e il suo comando e la responsabilità del viewmodel?

Esiste una strong relazione "amico" 1: 1 tra il modello di visualizzazione e il suo comando, in cui il codice è stato appena spostato in un'altra classe. Quindi non c'è niente di sbagliato con il comando che ha accesso diretto a viewmodel.

Un'altra comprensione, il viewmodel è una classe molto semplice, quasi solo con proprietà e contiene poca logica. Quindi la logica dovrebbe essere nel comando.

O il viewmodel è piuttosto intelligente e dovrebbe contenere la logica dell'applicazione. I comandi sono necessari solo quando ce ne sono troppi in un viewmodel o sono un po 'complicati altrimenti il codice di comando può rimanere nel viewmodel.

Sto solo vagando, suppongo, per favore aiutami a capire il modellismo e qual è la sua responsabilità?

    
posta Karsten 12.08.2013 - 16:22
fonte

5 risposte

6

Il comando dovrebbe essere on ViewModel.

In MVVM, ViewModel è la cosa che dovrebbe contenere tutta la logica che guida la vista. La vista è la semplice classe: solo una raccolta di controlli dell'interfaccia utente il cui stato è associato alle proprietà sul ViewModel.

Josh Smith ha scritto una buona introduzione a MVVM che dovrebbe chiarire le cose per te.

    
risposta data 12.08.2013 - 16:48
fonte
3

MVVM eredita direttamente dal pattern originale di Smalltalk MVC come definito da Trygve Reenskaug . Proprio come MVC è molto frainteso, MVVM è pure. Nella definizione originale, MVC consisteva in un modello concettuale (al quale oggi ci riferiamo come un modello di dominio) che contiene i dati e la logica che alimenta un'applicazione, una vista che fornisce una rappresentazione visiva di quel modello concettuale e un controller che ascolta agli eventi sulla vista e li gestisce come operazioni all'interno del Modello.

Ciò che le persone dimenticano è che l'ambiente Smalltalk era praticamente la prima GUI esistente. Questo è il vero progetto di Xerox che Jobs ha "emulato" per Lisa (e che Microsoft ha successivamente sfruttato per Windows). Smalltalk aveva un sistema di interfaccia utente di livello molto basso, simile alla programmazione diretta dell'API Win32. Il controller era responsabile dell'ascolto del messaggio pump e della conversione dei messaggi giunti nell'interfaccia utente in operazioni logiche. Non c'erano librerie di widget quando il modello MVC è stato concepito per la prima volta.

Avanzamento veloce di alcuni anni e Smalltalk è un prodotto commerciale (VisualWorks) con widget e un nuovo modello è emerso: MMVC , questo è MVC con due modelli: il modello di dominio che è ciò che intendiamo essere; e il modello di applicazione che più o meno è un modello specifico per l'applicazione stessa, contenente concetti importanti per l'applicazione ma non per il dominio.

Permettetemi di indicare un punto interessante nell'argomento Wiki C2 su MMVC (enfasi mia):

So what, you say. Well, here's what. As a point of general principle, people who talk about MVC architecture (such as people in the J2EE and JSP communities) should take it upon themselves to understand the historical meaning and implications of the terms they use, so as to eliminate confusion about WhatsaControllerAnyway, and to be aware that ModelViewController often means ModelModelViewController in the original Smalltalk implementation of the paradigm. In fact, a case could probably be made that many of the responsibilities allocated to the "controller" (in the Jacobsonian connotation of the term) were probably allocated to ApplicationModels in ModelModelViewController architecture.

L'architettura MMVC forniva le responsabilità del modello applicativo normalmente assegnate al controller. A causa dell'introduzione di widget in VisualWorks che sapevano cose come "Sono un pulsante e qualcuno mi ha fatto clic". I controllori non avevano bisogno di contenere la stessa logica a cui erano abituati. L'invio delle operazioni gravitava verso il modello di applicazione e lontano dal controller.

MVVM è MMVC senza un controller separato. ViewModel deve contenere la logica al suo interno, ma solo quanto basta per interpretare un comando e inviarlo al modello per ulteriori informazioni. Come ho detto prima, Caliburn fa molti cablaggi per te per convenzione. Quindi, invece di dover registrare un comando di inoltro e farlo risolvere al metodo, Caliburn cerca un metodo sul ViewModel chiamato Salva e collega un comando per te che è registrato sul pulsante con una X: Name of Save, puntandolo al tuo metodo di salvataggio.

    
risposta data 19.08.2013 - 17:15
fonte
2

Riformerò ciò che ha detto Mike Brown.

Il punto principale dei comandi è consentire un facile collegamento dati da DataContext a controlli attivi, come i pulsanti. Quindi si crea una classe di comando, la si espone come proprietà e si associa a un pulsante. Questo pulsante chiamerà Execute se premuto. Questo è semplicemente perché non è possibile associare direttamente i metodi. E ti consente anche di avere CanExecute in un posto come ciò che viene eseguito.

Ma con Caliburn.Micro, ti permette di legare i metodi direttamente attraverso la convenzione. In realtà crea un comando internamente per te. Quindi con Caliburn.Micro, i comandi personalizzati sono praticamente inutili.

    
risposta data 13.08.2013 - 17:07
fonte
1

Caliburn usa "convenzioni" per le funzioni di Autowire come comandi per comandare i bersagli. Quindi la tua funzione Salva sul tuo ViewModel viene ordinatamente racchiusa in un comando dietro le quinte (leggi la sezione su Corrispondenza delle azioni nella documentazione di Caliburn su Convenzioni ) per scoprire come funziona.

In sostanza, puoi saltare la creazione di comandi a tutti, perché caliburn usa le convenzioni per rimuovere alcune delle cerimonie di MVVM per te.

    
risposta data 12.08.2013 - 18:01
fonte
0

Ecco un esempio della classe del modello di visualizzazione che utilizza MVVM Light Toolkit :

public class EditViewModel : ViewModelBase
{
    public EditViewModel()
    {
        SaveCommand = new RelayCommand(noParameter => Save());
    }

    private void Save()
    {
        // Save code goes here.
    }

    public static ICommand SaveCommand { get; private set; }
}

La classe RelayCommand trasmetterà tutti gli usi della proprietà SaveCommand al metodo Save() nella classe del modello di vista. Il comando stesso non ha bisogno di fare riferimento alla classe del modello di vista poiché è un membro della classe del modello di vista.

    
risposta data 12.08.2013 - 17:14
fonte

Leggi altre domande sui tag