Walidacja

Walidacja jest to technika sprawdzająca, czy dany obiekt spełnia pewne założenia poprawności danych. W WPF-ie oraz Silverlighcie istnieją trzy sposoby walidacji obiektów:

  • walidacja poprzez rzucanie wyjątków,
  • walidacja z użyciem interfejsu IDataErrorInfo,
  • walidacja z użyciem interfejsu INotifyDataErrorInfo

1. Walidacja poprzez rzucanie wyjątków

Walidacja poprzez rzucanie wyjątków odbywa się w następujący sposób. W seterze danej właściwości dodajemy warunek sprawdzający czy wpisane dane są poprawne. Jeżeli nie to najzwyczajniej w świecie rzucamy wyjątek, w którym podajemy komunikat błędu. Przykładowy properties z walidacją może wyglądać w ten sposób:

W celu “wyłapania” tego wyjątku i pokazania odpowiedniego komunikatu,w bindingu musimy ustawić właściwość ValidatesOnExceptions na wartość true.

Taki sposób walidowania jest jednak rzadko stosowany i wielu programistów twierdzi, że rzucanie wyjątków powinno się odbywać tylko w przypadku nieprawidłowego działania aplikacji. Ponadto walidowane propertisy nie mogą być autopropertisami, co dodatkowo wydłuża czas tworzenia klas.

2. Walidacja z użyciem interfejsu IDataErrorInfo

W celu wyłapywania błędów w widoku, należy w bindingu ustawić ValidatesOnDataError = true

Przykładowa klasa implementująca interfejs IDataErrorInfo może wyglądać następująco:

Najważniejszą metodą w powyższej klasie jest indekser

to właśnie tutaj mogą zostać sprawdzone wszystkie właściwości danego obiektu – propertyName oznacza nazwę propertisu, który walidujemy. W przypadku, gdy wartość jakiejś właściwości jest nieprawidłowa, w pole result wpisujemy komunikat błędu. Komunikaty te “wyłapywane” są przez widok, a następnie wyświetlane w postaci komunikatów przy odpowiednich kontrolkach. Jeżeli wszystko jest OK zwracamy string.Empty.Walidacje przy pomocy interfejsu IDataErrorInfo idealnie nadają się do walidowania modelu.

3. Walidacja z użyciem interfejsu INotifyDataErrorInfo

Interfejs INotifyDataErrorInfo prezentuje się w następujący sposób:

  • bool HasErrors – określa czy dany obiekt zawiera błędy
  • event EventHandler ErrorsChanged– zdarzenie informujące o zmienie ilości błędów w obiekcie
  • IEnumerable GetErrors(string propertyName) – funkcja pobierająca kolekcję błędów dla danego propertisa

W celu “wyłapania” błędów przez widok należy w bindingu ustawić properties
NotifyOnValidationError = true

Jak już wcześniej wspomniano funkcja GetErrors(string propertyName) zwraca kolekcję błędów dla danej właściwości. Zatem do klasy, która będzie implementowała interfejs INotifyDataErrorInfo należy dodać kolekcję przechowującą obiekty typu ValidationResult. Przykładowa implementacja interfejsu może wyglądać w następujący sposób:

Funkcja Validate() najpierw czyści wszystkie poprzednie wyniki walidacji, a następnie przy pomocy klasy Validator oraz funkcji TryValidateObject waliduje wszystkie właściwości, które zostały oznaczone atrybutem dziedziczącym po klasie ValidationAttribute.Z kolei funkcja Validate(string propertyName) waliduje tylko konkretną właściwość.
Przykładowe walidowanie właściwości przy pomocy atrybutów może wyglądać w następujący sposób:

W celu stworzenia własnych regół walidacji, nie uwzględnionych w zapewnionych przez framework atrybutach należy stworzyć własną klasę dziedziczącą po klasie ValidationAttribute, a następnie przeciążyć metodę IsValid. Przykładowa klasa może wyglądać w następujący sposób:

Walidacja przy użyciu interfejsu INotifyDataErrorInfo idealnie nadaje się (wg mnie) do walidowaniu całych ViewModeli. Przy zamykaniu okna wystarczy wywołać funkcję Validate() z bazowego ViewModelu, a w przypadku gdy zwróci ona false zatrzymać zamykanie okna. Jako, że walidacja zostanie przeprowadzona na wszystkich wybranych przez nas propertisach, widok automatycznie się zaktualizuje i pokaże komunikaty błędów na odpowiednich kontrolkach okna.

Walidacja