業務アプリの「使い勝手」を極める:SplitContainerの状態永続化で実現するプロのUI設計
業務アプリケーションにおいて、UIは単なる装飾ではない。それは「作業効率の直結変数」だ。
特にデータグリッドと詳細パネルを行き来するようなツールでは、`SplitContainer`を用いてユーザーが作業領域を動的に調整できるようにすることは必須要件と言える。
しかし、多くの開発者がここで「次回起動時にレイアウトが崩れる」「設定ファイルへの書き込みタイミングで例外を吐く」といった初歩的な罠に陥る。
今日は、Visual Basic .NETの深淵を知る者として、堅牢で保守性の高い「SplitContainer状態の永続化」というテーマを、実務レベルの知見で解説する。
—
1. なぜ「Designerのプロパティ値」だけでは不十分なのか
初心者は、`SplitContainer`の `SplitterDistance` をデザイナで固定しがちだ。しかし、これではユーザーの解像度やモニタ環境、業務内容による個別のニーズを一切無視していることになる。
プロの設計はこうだ。
1. レイアウトのメタデータ化: 画面の構成情報を設定ファイル(XMLまたはJSON)として分離する。
2. ライフサイクルの掌握: `FormClosing` イベントで保存し、`Shown` または `Load` イベントで復元する。
3. 境界値チェック: 不正な値(負の値や、フォームサイズを超えた値)が保存された際の「自己修復ロジック」を組み込む。
—
2. 堅牢な実装:プロダクションコードのテンプレート
以下は、`Settings.settings`(VB.NETの標準設定機能)を活用しつつ、読み込み時のバリデーションを組み込んだ実装例だ。
”’
”’
Public Class LayoutManager
‘ 保存用キー
Private Const SETTING_KEY As String = “MainSplitterDistance”
”’
”’
Public Shared Sub RestoreLayout(splitContainer As SplitContainer, form As Form)
‘ 設定値を取得(デフォルトは300)
Dim savedDistance As Integer = My.Settings.MainSplitterDistance
‘ バリデーション:画面幅が変更されている可能性があるため、
‘ 現在のパネルサイズを超えていないかチェックし、不正ならデフォルト値に戻す
If savedDistance > 0 AndAlso savedDistance < (splitContainer.Width - 50) Then
splitContainer.SplitterDistance = savedDistance
Else
splitContainer.SplitterDistance = 300
End If
End Sub
'''
”’
Public Shared Sub SaveLayout(splitContainer As SplitContainer)
‘ 現在の値を保存
My.Settings.MainSplitterDistance = splitContainer.SplitterDistance
My.Settings.Save()
End Sub
End Class
実装のポイント
- バリデーションの重要性: `savedDistance < (splitContainer.Width - 50)` というチェックを入れている。これがなければ、画面サイズを小さく変更した際、スプリッターが画面外に消えてしまい、ユーザーが操作不能になる事故が発生する。
- 疎結合: UIロジックと保存ロジックを分離しているため、将来的に設定保存先をデータベースやクラウドに変更したくなった際も、このクラスを差し替えるだけで済む。
—
3. 組み込みのベストプラクティス:Form側での呼び出し
このクラスを、メインフォームで以下のように呼び出す。
Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
‘ フォームの表示後に呼び出すことで、コントロールの初期化が完了した安全なタイミングを確保
LayoutManager.RestoreLayout(Me.SplitContainer1, Me)
End Sub
Private Sub MainForm_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
‘ 終了直前に現在の状態を確定させる
LayoutManager.SaveLayout(Me.SplitContainer1)
End Sub
—
4. プロの視点:さらなる高みへ
この実装だけでも十分実用レベルだが、さらに一歩進んだ設計を行うなら以下の点に留意せよ。
- 例外処理の徹底: `My.Settings.Save()` はIO処理であるため、書き込み権限がないディレクトリで実行された場合に例外が発生する。`Try-Catch` でラップし、ログを残すか、デフォルト値で運用を継続させるフォールバック処理を忘れてはならない。
- ユーザー体験(UX)への配慮: 頻繁にスプリッターを動かす場合、`SplitterMoved` イベントの度に保存を行うのはディスクI/Oの無駄だ。必ず `FormClosing` または `FormClosed` イベントで、「終了時に一度だけ」保存するようにせよ。
- 複数スプリッター対応: 画面が複雑になり、`SplitContainer` がネストする場合は、Dictionaryなどでキー管理を行い、保存する設定値を拡張できるようにしておくと良い。
結びに代えて
業務自動化ツールは、作って終わりではない。ユーザーが毎日ストレスなく操作し、業務を加速させるための「道具」だ。
画面のわずかな配置調整を、ユーザーの手を煩わせずに自動化する。こうした小さな気配りの積み重ねこそが、アーキテクトとしてのあなたの評価を決定づける。
さあ、コードを書き、現場の空気を変えてこい。幸運を祈る。
