2010-05-12 9 views
12

Kiedy po raz pierwszy wyświetlam ekran użytkownikowi, raczej nie powinienem wyświetlać wszystkich komunikatów sprawdzania poprawności wymaganych pól i takich, zanim użytkownik będzie miał szansę wypełnić dowolne pole formularza. Ustawiłem UpdateSourceTrigger na moich powiązaniach na LostFocus, ale błędy są nadal wyświetlane przy pierwszym wyświetleniu kontrolki. Czy istnieje sposób na obejście tego?W jaki sposób można uzyskać, aby WPF NIE wyświetlał błędów sprawdzania poprawności podczas początkowego wyświetlania kontrolki?

XAML:

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

ViewModel:

[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

Czy opracowałeś najlepsze podejście do tego Briana? : \ – GONeale

Odpowiedz

2

Można uzyskać lepsze odpowiedzi, jeśli dołożyć starań, aby opublikować fragment swojego właściwego kodu/XAML. Ułatwiłoby to odtworzenie i wyeliminowanie wielu zgadywanek.

Spróbuj ustawić ValidatesOnTargetUpdated="False" na swoich regułach sprawdzania poprawności i sprawdź, czy to pomaga.

+2

W rzeczywistości nie używam ValidationRules, implementuję IDataErrorInfo. Powinien zawierać więcej szczegółów w pytaniu, przeprosić. –

8

Nie umieszczam logiki walidacyjnej w indeksatorze. To zmienia kontrolę nad czasem sprawdzania poprawności w widoku. W twoim schemacie widok wyzwala sprawdzanie poprawności, gdy prosi o podanie informacji o błędzie właściwości. Nie znam wszystkich okoliczności, w których to się stanie i założę się, że ty też nie.

Zamiast tego umieszczam logikę walidacji właściwości (dokładniej, wywołanie funkcji sprawdzania poprawności) w jej ustawiaczu. Przechowuję komunikat o błędzie w słowniku oznaczonym nazwą właściwości i poproszę o sprawdzenie komunikatu o błędzie dla tej właściwości.

Domyślnie komunikat o błędzie jest aktualny z bieżącą wartością właściwości. Za każdym razem, gdy widok aktualizuje właściwość i żąda nowych informacji o błędzie, otrzyma właściwą odpowiedź.

Ale masz również dość precyzyjną kontrolę nad tym, co faktycznie znajduje się w słowniku. Jeśli chcesz, aby właściwość pojawiała się w interfejsie jako poprawna, po prostu wyczyść jej komunikat o błędzie w słowniku (i podnieś PropertyChanged, aby interfejs był w stanie uzyskać nowy komunikat o błędzie). Można również ustawić pola właściwości właściwości zamiast samych właściwości, pomijając sprawdzanie poprawności, podczas konstruowania obiektu modelu widoku.

2

Wystarczy wskazać, w jaki sposób obchodzić ten wykorzystując IDataErrorInfo ...

umieścić wezwanie do nowej metody zwanej OnDataUpdated() w każdej podstawce mojego widoku związana nieruchomości, takich jak:

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(); 
     } 
    } 

następnie wewnątrz OnDataUpdated() znakiem prywatna logiczna pole jako true wskazujący dane uległy zmianie po raz pierwszy (FormType było konieczne tylko dla mojego przypadku biznesowego):

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

Następnie w mojej właściwości indeksowania IDataErrorInfo robię co następuje (Rozdzielam ją, aby "ValidForm()" można było wywołać ręcznie, aby wykonać także sprawdzanie poprawności formularza.

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; 
     } 

Działa pięknie. Teraz mam tylko style sprawdzania poprawności pojawiające się po edycji przez użytkownika formularza.

Jeśli chcesz jakieś dodatkowe wisienką na torcie, można skomentować w moim RaisePropertyChanged(() => CanConfirm); w metodzie OnDataUpdated() i wiążą że do Confirm IsEnabled={Binding CanConfirm} ze skojarzoną nieruchomości:

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

a przycisk będzie tylko włączone, gdy twój formularz jest również ważny. :)

Ciesz się! i powodzenia z behemotem, który jest WPF.

Powiązane problemy