VB.NETで「ただのOK」に別れを告げよう!カスタムダイアログでデータをスマートに受け取る設計術
こんにちは。現場で「動けばいい」というコードを「美しく保守性の高いコード」へと昇華させることに情熱を燃やしているエンジニアです。
Windows Forms開発において、`Form.ShowDialog()` を使ったモーダルダイアログは避けて通れない道です。しかし、初心者の多くが陥る罠があります。それは、「DialogResult.OK かどうか」だけで判断し、肝心の中身を強引にグローバル変数などで受け渡してしまうことです。
今日は、そんな悪しき習慣から卒業し、「カスタムオブジェクト」を介してリッチなデータを安全かつスマートに呼び出し元へ渡す設計パターンを伝授します。
—
なぜ「DialogResult」だけでは不十分なのか?
標準の `DialogResult` は、あくまで「ユーザーがどのボタンを押したか」というステータスしか持ちません。
例えば、「顧客名」や「更新日時」などの複雑なデータを取得したいとき、呼び出し元のフォームが「OK」を受け取った後に、わざわざダイアログのコントロール(テキストボックス等)を直接見に行くようなコードを書いていませんか?
これは設計として非常に危険です。
- ダイアログ側のコントロール名が変わったら、呼び出し元も壊れる。
- ダイアログの内部構造を外部にさらけ出している(カプセル化の欠如)。
これらを解決するのが「データ保持専用クラス(DTO)」を使った受け渡し術です。
—
ステップ1:データを運ぶ「箱(クラス)」を作る
まずは、ダイアログから親フォームへ渡したい情報をまとめたクラスを定義します。
‘ ダイアログの結果を格納するクラス(DTO: Data Transfer Object)
Public Class UserInputResult
Public Property UserName As String
Public Property SelectedDate As DateTime
Public Property IsValidated As Boolean
End Class
—
ステップ2:ダイアログ側に「受け渡し口」を用意する
ダイアログフォームに、上記クラスを保持するためのプロパティを一つ追加します。これが「窓口」になります。
Public Class InputDialog
‘ 外から読み取り専用で結果を取得できるようにする
Public Property ResultData As UserInputResult
Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click
‘ 入力内容をオブジェクトに詰め込む
ResultData = New UserInputResult With {
.UserName = txtName.Text,
.SelectedDate = dtpDate.Value,
.IsValidated = True
}
‘ OKを返して閉じる
Me.DialogResult = DialogResult.OK
End Sub
End Class
—
ステップ3:呼び出し元で「結果」を受け取る
呼び出し元では、ダイアログを閉じた後にプロパティを確認するだけです。
Private Sub btnOpenDialog_Click(sender As Object, e As EventArgs) Handles btnOpenDialog.Click
Using dlg As New InputDialog()
‘ ダイアログを開く
If dlg.ShowDialog() = DialogResult.OK Then
‘ 結果オブジェクトから安全に取り出す
Dim data = dlg.ResultData
‘ これでダイアログのコントロールを意識せずに値が使える!
MessageBox.Show($”ようこそ {data.UserName} さん!”)
End If
End Using
End Sub
—
初心者が陥りやすい「落とし穴」を解説
1. `Using` ステートメントを忘れる
ダイアログはフォームという「重いリソース」です。`Using` を使うことで、使い終わった瞬間にメモリが確実に解放されるようになります。これを忘れると、アプリが長期間起動しているうちにメモリリークの原因となります。
2. ダイアログのコントロールを直接操作する
「`ParentForm.txtData.Text = “…”`」のように書いてはいけません。これは「密結合」と呼ばれ、後々コードの修正が困難になる原因です。今回紹介したように「オブジェクト」を介することで、ダイアログ側を修正しても呼び出し元が壊れない、強固なプログラムが作れます。
3. 初期化忘れ
`ResultData` プロパティが `Nothing` のまま参照されると例外(NullReferenceException)が発生します。コンストラクタで初期化するか、呼び出し側で必ずチェックする癖をつけましょう。
—
まとめ:ここをクリアすれば「中級者」への扉が開く!
今回紹介した「カスタムオブジェクトでのデータ受け渡し」は、大規模なシステム開発の現場では当たり前に行われている設計手法です。
- カプセル化: ダイアログの中身を隠し、必要なデータだけを渡す。
- 保守性: クラス構造を変えれば済むため、変更に強い。
- 可読性: コードが何をしているか一目でわかる。
マクロの記録や、コントロールを直接弄るプログラミングから一歩進んで、「オブジェクト」のやり取りを意識してみてください。これこそが、VB.NETを自在に操るための第一歩です。
皆さんの開発するアプリケーションが、より美しく、より堅牢なものになることを願っています。何か不明点があれば、いつでも聞いてくださいね!
