スキマハコ

わすれがちなスキマな事を詰め込んでいます。ITの他に暮らしについても書いています。

BindingSourceと単純なコントロールをバインドする

 BindingSourceとしてTextBoxをはじめとするUI系コントロールとバインドした時に、入力値が誤っている場合にフォーカスが外れなくなる障害が発生した。その調査を行っていて気付いたこと、分かった事について以下にまとめる。*1

 バインドした時に期待されるのがBindingSourceとControlの同期である。ここでの同期とは以下の事を指す。

  1. Adapterを介して取得したデータ情報がBindingSourceに格納されることでバインドを設定した項目情報がControlに描画を含めて反映される
  2. ユーザがControlに入力した情報がプログラムを記述することなく、BindingSourceに反映される。

 同期の仕組は「変更通知」により実現している。BindingSourceとControlがそれぞれ変更を通知しあって値を設定・描画等を行っている。
 
 ControlからBindingSourceへの変更通知のとき、Controlの情報を「検査」する。
 「検査」結果がOKであればBindingSourceに格納します。NGの場合は処理をキャンセルする。
 以下にフローチャートを記述する。
 
 検査はバインドしているDBの項目に一致しているかどうかを検査する。
 例えば、日付型の項目とバインドしている(Control)テキストボックスに0000/00/00を入力する。すると、結果がfalse(DBに設定することが出来ない値)と判断され、処理がキャンセルされる。
 この処理を行っている時に発生するイベントをValidatingとValidatedという。
  

ValidatingとValidated

 このイベントはLeave→Validating →Validatedの順番で発生する。コントロールがフォーカスを失って(Leave)、ユーザの入力を検査し(Validating)、検査後にBindingSourceに値を反映する(Validated)。もし検査が誤った場合、Validatingは「フォーカスを失う」処理をキャンセルし、Validatedは発生しない。
 

対応策案

 ValidatingとValidatedのため、バインドしたコントロールはDB登録が不可能な値を設定した時にフォーカスが外れない、という障害が発生した。この症状に対応するには以下の方法が考えられる。

  • Control.CausesValidation プロパティをFalseにする

CausesValidationは前述したValidatingとValidatedを抑止するプロパティである。これをFalseにすると検査と検査後の設定処理が行われなくなるため、「誤った値が設定されたとき」にフォーカスが外れなくなることはなくなる。

  • 問題点

 ValidatingとValidatedはControlの値を検査し、BindingSoruceに設定する動作を行っていたため、これを抑止するとControlとBindingSoruceの同期がとれなくなってしまう。
 対応策として、バインドしているControlの値を直接BindingSoruceに設定する事が考えられるが、バインドの利点が無くなってしまう。

  1. Leaveイベント時に値を設定する。

 Leaveイベント時にDB項目として矛盾しない値を設定すると、この問題は発生しなくなる。

  • 問題点

 自動的に値が設定されてしまうので、入力ユーザが意図しない値が登録されてしまう可能性がある。
 そのため、以下の制御が考えられる。

  1. ユーザが分かりやすいように背景色を設定する(登録する・しないはユーザまかせ)
  2. 異常フラグ等を設定して、登録前に全項目をチェックし、その状態の時は登録を行わないようにする(システムで制御)

参考:
http://msdn.microsoft.com/ja-jp/library/xz45s2bh%28v=vs.85%29.aspx
http://msdn.microsoft.com/ja-jp/library/ms993236.aspx

*1:前に調べたものをdocにまとめてたんですけど、間違いとかありそうなので、こちらにアウトプット。
図で〜とか言ってるところは、wordで書いてたので省略。後から追記するかもしれません。