はじめに
今回の記事は、前回までに加えて、応用的な内容を紹介します。データの入力検証、データの追加、ストアドプロシージャの実行など、Tips的なトピックを順番に紹介したいと思います。
また、この連載はサンプルシステムをベースに説明を行います。以下のサイトからサンプルコードや実行ファイルを入手して、確認しながら読み進めていただけると、より一層理解が深まると思います。
サンプルアプリケーションの公開サイト
Silverlightアプリケーションの入力検証機能
Silverlight 3で入力検証機能を考える場合、前回紹介したバインディングの機能を生かして、エンティティクラスの中で行う手法が典型的な形になるでしょう。バインディングされる各プロパティのSetterでチェック処理を行い、例外をスローするように実装します。このとき該当コントロールのValidatesOnExceptionsプロパティをTrueにすると、TwoWayバインディングのターゲット(つまりコントロール側)からソースオブジェクトを変更する時に発生した例外を、バインディングエンジンがキャッチしてくれます。
<TextBox Grid.Row="4" Grid.Column="1" Text="{Binding Quantity, Mode=TwoWay, ValidatesOnExceptions=True}" />
エンティティクラスを確認して、バインド対象であるQuantityを見てみましょう。SetterでExceptionを発生させていることがわかります。
private int quantity = 1; public int Quantity { get { return this.quantity; } set { if (this.quantity != value) { if (1 > value || value > 99) { throw new ArgumentException("数量は 1 - 99 の間で入力してください。"); } this.quantity = value; PropertyChanged(this, new PropertyChangedEventArgs("Quantity")); } } }
この実装により、実行時には次のように入力検証を行うことができるようになります。
また、Silverlight 4からは、あえてSetterでExceptionを発生させることなく、入力検証機能を実装できる以下2つのインターフェースを提供します。
- IDataErrorInfo
- INotifyDataErrorInfo
プロパティレベルでの妥当性検査のエラー通知
エンティティレベルでの妥当性検査のエラー通知
特にINotifyDataErrorInfoはSilverlight 4特有な実装になり、柔軟な使用が見込めるため、簡単に紹介しておきます。
例えば、姓と名の2つの入力枠があり、どちらか一方は入力されている必要があるというルールを作成したい場合を考えます。この場合、下記のエンティティクラスの一部のように実装を行います。
private string lastname; public string LastName { get { return lastname; } set { lastname = value; this.OnPropertyChanged("LastName"); this.OnErrorsChanged("LastName"); this.OnErrorsChanged("FirstName"); } } private string firstname; public string FirstName { get { return firstname; } set { firstname = value; this.OnPropertyChanged("FirstName"); this.OnErrorsChanged("FirstName"); this.OnErrorsChanged("LastName"); } } void OnErrorsChanged(string propertyName) { if (ErrorsChanged != null) ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName)); }
LastName(姓)FirstName(名)もSetterで2回OnErrorsChangedを実行しています。その結果、以下のGetErrorsが実行されます。
public System.Collections.IEnumerable GetErrors(string propertyName) { switch (propertyName) { case "LastName": case "FirstName": if (string.IsNullOrEmpty(lastname) && string.IsNullOrEmpty(firstname)) return new[] { "姓名のどちらかは入力してください"}; break; } return null; }
その結果、下図のように、2つのコントロールに対して同時に警告を表示(消去)できるようになります。
このようにエンティティ全体、あるいは複数のコントロールにまたがる入力検証が簡単に実装できるのがSilverlight 4の特徴の1つです。