Silverlight 3でのデータの検証について

記事は適当に追記・訂正・削除されますので、あしからず。内容に誤り等あれば、指摘お願いします。

Silverlight 3での検証(Validation)についてのメモ。以下、断りがない限りSilverlightと書いたときは、Silverlight 3を指す。

要約

Silverlight 3では、Binding.ValidatesOnExceptionsプロパティを使用し、ターゲットからソースへ値を設定する際(プロパティのsetter)の例外を検証エラーとして扱うことで、検証を行う。

検証にもバインディングを活用

  • バインディングを活用する。
  • Binding.Modeプロパティは、もちろんTwoWay。
  • Binding.ValidatesOnDataErrorsプロパティはSilverlight 4からなので未使用。
  • Binding.ValidatesOnExceptionsプロパティをTrue。
  • Binding.ValidatesOnExceptionsをTrueに設定すると、バインディング時の例外が検証エラーとして扱われる。
  • Binding.ValidationRulesプロパティは、WPFにはあるがSilverlightにはない。
  • Binding.NotifyOnValidationErrorプロパティをTrue。
  • ValidatesOnExceptionsを設定するとValidationRulesにExceptionValidationRuleを指定した状態になるらしい。
  • ValidatesOnDataErrorsを設定するとValidationRulesにDataErrorValidationRuleを指定した状態になるらしい。
  • Binding.Converterプロパティは、ソースとターゲットとの間で型変換するために使用する。問題有。詳細は後述。
<!-- Converterプロパティは現状未設定 -->
<TextBox Text="{Binding Birthday, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}" />

バインディング時に例外を投げる(検証)

  • プロパティのsetで、検証を行い、例外をスローする(例外は検証エラーとして扱われる)。
  • 検証エラーはデフォルトでコントロールの枠を赤くすることで通知される(もちろん変更可能)。
  • データ注釈(検証属性)を、検証に利用できる。
  • データ注釈では、データクラスやそのメンバーに、検証規則や表示方法などの属性を適用する。
private DateTime _Birthday;

// 検証属性を付与。外部メッセージリソースを指定することなども可能。
[Required]
public DateTime Birthday
{
    get { return this._Birthday; }
    set
    {
        string propertyName = "Birthday";
        Validator.ValidateProperty(value,
            new ValidationContext(this, null, null) { MemberName = propertyName });
        this._Birthday = value;
        OnPropertyChanged(propertyName);
    }
}

IValueConverterによる型変換

  • (おさらい)Binding.Converterプロパティは、ソースとターゲットとの間で型変換するために使用する。
  • Binding.Converterプロパティには、IValueConverterインタフェースを実装したクラスを設定する。
<UserControl.Resources>
    <local:DateTimeConverter x:Key="dtc" />
</UserControl.Resources>
<!-- 中略 -->
<TextBox Text="{Binding Birthday, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True, Converter={StaticResource dtc}}" />
// IValueConverterの実装

プロパティのsetterで検証する限りConverterは機能しない

  • 型変換では例外をスローしてはいけない(例外は検証エラーとして扱われない)。
  • DependencyProperty.UnsetValueを返すと、プロパティのsetterは呼ばれない(=検証が動かない)。
  • Binding.ValidationRulesは、WPFにはあるがSilverlightにはない。
  • WPFではValidationRulesで検証された後にConverterでの変換が開始される。
  • Silverlightでは検証できないままにConverterでの変換が開始される。
  • 検証→変換→設定ではなく、変換→検証→設定になる。
  • バインディングを活用するので、バインディングが動かない場合には、検証をかけられない。
  • 例)必須入力のテキストボックスがあるとして、そこに一切フォーカスを当てずに送信するボタンを押す。
  • 送信ボタンなどで、すべてのプロパティの検証が必要になる。
  • プロパティ単位の検証はまだ良いが、オブジェクト単位(すべてのプロパティ)の検証は良くない。
  • オブジェクト単位の検証は、Validator.ValidateObject()やValidator.TryValidateObject()を使用できる。
  • オブジェクト単位の検証ができても、それが検証エラーとして扱われない。手動で検証エラー表示を制御する。
  • 各Bindingに対してUpdateSource?


http://msdn.microsoft.com/library/cc278072#data_validation

データ注釈(Data Annotations)
http://msdn.microsoft.com/library/dd901590

System.ComponentModel.DataAnnotations 名前空間
http://msdn.microsoft.com/library/system.componentmodel.dataannotations

Validatorクラス
http://msdn.microsoft.com/library/system.componentmodel.dataannotations.validator