Powiązanie danych i reguły walidacji WPF - najlepsze rozwiązania

101

Mam bardzo prostą aplikację WPF, w której używam powiązania danych, aby umożliwić edycję niektórych niestandardowych obiektów CLR. Chcę teraz wprowadzić pewne sprawdzanie poprawności danych wejściowych, gdy użytkownik kliknie przycisk Zapisz. Jednak wszystkie książki WPF, które przeczytałem, nie poświęcają tak naprawdę miejsca temu zagadnieniu. Widzę, że możesz tworzyć niestandardowe reguły walidacji, ale zastanawiam się, czy nie byłoby to przesadą dla moich potrzeb.

Moje pytanie brzmi więc: czy jest gdzieś dobra przykładowa aplikacja lub artykuł, który demonstruje najlepsze praktyki sprawdzania poprawności danych wejściowych użytkownika w WPF?

Mark Heath
źródło

Odpowiedzi:

83

Myślę, że nowym preferowanym sposobem może być użycie IDataErrorInfo

Przeczytaj więcej tutaj

rudigrobler
źródło
3
Znalazłem również platformę Cinch ( cinch.codeplex.com ), która zawiera demo sprawdzania poprawności najlepszych praktyk w WPF + MVVM i używa IDataErrorInfo
Mark Heath
3
W .NET 4.5 można użyć INotifyErrorInfo, która umożliwia zwracanie obiektów zamiast samych ciągów.
Peter,
24

Z dokumentacji MS wzorców i praktyk :

Walidacja danych i raportowanie błędów

Twój model lub model widoku będzie często musiał przeprowadzić walidację danych i zasygnalizować wszelkie błędy walidacji danych do widoku, aby użytkownik mógł podjąć działania w celu ich poprawienia.

Silverlight i WPF zapewniają obsługę zarządzania błędami walidacji danych, które występują podczas zmiany poszczególnych właściwości, które są powiązane z kontrolkami w widoku. W przypadku pojedynczych właściwości, które są powiązane z danymi z kontrolką, model widoku lub model może sygnalizować błąd sprawdzania poprawności danych w programie ustawiającym właściwości, odrzucając przychodzącą złą wartość i zgłaszając wyjątek. Jeśli właściwość ValidatesOnExceptions w powiązaniu danych ma wartość true, aparat powiązań danych w WPF i Silverlight obsłuży wyjątek i wyświetli użytkownikowi wizualną wskazówkę, że wystąpił błąd sprawdzania poprawności danych.

Jednak w miarę możliwości należy unikać zgłaszania wyjątków z właściwościami w ten sposób. Alternatywnym podejściem jest zaimplementowanie interfejsów IDataErrorInfo lub INotifyDataErrorInfo w modelu widoku lub klasach modelu. Te interfejsy umożliwiają modelowi widoku lub modelowi sprawdzania poprawności danych dla jednej lub wielu wartości właściwości i zwracania komunikatu o błędzie do widoku, aby użytkownik mógł zostać powiadomiony o błędzie.

Dokumentacja wyjaśnia, jak zaimplementować IDataErrorInfo i INotifyDataErrorInfo.

Poklepać
źródło
3
Zacząłem się martwić, gdy zobaczyłem rzut jako zalecenie wyjątku. cieszę się, że następuje „rzucanie wyjątków z właściwościami w ten sposób, gdzie to możliwe”
kenwarner,
22
należy również zauważyć, że pewien muppet w Microsoft zdecydował się nie umieszczać INotifyDataErrorInfo w .net4, ale tylko w Silverlight. jego ból ..
aL3891
5
@ al3891- to zostanie posortowane w .NET 4.5- msdn.microsoft.com/en-us/library/ ...
RichardOD
@ aL3891 Czy istnieje alternatywa dla brakującego INotifyDataErrorInfo?
AgentKnopf
10

personaly, używam wyjątków do obsługi walidacji. wymaga następujących kroków:

  1. w wyrażeniu powiązania danych musisz dodać „ValidatesOnException = True”
  2. w obiekcie danych, z którym jesteś powiązany, musisz dodać procedurę obsługi DependencyPropertyChanged, w której sprawdzasz, czy nowa wartość spełnia twoje warunki - jeśli nie - przywracasz do obiektu starą wartość (jeśli musisz) i rzucasz wyjątek.
  3. w szablonie kontrolnym używanym do wyświetlania nieprawidłowej wartości w kontrolce można uzyskać dostęp do kolekcji błędów i wyświetlić komunikat o wyjątku.

sztuczka polega na tym, aby wiązać się tylko z obiektami, które pochodzą z DependencyObject. prosta implementacja INotifyPropertyChanged nie zadziała - we frameworku jest błąd, który uniemożliwia dostęp do kolekcji błędów.

Greg
źródło
3

Przeczytaj również ten artykuł . Podobno Microsoft wydał swoją bibliotekę Enterprise Library (v4.0) na podstawie swoich wzorców i praktyk, w których obejmują one temat walidacji, ale Bóg wie, dlaczego nie uwzględnili walidacji dla WPF, więc post na blogu, do którego cię kieruję, wyjaśnia, co autor zrobił, aby go dostosować. Mam nadzieję że to pomoże!

murki
źródło
2

Może Cię zainteresować przykładowa aplikacja BookLibrary platformy WPF Application Framework (WAF) . Pokazuje, jak używać walidacji w WPF i jak kontrolować przycisk Zapisz, gdy występują błędy walidacji.

jbe
źródło
0

Jeśli Twoja klasa biznesowa jest używana bezpośrednio przez interfejs użytkownika, lepiej jest użyć IDataErrorInfo, ponieważ zapewnia to logikę bliżej właściciela.

Jeśli klasa biznesowa jest klasą pośredniczącą utworzoną przez odwołanie do usługi WCF / XmlWeb, nie można / nie wolno używać IDataErrorInfo ani zgłaszać wyjątku do użytku z ExceptionValidationRule. Zamiast tego możesz:

  • Użyj niestandardowej reguły ValidationRule.
  • Zdefiniuj klasę częściową w projekcie interfejsu użytkownika WPF i implementuje IDataErrorInfo.
Alex Pollan
źródło
1
Wiem, że to stare, ale mam nadzieję, że Alex będzie w stanie odpowiedzieć. To jest wniosek, do którego również doszedłem, ale problem polega na tym, że musisz napisać jakąś walidację dla (na przykład) właściwości "Age", która nie może być większa niż 100 w ValidationRule, a następnie powtórzyć tę samą logikę w interfejsie IDataErrorInfo , co powiela logikę. Czy można to obejść?
JFTxJ
Gdzie duplikujesz logikę? w jakiejś weryfikacji serwera? Wydaje mi się, że po twoim komentarzu sprawdzasz poprawność za pomocą IDataErrorInfo w interfejsie użytkownika i powielasz walidację w obiekcie biznesowym, prawda? Jeśli tak, to poprawne jest sprawdzenie poprawności po obu stronach. Obiekty biznesowe nie mogą ufać interfejsowi użytkownika i muszą przeprowadzić własną weryfikację (choć wydaje się, że jest to duplikat)
Alex Pollan
Nie, powielenie logiki walidacji znajduje się w IDataErrorInfo iw niestandardowej regule walidacji ... Ponieważ niestandardowa reguła walidacji jest jedynym sposobem sprawdzenia danych PRZED ich faktyczną aktualizacją do obiektu związanego, ta walidacja (wiek musi być niższy następnie 100) musi zostać zdefiniowana w IDataErrorInfo, aby zwracała komunikat „dla każdego pola”, ale musi być również zaimplementowana w niestandardowej regule walidacji. Ma sens?
JFTxJ,