2016-04-27 8 views
1

Ich bin im Moment ein wenig verwirrt, weil ich mich nicht sicher bin über Dinge wie "Wer ist verantwortlich für die Validierung von Modelldaten".MVVM - Wer ist verantwortlich für

ihm ein Beispiel geben:

Ich habe einen Antrag bekommen, in dem eine Beziehung zwischen einer Person und bestimmten Geräten sichtbar gemacht wird.

public class Person{ 
    public string Firstname {get; set;} 
    public string Lastname {get; set;} 
    public SomeSortOfDevice SomeSortOfDevice {get; set;} 
} 

public class SomeSortOfDevice{ 
    public DateTime DeviceExpiration {get; set;} 
    public string DeviceSerialCode {get; set;} 
    //public bool IsSerialCodeValid{get{ 
    //  SomeValidationLogic() 
    //} 
} 

In der Ansicht der App kann der Benutzer die Daten des Geräts ändern. Jetzt gibt es einige Regeln - zum Beispiel ist der DeviceExpiration an eine TextBox gebunden, sollte aber nur aktiviert werden, wenn ein gültiger SerialCode gesetzt ist.

Aber wer entscheidet, ob der SerialCode gültig ist? Das Modell selbst? Das ViewModel? Sollte das Modell eine zusätzliche Eigenschaft "IsSerialValid" enthalten oder wie könnte die IsEnabled-Eigenschaft einer TextBox an diese Regel gebunden sein?

bearbeiten 1

public class ViewModel{ 
    public Person SelectedPerson {get; set;} 
} 

Das ist, wie ich die Modelle oben benutzen würde - The View wird einige Bindungen auf dem SeletedPerson bekommen.

Edit 2

ich denke, es Ein bisschen mehr complicaten ist, als ich es vorher erklärt. Nehmen wir an, das Gerät ist ein Token und ich möchte feststellen, ob der Benutzer etwas eingegeben hat - wenn er etwas eingegeben hat, ist es gültig?

Wenn die Validierung sollte in Modell behandelt werden (wie ich es im Moment haben) das Modell würde wie folgt aussehen:

public Token{ 
    public DateTime ExpirationDate {get; set;} 
    public string Serial {get; set;} 
    public bool IsTokenExpired{ 
     get{ 
      return ExpirationDate.Date < DateTime.Now; 
     } 
    } 
    public bool IsTokenValid{ 
     get{ 
      return new Regex("[0-9]{8,12}").Match().Success; 
     } 
    } 
    public bool IsTokenSet{ 
     get{ 
      return TokenSerial.Length > 0; 
     } 
    } 
} 

nun die TextBox zu aktivieren, wo der Benutzer eingeben soll (oder wählen Sie) ein Datum, die Bindung sieht wie folgt aus:

<TextBox IsEnabled="{Binding SelectedPerson.Token.IsTokenValid}"/> 

das funktioniert ganz gut, aber ich habe im Modell ein gutes Gefühl über die Validierungsregeln nicht wirklich bekam.

+0

Das 'ViewModel' sollte die Validierungen verarbeiten – bit

+0

Können Sie uns den Befehl zeigen, den Sie ausführen möchten, wenn die Validierungen bestanden werden? – bit

+1

Schauen Sie in IDataErrorInfo, WPF-Steuerelemente unterstützen es. –

Antwort

0

Keine Notwendigkeit, eine zusätzliche Eigenschaft zu halten. Implementieren Sie einfach die Schnittstelle INotifyPropertyChanged, die ein Ereignis auslöst, wenn sich der Eigenschaftswert ändert.

Sie können das Ereignis der geänderten Eigenschaft der Eigenschaft im Ansichtsmodell anhören und die Überprüfung dort durchführen. So wird die Ansicht auch in einem MVVM-Modell aktualisiert.

Sie können auch die IsEnabled-Eigenschaft des Textfelds an eine Viewmodel-Eigenschaft binden, die während der Überprüfung festgelegt wird, wenn sie einen gültigen Wert enthält.

Wenn Sie möchten, können Sie auch einen Konverter für die IsEnabled-Eigenschaft verwenden und den Text als Befehlsparameter übergeben, sodass der Konverter den Text prüft und den bool-Wert der IsEnabled-Eigenschaft des Textfelds nach Bedarf festlegt.

+0

Das ist die Frage - ist es eine Validierung oder Konversation, wenn ich eine Eingabe validieren und als Bool-Wert darstellen möchte. Nehmen wir an, ich habe 10 TextBoxes und einen Button in meiner View - der Button sollte aktiviert sein, wenn alle TBs einen gültigen Dateipfad haben - sollte mein ViewModel 10 zusätzliche Eigenschaften "IsFileOneValid" usw. behandeln um die anderen Controls auf dem zu benachrichtigen Blick auf den Validierungsstatus? – C4p741nZ

+0

Nein, Sie können es mit einer einzigen Eigenschaft verwalten. Sie können das geänderte Ereignis der Eigenschaft oder der Eigenschaft der Eigenschaft überwachen und die Überprüfung beim Auftreten des Ereignisses durchführen und einen booleschen Wert auf "true" oder "false" setzen. Diese Bool-Eigenschaft ist an die IsEnabled-Eigenschaft der Schaltfläche gebunden. Selbst wenn ein Textfeld ungültig ist, ist die Eigenschaft falsch und die Schaltfläche ist inaktiv. – ViVi

1

Ich denke, es hängt alles von dem spezifischen Design ab. Im Allgemeinen können Sie einige Logikprüfungen im Modell implementieren, aber das Modell sollte nicht mit der Benutzeroberfläche kommunizieren (und nicht kommunizieren). Normalerweise würde das Modell die Daten einfach nicht speichern, wenn etwas nicht stimmt.

Die Sichtbarkeit von Steuerelementen sollte in ViewModel behandelt werden, wie Sie in Ihrem Code richtig vorgeschlagen haben.Wenn jedoch in Ihrem Fall ein falscher serieller Code eingegeben wird, wird die IsValid-Eigenschaft nicht geändert (da in wird auf Anforderung berechnet). Der bessere Weg wäre, den Seriencode im Setter von DeviceSerialCode zu überprüfen und den IsSerialCodeValid von dort zu setzen. Damit die Benutzeroberfläche die Änderung widerspiegelt, sollte Ihr ViewModel auch die INotifyPropertyChanged-Schnittstelle implementieren und Änderungen an den Eigenschaften in ihren Ssettern signalisieren.

+0

Wenn Sie sagen, dass das Modell nicht mit der Ansicht kommunizieren soll - bedeutet das, dass es nicht korrekt ist, z. SelectedPerson.Firstname (da SelectedPerson vom Typ Person (Model) ist), aber stattdessen eine zusätzliche Eigenschaft firstname im ViewModel selbst implementieren? Scheint so, als würde dies zu einem Durcheinander führen ... – C4p741nZ

+0

Ich denke, es ist in Ordnung, Modellobjekte in Datenbindungen zu referenzieren, aber im Allgemeinen sollten Sie keine zusätzlichen Felder im Modell erstellen, die einige UI - Eigenschaften widerspiegeln (zB Sichtbarkeit von Elementen usw.) .). Das Modell sollte die Problemdomäne widerspiegeln, und viewmodel sollte die gesamte Ansichtslogik behandeln. –

2

Nun, das ist nur eine Meinung, aber so würde ich es tun.

Zunächst sollten Sie Ihr Modell eine Validierungsmethode haben, so etwas wie public bool ValidateSerial(string serial);

Dann in Ihrem Viewmodel Sie eine Eigenschaft werde haben zur TextBox binded und Sie werden die Kontrolle dort tun, so etwas wie:

_private string _serialNumber; 
public string SerialNumber 
{ 
    get 
    { 
     return this._serialNumber; 
    } 
    set 
    { 
     this._serialNumber=value; 
     RaisePropertyChanged("SerialNumber"); 
     this.IsSerialValid=Model.ValidateSerial(string serial); 
     RaisePropertyChanged("IsSerialValid"); 
    } 
    public bool IsSerialValid { get; set;} 
} 

Die Eigenschaft IsSerialValid ist diejenige, die Sie an die Eigenschaft IsEnabled der anderen TextBox binden.

Hoffe, dass dies für Sie sinnvoll ist.

+0

Das sieht sehr nach der Lösung aus, die ich beim Momen habe - wie in meinem Schnitt erwähnt, bin ich nicht wirklich glücklich mit diesem – C4p741nZ

+0

Ich bemerkte, dass in diesem Fall SerialNumber eine Eigenschaft Ihres ViewModel wäre - warum sollte ich das tun Wenn SerialNuber bereits in meinem Modell enthalten ist? – C4p741nZ

+0

Weil im Modell keine Eigenschaft, sondern eine Validierungsmethode ist. Ich habe den Namen geändert, weil es @ Chill-X verwirrend war – Pikoh

Verwandte Themen