2010-05-12 3 views
12

Wenn ich meinen Bildschirm zum ersten Mal dem Benutzer zeige, möchte ich lieber nicht, dass alle Validierungsnachrichten für erforderliche Felder angezeigt werden, bevor der Benutzer die Möglichkeit hatte, eines der Formularfelder auszufüllen. Ich habe die UpdateSourceTrigger auf meine Bindungen zu LostFocus gesetzt, aber die Fehler werden immer noch angezeigt, wenn das Steuerelement das erste Mal angezeigt wird. Gibt es eine Möglichkeit, dies zu umgehen?Wie kann ich WPF veranlassen, KEINE Validierungsfehler bei der ersten Anzeige der Kontrolle anzuzeigen?

XAML:

<TextBox Text="{Binding Path=OpeningOdometer, ValidatesOnDataErrors=True, UpdateSourceTrigger=LostFocus}" /> 

Ansichtsmodell:

[Required(ErrorMessage = "Please enter the opening odometer.")] 
[Range(0, Double.MaxValue, ErrorMessage = "Opening Odometer must be a positive number")]   
public string OpeningOdometer 
{ 
    get { return _openingOdometer; } 
    set 
    { 
     _openingOdometer = value; 
     NotifyOfPropertyChange(() => OpeningOdometer); 
    } 
} 

// Implementation of IDataErrorInfo 
public string this[string columnName] 
{ 
    get 
    { 
     // This uses the System.ComponentModel.DataAnnotations placed on 
     // the OpeningOdometer property to produce an error string 
     // if the value of the property is in violation of any of the 
     // annotated rules. 
     return _valHelper.GetErrorsForProperty(columnName, this); 
    } 
} 
+1

Haben Sie den besten Ansatz für diesen Brian ausgearbeitet? : \ – GONeale

Antwort

2

Sie können bessere Antworten bekommen, wenn Sie sich bemühen, einen Ausschnitt Ihrer entsprechenden Code/XAML zu veröffentlichen. Es würde es einfacher machen, viel von dem Rätselraten zu reproduzieren und zu eliminieren.

Versuchen Sie ValidatesOnTargetUpdated="False" auf Ihre Validierungsregeln und sehen, ob das hilft.

+2

Ich verwende ValidationRules nicht, ich implementiere IDataErrorInfo. Sollte mehr Detail in die Frage enthalten, Entschuldigung. –

8

Ich setze keine Validierungslogik in den Indexer. Dies ändert die Kontrolle über das Timing der Validierung auf die Ansicht. In Ihrem Schema löst die Ansicht eine Validierung aus, wenn sie nach den Fehlerinformationen der Eigenschaft fragt. Ich kenne nicht alle Umstände, in denen das passieren wird, und ich wette, Sie auch nicht.

Stattdessen legte ich die Validierungslogik einer Eigenschaft (genauer gesagt, den Aufruf der Validierungsfunktion) in ihren Setter. Ich speichere die Fehlermeldung in einem Wörterbuch, das für den Eigenschaftsnamen codiert ist, und lasse den Indexer die Fehlermeldung für die Eigenschaft anzeigen.

Standardmäßig ist die Fehlermeldung daher aktuell mit dem aktuellen Wert der Eigenschaft. Wenn die Ansicht eine Eigenschaft aktualisiert und ihre neuen Fehlerinformationen anfordert, erhält sie die richtige Antwort.

Aber Sie haben auch ziemlich feinkörnige Kontrolle darüber, was tatsächlich in diesem Wörterbuch ist. Wenn eine Eigenschaft in der Benutzeroberfläche als gültig angezeigt werden soll, löschen Sie einfach die Fehlermeldung im Wörterbuch (und erhöhen Sie PropertyChanged, damit die Benutzeroberfläche die neue Fehlermeldung erhält). Oder Sie können die Backing-Felder der Eigenschaften anstelle der Eigenschaften selbst festlegen, indem Sie die Validierung umgehen, wenn Sie das View-Modellobjekt erstellen.

2

nur um anzuzeigen, wie ich diese IDataErrorInfo Verwendung behandelt ...

ich einen Anruf auf ein neues Verfahren OnDataUpdated() in jedem Setter meiner Ansicht gebundene Eigenschaft, wie genannt gestellt:

private string username; 
    public string Username 
    { 
     get { return username; } 
     set 
     { 
      username = value; 
      OnDataUpdated(); 
     } 
    } 

    private string password; 
    public string Password 
    { 
     get { return password; } 
     set 
     { 
      password = value; 
      OnDataUpdated(); 
     } 
    } 

dann innerhalb OnDataUpdated() Zeichen ein privates Feld boolean als true Daten, die zum ersten Mal geändert (FormType wurde nur notwendig für mein Business Case):

private void OnDataUpdated() 
{ 
    dataChanged = true; 
    // .. Any other universal RaisePropertyChanged() events you may want to call to get your UI into sync. Eg. RaisePropertyChanged(() => CanConfirm); 
} 

Dann in meiner IDataErrorInfo Indexer-Eigenschaft mache ich Folgendes (Ich habe es aufgeteilt, so 'ValidForm()' kann manuell aufgerufen werden, um auch Formular-Validierung durchzuführen.

public string this[string columnName] 
     { 
      get 
      { 
       string result = null; 
       if (columnName == "Username") 
       { 
        // If other payment amounts have fully paid for balance, and cash amount has been entered, deny 
        if (!ValidForm(FormType.Step1, columnName)) 
         result = "Please enter the username field."; 
       } 
       else if (columnName == "Password") 
       { 
        if (!ValidForm(FormType.Step1, columnName)) 
         result = "Please enter the password field."; 
       } 
       return result; 
      } 
     } 

     /// <summary> 
     /// Test if valid form. 
     /// </summary> 
     /// <param name="formType">Specify which form we should validate.</param> 
     /// <param name="columnName">If ommitted, entire form will be validated.</param> 
     /// <returns></returns> 
     private bool ValidForm(FormType formType, string columnName = null) 
     { 
      // This field is used to denote when data has changed on the form. 
      // If data has changed, we know we can activate any form validation. 
      // We do not activate the form validation until after a user has typed 
      // something in at least. 
      if (!dataChanged) return true; 

      var errors = false; 
      if (formType == FormType.Step1 && ((string.IsNullOrEmpty(columnName) || columnName == "Username") && string.IsNullOrEmpty(Username))) 
       errors = true; 
      if (formType == FormType.Step1 && ((string.IsNullOrEmpty(columnName) || columnName == "Password") && string.IsNullOrEmpty(Password))) 
       errors = true; 
      return !errors; 
     } 

Funktioniert wunderbar. Jetzt habe ich nur noch Validierungsstile, nachdem ein Benutzer das Formular bearbeitet hat.

Wenn Sie einige zusätzliche Sahnehäubchen auf dem Kuchen wollen, können Sie in meinem RaisePropertyChanged(() => CanConfirm); im OnDataUpdated() Verfahren Stellung zu nehmen und binden, die zu Ihrem bestätigen Knopf IsEnabled={Binding CanConfirm} mit der zugehörigen Eigenschaft:

/// <summary> 
/// Can the user confirm step 1? 
/// </summary> 
public bool CanConfirm 
{ 
    get { return ValidForm(FormType.Step1); } 
} 

und Ihre Schaltfläche wird nur sein aktiviert, wenn Ihr Formular auch gültig ist. :)

Viel Spaß! und viel Glück mit dem Ungetüm, das WPF ist.

Verwandte Themen