Integracja Fluent Validation z WPF – wersja async

Fluent Validation w WPF

W poprzednim wpisie pokazałem, jak użyć Fluent Validation w WPF. Wspomniałem, że tamta implementacja niestety nie nadaje się, gdy potrzebujemy walidować dane w sposób asynchroniczny – np. sprawdzić w usłudze, czy dane są unikalne. W tamtym wpisie pokazałem również użycie IDataErrorInfo, ponieważ jest on najczęściej wykorzystywany do realizacji walidacji. Dzisiaj natomiast opiszę nową wersję tego interfejsu, dodaną w .NET 4.5 – INotifyDataErrorInfo. Co fajne, nowy interfejs umożliwia realizację walidacji asynchronicznej, która jest dostępna w Fluent Validation.

W tym wpisie bazuję na przykładzie walidacji z wykorzystaniem IDataErrorInfo (dlatego odsyłam do przeczytania w pierwszej kolejności tamtego wpisu) i tutaj skupię się wyłącznie na zmianach, jakie zrobiłem w kodzie, aby wspierać asynchroniczną walidację.

Implementacja view modelu

W pierwszej kolejności usunąłem z ViewModel kod związany z IDataErrorInfo: metodę GetValidationError, właściwość Error oraz indekser.

Metoda SelfValidate zmieniła sygnaturę i teraz jest w wersji asynchronicznej (wraca Task<ValidationResult>):

Do ViewModel dodałem dwie pomocnicze właściwości, które będą wykorzystane w innych częściach kodu: IsValidating (czy trwa właśnie walidacja – aby wyświetlić później stosowną informację w widoku) oraz ValidationResult (w niej będzie zapisywany wynik ostatniej walidacji na potrzeby przekazania informacji o błędach do WPF):

Sam interfejs INotifyDataErrorInfo definiuje trzy rzeczy, które trzeba dodać do kodu: zdarzenie ErrorsChanged (za jego pomocą będziemy informować, że zmieniła się informacja o błędach dla właściwości), właściwość HasErrors (czy są błędy) oraz metoda GetErrors (zwraca informacje o błędach dla właściwości). Implementacja tych elementów może wyglądać tak:

Zmieniła się również sama metoda Validate. Przede wszystkim jest asynchroniczna, ustawia właściwość IsValidating oraz za pomocą zdarzenia ErrorsChanged (przy pomocą pomocniczej metody) aktualizuje informacje o błędach.

W przypadku implementacji z poprzedniego wpisu WPF sam automatycznie, po zmianie danych w kontrolce, korzystał z indeksera, w którym odpalana była metoda SelfValidate. W tym przypadku musimy zrobić to troszeczkę inaczej. Ponieważ sami musimy wywołać metodę Validate, najlepiej zrobić to w metodzie OnPropertyChanged, która w moich aplikacjach jest uruchamiana w każdym seterze właściwości, gdy nastąpiła jest zmiana. Jak widać w poniższym kodzie, na końcu metody sprawdzamy, czy nazwa właściwości jest OK (nie ma sensu wywoływać walidacji dla zmian niektórych właściwości, np. IsValid), i jeśli tak, to wywołujemy metodę Validate. Co istotne, jak widać w powyższym kodzie, metoda Validate informuje WPF tylko w sytuacji, gdy właściwość się nie waliduje. Musimy jeszcze poinformować WPF o tym, że właściwość znowu ma wartość poprawną – i robimy to właśnie w metodzie OnPropertyChanged:

Darmowy kurs Visual Studio

Pracując z setkami programistów, zauważyłem, że większość osób nie pracuje efektywnie w Visual Studio. W skrajnych przypadkach korzystali z kopiowania z wykorzystaniem menu Edit. Wiem, że to dziwne, ale naprawdę niektórzy tak pracują. Dlatego postanowiłem stworzyć kurs Visual Studio – aby pomóc koleżankom i kolegom w efektywniejszej pracy.

Przygotowałem 20 lekcji e-mail, w których pokażę Ci, w jaki sposób pracować efektywniej i szybciej w Visual Studio. Poznasz dodatki, bez których nie wyobrażam sobie pracy w tym IDE.

Po więcej informacji zapraszam na dedykowaną stronę kursu: Darmowy Kurs Visual Studio.

Quiz C#

Ostatnio przygotowałem również quiz C#, w którym możesz sprawdzić swoją wiedzę. Podejmiesz wyzwanie?

Implementacja walidatora oraz widok

Po stronie zmian w bazowym view modelu to już wszystko. W przykładzie zmienił się nieco również sam walidator dla przykładowego widoku. Dodana została dodatkowa reguła sprawdzająca, czy wpisany adres jest unikalny. W prawdziwej aplikacji w tym miejscu prawdopodobnie aplikacja wysłałaby żądanie do usługi, tutaj natomiast symulujemy to wywołaniem metody Task.Delay. Aby walidator wykonał tę walidację asynchronicznie, musimy skorzystać z metody MustAsync, jak to widać poniżej:

Ostatnią rzeczą, która trzeba jeszcze zmienić, jest definicja bindingu w samym widoku. Zamieniamy ValidatesOnDataErrors na ValidatesOnNotifyDataErrors:

Podsumowanie

Po tych wszystkich zmianach możemy się cieszyć asynchroniczną walidacją w aplikacji WPF z wykorzystaniem Fluent Validation. Dzięki temu rozwiązaniu możemy bez blokowania interfejsu użytkownika walidować dane po stronie serwera. Od jakiegoś czasu przestawiłem się w swoich aplikacjach z walidacji z wykorzystaniem IDataErrorInfo na INotifyDataErrorInfo, do czego również zachęcam i Ciebie, drogi Czytelniku. 🙂

Jak poprzednio, cały działający przykład znajduje się na githubie.

1 thought on “Integracja Fluent Validation z WPF – wersja async

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *