SourceChord

C#とXAML好きなプログラマの備忘録。最近はWPF系の話題が中心です。

WPFでの入力値検証・まとめ

今まで何回かに分けて書いてきたWPFのバリデーション関係ネタについて、自分でもわりと見返すので、この入力値検証関連の記事をまとめておきます。

あと、各種バリデーション方法のサンプルコード一式を、以下のリポジトリに上げておきました。

色々書いたブログの記事とは微妙にリンクしていないサンプルですが・・・
まぁ、この手のバリデーション処理を実装するときには、少しは役に立つのでは、、、と思います。

サンプルの説明

  • Example1_WithException・・・例外を使った方法
  • Example2_ValidationRule・・・ValidationRuleを使った方法
  • Example2_1_ErrorTemplate・・・ErrorTemplateでエラー時の表示内容をカスタマイズ
  • Example3_IDataErrorInfo・・・IDataErrorInfoを使った方法
  • Example_INotifyDataErrorInfoフォルダ
    • Example4_INotifyDataErrorInfo・・・INotifyDataErrorInfoの基礎
    • Example5_DataAnnotations・・・・DataAnnotationsを使って、属性でバリデーション内容を指定
    • Example6_CustomValidation・・・・独自バリデーション条件の指定方法
    • Example7_MultiplePropValidation・・・複数のプロパティが絡むバリデーション
    • Example8_Localize・・・・・・・・エラー時の表示メッセージのローカライズ

関連リンク

WPFでの入力値検証 - SourceChord
WPFでの入力値検証・その2 ~INotifyDataErrorInfoを使ってみる~ - SourceChord
WPFでの入力値検証・その3 ~DataAnnotationsを使う~ - SourceChord
WPFでの入力値検証・その4 ~ErrorTemplateで検証結果の表示をカスタマイズ~ - SourceChord
WPFでの入力値検証・その5 ~INotifyDataErrorInfo実装のベースクラスを作成~ - SourceChord
WPFでの入力値検証・その6 ~複数のエラー表示への対応~ - SourceChord
WPFでの入力値検証・その7 ~独自の検証ロジックを作成する~ - SourceChord
WPFでの入力値検証・その8 ~複数のプロパティが絡むバリデーションを作成する~ - SourceChord
WPFでの入力値検証・その9 ~エラー表示のローカライズ~ - SourceChord

あと、関連してPrismのErrosContainerについて↓
Prism.Mvvmを使ってみる・その2 ~ErrorsContainerの使い方~ - SourceChord

各種バリデーション方法の使い分け

色々な方法を書いたけど、WPFでバリデーションをする場合は、基本的に以下2択のどっちかになるのでは、、、と思います。

  • ValidationRuleを使って、View側でバリデーション
  • INotifyDataErrorInfoを使って、VM側でバリデーション

ValidationRuleとINotifyDataErrorInfoの使い分け

ValidationRuleとINotifyDataErrorInfoの動作は、以下のような違いがあります。
それぞれ、適材適所で使っていくのがいいのかな、と思います。

自分は基本的にはINotifyDataErrorInfoを使うかなぁ、、って印象。

ValidationRuleの動作

ValidationRuleを使う場合は、現在UI上に入力されている値がVMに反映されるとは限りません。
⇒バリデーションした結果、値が有効だった場合だけ、バインドしているVMのプロパティに反映されます。

完全にView側で閉じたバリデーションをしておき、VMには常に有効な値しか入らない、という動作にしたい場合に向いています。

ValidationRuleを使った方法は、VM側では処理を行わずにView側でデータを加工するようなイメージです。
ちょうどValueConverterと似たような立ち位置でしょうか。

INotifyDataErrorInfoの動作

一方、INotifyDataErrorInfoを使った場合は、UIからバインドした値がバリデーションで無効な値、と判断される場合もその値がVM側プロパティにセットされます。(IDataErrorInfoも同様)
そのため、UIに入力された値をバリデーション処理で判定した結果、エラーが起きているかどうかもVM側からチェックできるようになります。

バリデーション処理自体をVM単体テストとして行いたいような場合には、こちらの方が向いているかと思います。

また、複数のプロパティが絡むような複雑なバリデーションも、こちらの方法の方が向くと思います。