MVVM – Validazione

Stiamo cercando di capire la convalida nel mvvm facendo convalida nella logica o nel modello di business. Ho implementato la convalida per tipo di eccezione nella nostra logica di business: uno schema semplificato può essere trovato qui: alt text

Se abbiamo molti ingressi indipendenti l’uno dall’altro, non ci sono problemi, l’eccezione viene lanciata, la casella di testo lo prende e segna i suoi bordi rossi per ogni input sbagliato. Tuttavia, quando abbiamo valori dipendenti, siamo nei guai. per esempio

  • Valore1 e Valore2 nel modello non devono essere uguali, quindi abbiamo una funzione di convalida in ognuno di quelli che cercano il valore uguale e generano un’eccezione se ciò accade

  • ora, se impostiamo Valore1 su 0 e Valore2 su 1 tutto va bene

  • Valore 1 viene impostato nella GUI su 1 -> questo viene contrassegnato in rosso, perché la convalida degli altri valori non viene triggersta, quindi Valore2 nella GUI non è contrassegnato come difettoso

  • Value2 viene impostato su 2 nella GUI, ora abbiamo raggiunto uno stato valido, ma solo Value2 viene convalidato, quindi Value1 è ancora contrassegnato come difettoso

C’è un modello comune per risolvere questo problema? non vogliamo introdurre una dipendenza nell’interfaccia grafica tra le due caselle di testo, perché questa logica dovrebbe essere presente solo nel livello della logica aziendale.

Invece di implementare la validazione per eccezione si potrebbe anche implementare l’interfaccia IDataErrorInfo, ma il problema esiste ancora, non c’è modo di forzare valori dipendenti per convalidare nuovamente i loro valori, almeno nessuno che io possa vedere 🙂

Qualsiasi aiuto è apprezzato

evviva, manni


[pulizia, rimosso passaggio non necessario]


15.11.2010 – Parte 2

ok, grande ripensamento qui, stiamo andando con il livello businesslogic. ecco la nostra attuale configurazione pianificata: alt text (l’immagine è un po ‘piccola in scala qui, per favore aprila su una finestra separata per mostrarla a grandezza intera) tutto è più o meno chiaro, eccetto come notificare tutti i viewmodels / modellini di cloni dei diversi editor se il modello dei dati sotto la logica del business viene cambiato. un modo per farlo è tracciare i modelli clonati nella logica aziendale che li crea. Quando il modello di dati viene modificato utilizzando la business logic commit (), tutti gli altri cloni di modello registrati possono essere informati delle modifiche e propagandole ulteriormente. in alternativa, la logica di business potrebbe pubblicare un evento a cui tutti i viewmodels si iscrivono in modo da ottenere anche i cambiamenti – qualcuno potrebbe darmi un suggerimento che cosa è meglio?

Grazie ancora per l’aiuto, mi dispiace, sono così bloccato a mente;)

Potresti considerare l’utilizzo dell’interfaccia System.ComponentModel.IDataErrorInfo . Questa interfaccia molto utile ti dà la possibilità di:

  • effettuare la convalida in modo conforms a MVVM
  • fai una convalida personalizzata per ogni campo particolare (la convalida può controllare diversi valori se vuoi che lo faccia)
  • associa l’interfaccia utente agli errori di convalida

Implementa IDataErrorInfo sul tuo viewmodel (o anche virtualmente nel tuo modello di vista e lo sostituisci nei modelli di visualizzazione derivati). A causa della natura del databinding, i valori che ho bisogno di controllare sono tutti lì nel modello di vista, e posso testare qualsiasi combinazione di essi. Naturalmente hai ancora la tua convalida nel tuo livello aziendale, ma non hai più bisogno di fare un viaggio al tuo livello aziendale (o Modello) solo per effettuare qualche convalida.

Ecco un rapido esempio da una schermata (WPF) che raccoglie alcuni dettagli dell’utente e fa la convalida di base su di essi:

Codice C #:

#region IDataErrorInfo Members ///  /// Gets an error message indicating what is wrong with this object. ///  ///  /// An error message indicating what is wrong with this object. The default is an empty string (""). public override string Error { get { return this["UserCode"] + this["UserName"] + this["Password"] + this["ConfirmedPassword"] + this["EmailAddress"]; } } ///  /// Gets the  with the specified column name. ///  ///  public override string this[string columnName] { get { switch (columnName) { case "UserCode": if (!string.IsNullOrEmpty(UserCode) && UserCode.Length > 20) return "User Code must be less than or equal to 20 characters"; break; case "UserName": if (!string.IsNullOrEmpty(UserCode) && UserCode.Length > 60) return "User Name must be less than or equal to 60 characters"; break; case "Password": if (!string.IsNullOrEmpty(Password) && Password.Length > 60) return "Password must be less than or equal to 60 characters"; break; case "ConfirmedPassword": if (Password != ConfirmedPassword) return Properties.Resources.ErrorMessage_Password_ConfirmedPasswordDoesntMatch; break; case "EmailAddress": if (!string.IsNullOrEmpty(EmailAddress)) { var r = new Regex(_emailRegex); if (!r.IsMatch(EmailAddress)) return Properties.Resources.ErrorMessage_Email_InvalidEmailFormat; } break; } return string.Empty; } } #endregion 

e qui c’è il markup XAML per due delle caselle di testo sulla pagina (si noti in particolare le proprietà ValidatesOnDataErrors e ValidatesOnExceptions nell’associazione Text ):

   

C’è un modello comune per risolvere questo problema? non vogliamo introdurre una dipendenza nell’interfaccia grafica tra le due caselle di testo, perché questa logica dovrebbe essere presente solo nel livello della logica aziendale.

  1. Value1 e Value2 sono interdipendenti a causa della condizione “Valore1 e Valore2 nel modello non devono essere uguali”.

  2. Ciò significa che quando Value2 cambia, anche Value1 cambia e vice verse! In realtà, quando Value2 cambia, il risultato della validazione Value1 cambia, ma questo è vicino all’istruzione precedente.

  3. Value1 setter Value1 e Value2 devono notificare sia la modifica della proprietà Value2 che Value2 .

  4. La vista deve rileggere e riconvalidare entrambi i valori e cancellare il marchio difettoso.

  5. Non sono sicuro che WPF lo farà se scopre che l’evento di notifica è stato sollevato ma il valore in realtà non è cambiato.