Wymuszenie walidacji kontrolek w WPF

Windows Presentation Foundation posiada nowy model walidacji kontrolek. Każdej kontrolce podlegającej walidacji przypisujemy zestaw reguł walidacyjnych, np:

<TextBox  Height="23" Margin="120,6,177,0"  VerticalAlignment="Top" >
    <Binding Path="FirstName" Mode="TwoWay">
        <Binding.ValidationRules>
            <DataErrorValidationRule></DataErrorValidationRule>
        </Binding.ValidationRules>
    </Binding>
</TextBox>

Powyższa reguła mówi, że wykorzystywany obiekt biznesowy wspiera interfejs IDataErrorInfo:

public partial class Person : IDataErrorInfo
{
   private Dictionary<string, string> m_ValidationErrors = new Dictionary<string, string>();
   public Invoice()
   {       
   }
   private void AddError(string columnName, string msg)
   {
       if (!m_ValidationErrors.ContainsKey(columnName))
       {
           m_ValidationErrors.Add(columnName, msg);
       }
   }
   private void RemoveError(string columnName)
   {
       if (m_ValidationErrors.ContainsKey(columnName))
       {
           m_ValidationErrors.Remove(columnName);
       }
   }
   partial void OnFirstNameChanged()
   {
       if (string.IsNullOrEmpty(ReceiverName))
       {
           AddError("FirstName", "Musisz podac imie");
       }
       else
           RemoveError("FirstName");
   }
   
   #region IDataErrorInfo Members

   public string Error
   {
       get
       {
           if (m_ValidationErrors.Count > 0)
           {
               return m_ValidationErrors.ElementAt(0).Value;
           }
           else return null;
       }
   }
   public string this[string columnName]
   {
       get
       {
           if (m_ValidationErrors.ContainsKey(columnName))
           {
               return m_ValidationErrors[columnName];
           }
           else return null;
       }
   }
   #endregion
}

W przykładzie wykorzystałem obiekt Entity Framework. Implementacje wymusza nam interfejs więc myślę, że kod nie wymaga dodatkowego komentarza(jeśli macie jakieś pytania to proszę zadawać je np. w komentarzach).

Inna regułą, która spełnia się gdy zostanie wyjątek wyrzucony podczas próby zmiany właściwości jest ExceptionValidationRule. Ponadto, istnieje możliwość definiowania własnych reguł. Gdy któraś kontrolka nie przejdzie walidacji zostaje domyślnie podświetlona na czerwono:

image

Walidacja zostanie jednak wywoływana pierwszy raz w momencie gdy kontrolka straci focus bądź gdy zostanie zmieniona w niej wartość(zależy to od ustawień bindingu). Co jednak w przypadku gdy chcemy aby przy starcie okna błędnie wypełnione pola(w tym przykładzie puste) zostały zaznaczone na czerwono?

Rozwiązanie jest proste: Wystarczy obsłużyć zdarzenie Windows Loaded oraz wykonać poniższy kod:

m_FirstName.GetBindingExpression(TextBox.TextProperty).UpdateSource();

Po wykonaniu kodu, wszystkie puste pola(czyli te, które nie przeszły walidacji) będą podświetlone i tym samym użytkownik będzie wiedział co należy wypełnić.

One thought on “Wymuszenie walidacji kontrolek w WPF”

  1. Wywaliło dwa błędy w VS2010:
    1. Error 1 The name ‘ReceiverName’ does not exist in the current context D:\Projects\USD\USD\mainwindow.xaml.cs 419 33 USD (dotyczy: string.IsNullOrEmpty(ReceiverName))

    2. Error 1 Method must have a return type D:\Projects\USD\USD\mainwindow.xaml.cs 400 11 USD (dotyczy public Invoice())

Leave a Reply

Your email address will not be published.