Potresti implementare l'interfaccia INotifyPropertyChanged e utilizzare i setter per eseguire le convalide. Una volta completata la convalida, si imposta il campo privato e si notifica la proprietà modificata per l'UI da aggiornare in base allo stato di ViewModel.
Ecco un esempio di codice.
class YourViewModel : INotifyPropertyChanged {
private State _state;
public event PropertyChangedEventHandler PropertyChanged;
public State State {
public get { return _state; }
public set {
ValidateState(value);
//If async operation is required, you could set
//this ViewModel state to "Validating" or something like that
}
}
//ValidateState
void ValidateState(State newState) {
//Perform validations
if (validEnough) {
//Change the actual state, and also the UI state
_state = newState;
//Tells ui to update its view
PropertyChanged(this, new PropertyChangedEventArgs("State"));
}
}
}
//Example of unit test
[TestMethod]
public void SetState_HasNoPermissions_DoesNotChangeState() {
//... setup resources for the test
yourViewModel.State = State.FirstStep;
Assert.NotEquals(yourViewModel.State, State.FirstStep);
}
Aggiornamento per indirizzare alcuni commenti
... I personally think ViewModel should only contain logic, but should not know anything about View
È corretto. Le cose importanti del tuo schermo sono lo stato, non il combobox (che non è noto a viewModel). Non riesco a vedere come il mio esempio fallisce.
Examples: ... it's not OK to generate readable text for View like error meessages ...
Chi ha detto che non è giusto farlo? Vedi qualche problema nell'avere un viewModel che carica messaggi localizzati in fase di runtime, per esempio? Se è OK o no dipenderà dalle esigenze della tua applicazione.
So the thing I'm trying to say is I do not agree with this: here your viewModel IS the user interface.
Quello che ho cercato di dire è che la grafica e il materiale visivo sono posizionati SOLO nella vista, e lo stato e il comportamento sono posizionati nel ViewModel. Pertanto, le GUI sono rappresentate in parte dalla vista e in parte dal ViewModel. Ecco perché ho detto che nell'esempio, viewModel è la tua interfaccia utente, dal momento che non sto considerando dettagli come Combobox o GridView o altro; Mi interessa solo il comportamento dello schermo e questo comportamento dovrebbe essere interamente implementato nel tuo viewModel, se hai scelto di seguire il pattern MVVM.
Ma non è necessario credermi, per favore basta leggere l'articolo Modello di presentazione (un altro nome per lo stesso modello) e l'altra fonte menzionata di seguito.
Also it's not view that requires validation - bussinss logic ruquires it. And therefore it should implemented in the ViewModel layer rather then in View layer.
Quello che intendevo è che potrebbe esserci un requisito come: " Quando l'utente modifica il valore dello stato, deve esserci una convalida su di esso e la vista deve aggiornare questo valore solo se la convalida ha esito positivo. "
Per questo motivo, si desidera implementare un comportamento sulla GUI dell'utente: l'utente cambia il valore di una casella combinata e la convalida avviene; se la validazione fallisce, il valore di combobox rimane lo stesso; altrimenti un nuovo valore è impostato nella casella combinata.
L'affermazione precedente è implementata dal mio esempio, seguendo il modello di progettazione ModelView-ViewModel. In realtà, nell'esempio di codice inserisco ValidateState nel ViewModel, ma l'idea è che viewModel attiva la logica di validazione che dovrebbe essere implementata da qualche altra parte; il codice serve come esempio per aiutarti nel tuo scenario di sviluppo. Ma se tutto sommato ti sembra una cattiva pratica dopotutto, questo è solo un suggerimento comunque:)
Programming best practices are same for everything. If you use MVVM architecture pattern it doesn't mean you should be allowed introducing code smells.
Sono d'accordo e personalmente non vedo l'odore del codice qui.
One last thing. If your viewModel IS the user interface then how is it different from code behind file? ... What is the actual benefit of separating ViewModel from View if ViewModel "serves" View?
Lasciatemi rispondere citando Martin Fowler nel suo articolo sul modello di presentazione:
Presentation Model: Represent the state and behavior of the presentation independently of the GUI controls used in the interface
... E citando l'articolo MVVM da Msdn:
It provides separation of concerns. ... A clean separation between application logic and the UI will make an application easier to test, maintain, and evolve. It improves code re-use opportunities and enables the developer-designer workflow.
Informazioni sul file code-behind: questa è solo la parte C # del tuo XAML. Tutto il codice che hai inserito dovrebbe riguardare solo i problemi di presentazione; idealmente, il comportamento e lo stato della GUI dovrebbero essere implementati nelle classi ViewModel. Almeno questo è ciò che è descritto come il modello, dalle fonti di seguito. Ti suggerisco di leggere e comprendere completamente gli articoli seguenti.
Fonti:
link
link