【入門編】【中級者・実務】VB.NETによるWPFでの画面遷移フレームワーク設計:UserControl動的切替とパラメータ受渡し – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク
スポンサーリンク

Windowの乱立から卒業しよう:WPFにおける「一枚の舞台」を作る画面遷移設計術

こんにちは。開発の現場へようこそ。
Excel VBAや、かつてのWindows Formsで「新しい画面を開くときは `Form.Show()`」という書き方に慣れてきたあなた。もし今、WPF(Windows Presentation Foundation)に触れて、「あれ? 新しい画面を作ったのに、どうやって切り替えればいいんだっけ? 毎回新しいウィンドウを開くのは、なんだかスマートじゃない気がする……」と感じているとしたら、おめでとうございます。

あなたは今、「プロフェッショナルなアプリケーション設計」への入り口に立っています。

今日は、複数の画面を一つのウィンドウの中でスムーズに切り替え、かつ画面間で安全にデータをやり取りするための「モダンな画面遷移フレームワーク」の設計思想を伝授します。

1. なぜ「新しいウィンドウ」を何度も開いてはいけないのか?

まず、設計の前に「なぜそうするのか」という本質を理解しましょう。
初心者の多くは、マスター画面、入力画面、集計画面……と、機能が増えるたびに新しい `Window` オブジェクトを生成してしまいます。しかし、これには大きなデメリットがあります。

1. ユーザー体験(UX)の低下: タスクバーがウィンドウだらけになり、ユーザーが「今どの作業をしているか」を見失います。
2. リソースの浪費: ウィンドウ(Window)はOSレベルで重いリソースです。大量に開けばメモリを圧迫します。
3. データ管理の複雑化: 複数のウィンドウがバラバラに存在すると、「どのウィンドウが最新のデータを持っているのか?」という管理が地獄になります。

そこで採用するのが、「メインウィンドウという『舞台』を用意し、その上で『UserControl(演者)』を入れ替える」という設計パターンです。

2. 核心となるアーキテクチャ:Container & View パターン

この設計では、役割を明確に分離します。

  • MainWindow (Container): 常に表示されている外枠。画面を入れ替えるための「土台(ContentControl)」を持ちます。
  • UserControl (View): 個別の業務画面(一覧画面、詳細画面など)。これらは「部品」として作られます。

【図解イメージ】

[ MainWindow (舞台) ]
|-- [ ContentControl (舞台の中央) ] <-- ここを動的に書き換える!
|-- [ UserControl A (一覧画面) ] ← 切り替え前
|-- [ UserControl B (編集画面) ] ← 切り替え後

3. 実践:動的切り替えとパラメータ受渡し

それでは、実際に「顧客一覧画面」から「顧客編集画面」へ、顧客IDを渡しながら遷移するコードを書いていきましょう。

ステップ1:データの受け渡しを共通化する「規約(Interface)」を作る

ここがプロの技です。画面間で直接やり取りしようとすると、コードが複雑に絡み合います(密結合といいます)。
「データを受け取れる部品である」という共通のルール(Interface)を定義しましょう。

''' <summary>
''' 画面遷移時にパラメータを受け取るためのインターフェース
''' </summary>
Public Interface IParameterReceiver
    ''' <summary>
    ''' 画面にデータを渡すメソッド
    ''' </summary>
    ''' <param name="parameter">渡したいデータ(IDやオブジェクトなど)</param>
    Sub ReceiveParameter(parameter As Object)
End Interface

ステップ2:編集画面(UserControl)の実装

次に、データを受け取る側の画面を作ります。

CustomerEditView.xaml (UI部分は省略。テキストボックスなどがある想定)

CustomerEditView.xaml.vb

Public Class CustomerEditView
    ' IParameterReceiverを継承することで、パラメータを受け取れる能力を持たせる
    Implements IParameterReceiver

    Private _customerId As Integer

    ' インターフェースの実装
    Public Sub ImplementInterfaces() Implements IParameterReceiver.ReceiveParameter
        ' 渡されたオブジェクトを適切な型にキャストして受け取る
        If TypeOf parameter Is Integer Then
            _customerId = DirectCast(parameter, Integer)
            ' ここで、受け取ったIDを元にデータベースからデータを読み込む処理などを書く
            MessageBox.Show($"顧客ID: {_customerId} の編集モードを開始します。")
        End If
    End Sub
End Class

ステップ3:メインウィンドウによる制御

最後に、司令塔となる `MainWindow` を実装します。

MainWindow.xaml

<Window x:Class="MainWindow" ...>
    <DockPanel>
        <!-- 画面切り替え用のコンテナ -->
        <ContentControl x:Name="MainContentArea" DockPanel.Dock="Top" />
        
        <!-- 操作用ボタン(デモ用) -->
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom">
            <Button Content="一覧へ" Click="BtnShowList_Click" Margin="5"/>
            <Button Content="編集へ(ID:101)" Click="BtnShowEdit_Click" Margin="5"/>
        </StackPanel>
    </DockPanel>
</Window>

MainWindow.xaml.vb

Public Class MainWindow
    
    ''' <summary>
    ''' 画面を切り替える共通メソッド
    ''' </summary>
    ''' <param name="newView">表示したいUserControl</param>
    ''' <param name="param">渡したいパラメータ(任意)</param>
    Private Sub NavigateTo(newView As UserControl, Optional param As Object = Nothing)
        ' 1. パラメータがある場合、受け取り口(Interface)を持っているか確認して渡す
        If param IsNot Nothing AndAlso TypeOf newView Is IParameterReceiver Then
            DirectCast(newView, IParameterReceiver).ReceiveParameter(param)
        End If

        ' 2. コンテナの中身を新しい画面に入れ替える
        MainContentArea.Content = newView
    End Sub

    ' 一覧画面を表示
    Private Sub BtnShowList_Click(sender As Object, e As RoutedEventArgs) Handles BtnShowList.Click
        Dim listView As New CustomerListView() ' UserControlを生成
        NavigateTo(listView)
    End Sub

    ' 編集画面を表示(パラメータを渡す)
    Private Sub BtnShowEdit_Click(sender As Object, e As RoutedEventArgs) Handles BtnShowEdit.Click
        Dim editView As New CustomerEditView() ' UserControlを生成
        NavigateTo(editView, 101) ' ID:101を渡して遷移
    End Sub

End Class

4. 伝説のアーキテクトからの「極限の知見」

ここまで実装できれば、あなたは中級者の仲間入りです。しかし、現場で「動かない」「重い」「メモリが足りない」と騒がれるエンジニアにならないために、以下の2点を魂に刻んでおいてください。

① オブジェクトのライフサイクルを意識せよ

`NavigateTo` メソッドで `new UserControl()` を実行するたびに、新しいインスタンスがメモリ上に作られます。
もし、頻繁に画面を行ったり来たりする設計なら、毎回 `New` するのではなく、「画面インスタンスをキャッシュ(保持)しておく」ことを検討してください。
逆に、画面を離れる時にメモリを解放したい場合は、`Unloaded` イベントを利用して、重いリソース(画像やデータベース接続)を明示的に破棄する習慣をつけましょう。

② 「型」へのこだわりがバグを防ぐ

上記のコードでは `DirectCast(parameter, Integer)` としていますが、もし間違えて文字列を渡すとプログラムはクラッシュします。
実務では、`TryCast` を使って型チェックを厳密に行うか、あるいは `Object` ではなく、専用の 「DTO(Data Transfer Object:データ転送用クラス)」 を定義して渡すのが、最も安全で美しい設計です。

まとめ:ここをクリアすれば、VB.NETの基本はバッチリです

今回のポイントを振り返りましょう。

1. Windowを増やすのではなく、UserControlを入れ替える。
2. Interface (`IParameterReceiver`) を使って、画面間の結合度を下げる。
3. `ContentControl` を舞台として使い、`NavigateTo` メソッドで一括管理する。

このパターンをマスターすれば、どんなに複雑な業務アプリケーションでも、整理整頓された美しい構造で構築できるようになります。

最初は難しく感じるかもしれません。でも、一度この「型」を身につければ、あなたのコードは劇的に読みやすく、メンテナンスしやすくなるはずです。一歩ずつ、確実に進んでいきましょう。応援していますよ!

タイトルとURLをコピーしました