redwarrior’s diary

C#, ASP.NET, WEB, G*などの雑多な情報

BindingSourceを使用したTextBoxのデータ入力時におけるメリット

以前にWindowsフォームで作成したアプリケーションを修正する機会があり、BindingSourceについて理解が深まったので、記録を残しておく。

「TextBoxに入力した値をバリデーションして、正しい値ならば紐づいたDBのレコードを更新する」というよくある処理を実装する場合、BindingSourceを使用してBindingを行うと以下のようなケースで便利だった。

バリデーションでエラーになったら、変更前の値を復元したい

バリデーション処理は、Validatingイベントを使用すると思うが、パラメータから取得できる値、TextBoxフィールドの値も変更後の値になっている。
このままでは変更前の値を取得できないため、変更前の値を格納するフィールドを用意すると思うが、実はBindingSourceを使っていると変更前のフィールドがいらなくなる。

それは、BindingSourceから名前付きDataRowを取得でき、それが入力前の値を持っているからだ。名前付きDataRowの取得、入力前の値の取得は、以下のように行う。

var dataRowView = bindingSource.Current as DataRowView;
var row = dataRowView?.Row as 名前付きDataRowクラス名;
if (row != null)
{
    originalText = row[nameof(row.プロパティ名), DataRowVersion.Original].ToString();
}
//originalTextを使用して変更前の値を代入する処理など

レコードを更新する時に、値が変更されている場合のみ更新したい

バリデーション後の更新では、Validatedイベントを使用すると思うが、値が変更されていないのに毎回DBに接続して更新するのもムダなので、値が変わった場合のみ更新をしたい。
DBから取得した値と比較する方法があるが、対象が1つの画面からしか更新されない場合、取得のために毎回DBに接続すると、DB接続回数が増えてしまう。
上記の変更前の値を使用して、入力値と比較する事もできるが、実はBindingSourceを使っているともっと簡単な方法がある。

それは、BindingSourceから取得できる名前付きDataRowが、変更情報を持っているからだ。変更されたかどうかの判定は以下のように行う。

//rowは、名前付きDataRowクラス名のインスタンス。取得方法は上記と一緒。
if (row.RowState == DataRowState.Modified)
{
  //データが変更された場合に行う処理(DB更新処理など)
}

以上。