脱・力技のイベント制御!BindingSourceで実現する「マスター・ディテール」の極意
こんにちは。現場で泥臭いコードと格闘してきたあなたへ。
もしあなたが今、「ヘッダー(請求書)を選んだら、その下の明細が自動で切り替わる」という機能を、ボタン一つ一つにイベントを書いて制御しようとしているなら……今すぐその手を止めてください。
VB.NETの真骨頂は、「データの橋渡し(データバインディング)」をいかにスマートに設計するかにあります。今日は、Windows Formsにおける最強の武器『BindingSource』を使って、コードを極限まで削ぎ落とす設計手法を伝授します。
—
1. なぜ「力技の制御」が破滅を招くのか?
初心者が陥りやすいのが、「ヘッダーのグリッドの行選択イベントで明細を検索し、再読み込みする」という実装です。
これでは、データの整合性が崩れたり、UIとロジックが密結合しすぎてメンテナンス不能な「スパゲッティコード」が完成します。
BindingSourceは、単なるデータの仲介役ではありません。
UIとデータソースの間に立つ「調停者」です。これを使うことで、ヘッダーと明細の同期を「設定」だけで解決できるようになります。
—
2. 準備:データセットの親子関係を定義する
まず、`DataTable`同士に「リレーション(親子関係)」を持たせることがスタートラインです。
.net
‘ 例:請求書ヘッダー(dtHeader)と明細(dtDetail)の準備
Dim ds As New DataSet()
ds.Tables.Add(dtHeader)
ds.Tables.Add(dtDetail)
‘ 請求書ID(InvoiceID)をキーにして親子関係を定義
ds.Relations.Add(“HeaderToDetail”,
ds.Tables(“Header”).Columns(“InvoiceID”),
ds.Tables(“Detail”).Columns(“InvoiceID”))
このリレーションを定義するだけで、VB.NETのエンジンは「どのヘッダーにどの明細が紐づいているか」を理解します。
—
3. 実装の極意:BindingSourceを「二階建て」にする
ここが最大のポイントです。BindingSourceを2つ用意し、明細側のソースをヘッダーのBindingSourceに関連付けます。
.net
‘ ヘッダー用
Dim bsHeader As New BindingSource()
bsHeader.DataSource = ds.Tables(“Header”)
‘ 明細用(これが肝!)
Dim bsDetail As New BindingSource()
‘ データソースをヘッダーのBindingSourceに指定し、リレーション名を渡す
bsDetail.DataSource = bsHeader
bsDetail.DataMember = “HeaderToDetail”
‘ あとはフォームのコントロールにバインドするだけ
txtInvoiceNo.DataBindings.Add(“Text”, bsHeader, “InvoiceNo”)
dgvDetail.DataSource = bsDetail
これだけで完了です。
ヘッダーの行を切り替えると、`bsHeader`の`Position`が変わり、それに連動して`bsDetail`が自動的にフィルタリングされます。あなたはもう、明細を再検索するコードを一行も書く必要はありません。
—
4. 陥りやすい罠と解決策
Q. 「CurrentChanged」で何か処理をしたいときは?
「選択が変わった瞬間に合計金額を再計算したい」といったケースがあるでしょう。その場合は、`bsHeader`の`CurrentChanged`イベントを使います。
.net
Private Sub bsHeader_CurrentChanged(sender As Object, e As EventArgs) Handles bsHeader.CurrentChanged
‘ 現在のヘッダー行が確定した後のタイミングで動く
‘ ここで複雑な計算やログ出力を行うのが、VB.NETらしい設計です
Dim currentHeader As DataRowView = DirectCast(bsHeader.Current, DataRowView)
If currentHeader IsNot Nothing Then
CalculateTotal(currentHeader(“InvoiceID”))
End If
End Sub
Q. データが更新されないときは?
BindingSourceを使っていても、`DataTable`を直接触るとUIが追いつかないことがあります。そんな時は `BindingSource.EndEdit()` を呼んでください。これだけで、編集中の値がデータセットに確定され、即座に同期されます。
—
5. まとめ:エンジニアとして一段階上の視点へ
今回紹介した「BindingSourceによる連動」は、小規模なツールから業務基幹システムまで応用が効く、VB.NETにおける「型」のようなものです。
- イベントを書きすぎない: BindingSourceに任せられることは任せる。
- データ構造を正しく作る: DataSet/DataTableのリレーションを疎かにしない。
- UIを疎結合にする: コントロールとロジックの距離を離す。
ここをクリアすれば、あなたの書くコードは「動く」だけのものから、「保守できる」プロフェッショナルな資産へと変わります。
もし実装で詰まったら、思い出してください。「それはBindingSourceの紐付けで解決できないか?」と。
この問いかけができるようになった時、あなたはもう初心者ではありません。さあ、次の画面設計へ進みましょう!
