2012-11-28 13 views
7

Ich habe eine WPF Anwendung (.Net 3.5), die die IDataErrorInfo auf dem ViewModel verwendet, um Eingaben zu validieren.IDataErrorInfo: Wie kann man feststellen, ob alle Eigenschaften gültig sind?

Es funktioniert gut, die usercontrol erhalten die richtige UI-Feedback.

Das Problem ist, dass der Benutzer das ausgewählte Element noch ändern oder dieses Element speichern kann.

Also meine Frage ist: Wie kann ich wissen, dass alle meine Eigenschaften gültig sind? Oder zumindest, dass alle meine angezeigten Werte gültig sind. Das Ziel ist, einige IsActive auf dieses Ergebnis zu binden

+0

Wenn der Fehler Eigenschaft nicht null oder leer ist dann wird es einen Fehler geben –

+0

Wo möchten Sie wissen, ob sie alle gültig sind? In der Ansicht oder im ViewModel? – Blachshma

+0

Ich denke, die Antwort kann Ihnen helfen: http://StackOverflow.com/Questions/104520/WPF-validation-for-the-Whole-form –

Antwort

15

Von Ihrem Kommentar zu Ihrer Implementierung von IDataErrorInfo Ihre Implementierung dieser Art ändern ....

#region IDataErrorInfo Members 

public string Error 
{ 
    get { return this[null] } 
} 

public string this[string columnName] 
{ 
    get 
    { 
     StringBuilder result = new StringBuilder(); 
     if (string.IsNullOrEmpty(columnName) || columnName == "FirstName") 
     { 
      if (string.IsNullOrEmpty(FirstName)) 
       result.Append("Please enter a First Name\n"); 
     } 
     if (string.IsNullOrEmpty(columnName) || columnName == "LastName") 
     { 
      if (string.IsNullOrEmpty(LastName)) 
       result.Append("Please enter a Last Name\n"); 
     } 
     if (string.IsNullOrEmpty(columnName) || columnName == "Age") 
     { 
      if (Age < = 0 || Age >= 99) 
       result.Append("Please enter a valid age\n"); 
     } 
     return (result.Length==0) ? null : result.Remove(result.Length-1,1).ToString(); 
    } 
} 

#endregion 


public bool IsValid { 
    get { return string.IsNullOrEmpty(this.Error); } 
} 

Dann in Ihrer Eigenschaft verändertes Ereignis

if (e.PropertyName == "Error") { 
    OnPropertyChanged(this,new PropertyChangedEventArgs("IsValid")); 
} 
if (e.PropertyName != "Error" && e.PropertyName != "IsValid") { 
    OnPropertyChanged(this,new PropertyChangedEventArgs("Error")); 
} 
+0

Oh, deshalb ist der Fehler? Ich habe das vorher nicht verstanden und in allen Beispielen fand ich, das wurde nicht implementiert – J4N

+1

@ J4N ja, Fehler soll eine Zusammenfassung dessen sein, was mit dem Objekt selbst falsch ist, normalerweise als eine Zusammenfassung wie in dieser Antwort. –

+0

Ich habe meinen Code geändert, um Ihre Lösung zu verwenden (fast, ich habe immer noch eine IsValid-Eigenschaft, die einen booleschen Wert enthält, und ich aktualisiere sie in meinem Event-Change-Element. – J4N

0

Für jetzt habe ich diese Methode auf meinem Modell hinzugefügt.

public Boolean IsModelValid() 
    { 
     Boolean isValid = true; 
     PropertyInfo[] properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); 

     foreach (PropertyInfo p in properties) 
     { 
      if (!p.CanWrite || !p.CanRead) 
      { 
       continue; 
      } 
      if (this[p.Name] != null) 
      { 
       isValid = false; 
      } 
     } 
     return isValid; 
    } 

ich das Objekt selbst auf dem Property Ereignisse, ich aktualisiere

public MyClassName() 
    { 
     PropertyChanged += CheckModelValidity; 
     CheckModelValidity(null, null); 
    } 

, wenn es ändern, ich nenne diese Methode, und wenn das Ergebnis anders ist

als mein eigentliches öffentliches Mitglied, gebunden:

private void CheckModelValidity(object sender, PropertyChangedEventArgs e) 
    { 
     bool isModelValid = IsModelValid(); 
     if(isModelValid!= IsValid) 
     { 
      IsValid = isModelValid; 
     } 
    } 

Und dann kann ich nur die IsValid-Eigenschaft binden.

Ich weiß nicht, ob es eine bessere Lösung gibt?

+5

Böse, mit Reflexion jedes Mal, wenn eine Eigenschaft geändert Ereignis auftritt .... –

+2

Wenn Sie diese Route hinuntergehen, initialisieren Sie die Liste der gültigen Eigenschaftsnamen im statischen Konstruktor, der sie in einem statischen Feld speichert. Dann hast du nur die Reflektion einmal vorkommen. –

+0

@BobVale Ja, darauf bin ich auch nicht stolz, aber ich ziehe das dem Risiko vor, dass jemand vergisst, einen Check zu machen. Schön, ich werde das in einer statischen Var initialisieren. – J4N