C# WinFormsダッシュボードフォームの構築
C# App From Start to Finishシリーズのレッスン21では、Tim CoreyがWinFormsアプリケーションでトーナメントダッシュボードフォームの接続に焦点を当てます。 このフォームはアプリケーションのスタートアップ画面として機能し、既存のトーナメントを読み込むか新しいものを作成するためのユーザーのエントリポイントとなります。 WinFormsダッシュボードは、ユーザーの操作がコードで処理される特定のイベントを引き起こすWindows Formsのイベント駆動型機能を活用するプログラムです。
ティムは、このレッスンが複雑なUI作業についてではなく、データ、モデル、ストアドプロシージャ、およびフォームをクリーンかつ一貫した方法で結びつけることについてであると説明します。 注: WinForms は特に、在庫管理、CRMシステム、経理ツールなどの社内業務ソフトウェアに適しています。 WinFormsダッシュボードが実際のアプリケーションでどのように機能するかを真に理解するために、ティムはトーナメントの読み込み、モデルのデータ注入、データベース接続の処理、およびUIコントロールの配線をステップバイステップで説明します。
この記事では、ティムのビデオ説明に沿って、ダッシュボードフォームをセクションごとに詳しく見ていきます。参照しやすいようにタイムスタンプも含まれています。 WinFormsアプリケーションは一般的に軽量で優れたパフォーマンスを提供するため、古いまたは性能が低いハードウェアに最適です。
ダッシュボードフォームの紹介
最初に、ティムはレッスン21を紹介し、目的を説明します。それは、アプリケーションが起動したときに最初に表示される"トーナメントダッシュボードフォーム"を連動させることです。
ティムは、このフォームが意図的にシンプルであることを指摘しています。 いくつかのことだけを行います:
既存のトーナメントのリストを読み込みます
ユーザーがトーナメントを選択して読み込むことができます
ユーザーが新しいトーナメントを作成できるようにします
視聴者に対し、これは長くて過度に複雑なレッスンではないことを安心させますが、システムの多くの重要な部分に触れる予定です。
ダッシュボードフォームの役割
ティムは、ダッシュボードフォームには二つの主要な責任があることを説明します。
既存のトーナメントをドロップダウンにロードする
- ユーザーの操作に基づいて他のフォームを開く
トーナメントが既に存在する場合、ユーザーはそれを選択し、"トーナメントの読み込み"をクリックすることができます(後で接続されます)。 ユーザーが新しいトーナメントを作成したい場合、"トーナメント作成"をクリックすると、既にプロジェクト内に存在するフォームが開きます。
現時点で、ティムはトーナメントを読み込むボタンがまだ接続されておらず、後のレッスンで扱われることを明らかにします。
ドロップダウン用トーナメントリストの作成
C#プロジェクトテンプレートを選択すると、Visual Studioはユーザーインターフェイスを設計するためのフォームを開きます。
ティムはフォームのコードビハインドに切り替え、ドロップダウンがバックリストを必要とすることを説明します。フォームがデザイナーに表示され、UIのカスタマイズができるようになっていることに注目してください。 ドロップダウンはトーナメントを表示することを意図しているため、バックリストはList< TournamentModel>である必要があります。
彼はトーナメントというプライベートリストを作成し、新しいリストを手動で作成するのではなく、データソースがSQLであるかテキストファイルであるかを抽象化するGlobalConfig接続からデータを取得するべきだと説明します。
ティムはその後、GetTournament_Allという名前のメソッドを呼び出そうとしますが、それがまだ存在しないことに気づき、このメソッドをデータアクセス層に追加する必要があると説明します。
データレイヤーにGetTournament_Allを追加する
TimはSQL Connectorに移動し、欠けていたGetTournament_Allメソッドを実装します。 彼はこのメソッドがTournamentModelオブジェクトのリストを返すことを説明します。
彼はプロジェクトの他の場所で使用されている既存のパターンをコピーして、トーナメント用に適応させます。 主な違いは、このメソッドが次の名前のストアドプロシージャを呼び出すことです:
spTournaments_GetAllティムは、このストアドプロシージャが基本的なトーナメントデータのみを取得することを説明します。
ID
トーナメント名
- エントリーフィー
アクティブステータス
彼は、TournamentModelにはもっと多くのプロパティが含まれているが、これは最初のステップに過ぎないと述べています。
部分モデルハイドレーションの理解
ティムは重要な概念、部分的ハイドレーションについて説明するために一旦止まります。
トーナメントモデルにはチーム、賞品、ラウンドが含まれていますが、これらのプロパティはまだ埋められていません。 この段階では:
チームが空です
賞品がありません
ラウンドは空です
この時点では、基本的なトーナメントのプロパティのみが設定されており、チーム、賞金、ラウンドなどの関連エンティティは次回のロードまで空のままであると予想されます。
ティムはこれが意図的であり、関連するエンティティは基本のトーナメント記録がロードされた後に、必ず入力される必要があると強調しています。
各トーナメントの賞品を設定
Timは、データベースから返されるすべてのトーナメントを反復処理するforeachループを紹介します。
賞品について、彼はプロセスが簡単であると説明しています:
トーナメントIDによって賞品を取得するストアドプロシージャを呼び出します
- 結果をT.Prizesに割り当てます
彼はストアドプロシージャspPrizes_GetByTournamentを参照し、それが指定されたトーナメントに関連するすべての賞を返すと説明しています。
このパターン、つまり基礎データをロードしてからIDで子データをロードするという流れは、アプリケーション全体で繰り返されるものとしてTimが強調しています。
チームとチームメンバーの読み込み
次に、ティムは入力されたチームに進みます。
彼は、チームの読み込みが2段階のプロセスであることを説明します。
トーナメントに関連するチームを読み込む
- 各チームについて、チームメンバーを読み込みます
彼は、現在のトーナメントに関連するチームのみを取得するために、spTeams_GetByTournamentというストアドプロシージャを使用します。
その後、チームごとに、Timは既存のメソッドを再利用してチームIDでチームメンバーを読み込みます。 彼は、これはシリーズの前に既に書かれたコードとほとんど同じであり、トーナメントに特化したデータに適応しただけであることを指摘しています。
ラウンドの複雑さの紹介
Timは、ラウンドがトーナメントモデルの中で最も複雑な部分であると説明しています。
ラウンドは次のように保存されます:
List<List<MatchupModel>>それらを埋めるために、Timは行う必要があります。
トーナメントのすべての対戦を読み込む
各対戦の対戦エントリーをロードします
親のマッチアップや勝者のような関係を解決します
彼はストアドプロシージャを確認することから始めます。
- spMatchups_GetByTournament
spMatchupEntries_GetByMatchup
勝者IDとネストモデルの取り扱い
Tim はデータベースを扱う際の一般的な問題を指摘します: SQLはIDを返しますが、アプリケーションはオブジェクトを期待しています。
WinnerプロパティはTeamModelですが、データベースはWinnerIdしか返しません。 Timは、ネストされたオブジェクトを直接SQLからハイドレートできないと説明しています。
これを解決するために、彼はモデルに一時的なWinnerIdプロパティを追加します。これはデータの読み込み時にのみ使用されます。 すべてのチームがロードされたら、彼はIDを使用して正しいTeamModelをWinnerプロパティに割り当てます。
対戦エントリーと親対戦の入力
各対戦ごとに、Tim:
対戦IDで対戦エントリを読み込みます
有効なチームIDをチェックします
すべてのチームのキャッシュされたリストを使用して関係を解決します。
彼は、値が存在しないときにIDがデフォルトで0になる理由と、0より大きいかを確認することが重要である理由を説明します。
ティムは、対戦がすでにロードされた対戦を参照し、対戦がラウンドごとに順序付けされていることを利用して、親の対戦をどのように解決するかも説明しています。
ラウンド構造の構築
すべての対戦が完全に埋まると、ティムがラウンドの構築方法を説明します。
彼は紹介します。
currentRound変数
- 現在の行のリスト
彼が対戦をループする際に:
ラウンド番号が変更された場合、前回のラウンドがT.Roundsに追加されます。
新しいラウンドリストが作成されました。
マッチアップがそれに応じてグループ化されています
ティムは完全な例を通じて論理が明確であることを確認し、ループを分離することでコードが理解しやすくなることを強調します。
ダッシュボードドロップダウンの配線
Visual Studioのツールボックスからドラッグすることで、ラベル、テキストボックス、ドロップダウンなどの一般的なコントロールをフォームに追加することができます。
ダッシュボードフォームに戻り、TimはWireUpLists()メソッドを作成します。
彼は割り当てます:
大会リストへのDataSource
- DisplayMember to TournamentName
ラベルはしばしばドロップダウンの目的を説明するために使用され、一方テキストボックスはフォームでユーザー入力に使用できます。 ユーザーの操作を処理するために、デザイナーでボタンをダブルクリックすると、Form1.csファイルにClickイベントハンドラーが自動的に生成されます。
彼は、これがドロップダウンにオブジェクト参照ではなく人間が読みやすい名前を表示させる理由だと説明します。
SQL とテキストファイル接続のテスト
Timは両方のデータソースを使用してアプリケーションを実行します。
テキストファイル接続はすぐに動作します
SQL接続がエラーをスローします
Visual Studioでスタートボタンを選択するか、F5を押してアプリケーションを実行できます。
彼はエラーメッセージを確認し、このバグが欠けているパラメーターによって引き起こされたことを特定し、複数のデータソースを統合する際にはこのようなバグがよく発生することを指摘します。 このバグは、トーナメントIDを正しくストアドプロシージャに渡すことで修正されました。
両方の賞品とチームを修正した後、ティムは両方のデータソースが正しく動作することを確認します。 バグの特定と修正は、特に複数のデータソースを統合する際には、開発プロセスの通常の一部です。
トーナメント作成ボタンの配線
最後に、TimはCreate Tournamentボタンのイベント、特にClickイベントを処理することで接続します。
彼は、ボタンのイベント処理コードはコードビハインドファイル(Form1.cs)に書かれており、Form1.Designer.csファイルには書かれていないと説明しています。Form1.Designer.csファイルはWindows FormsのUIコードを自動的に生成するもので、手動で編集するべきではありません。
ボタンは単純に:
トーナメント作成フォームの新しいインスタンスを作成します。
- Show()を呼び出します
彼は、トーナメントを作成した後にユーザーがどこに行くべきかに関するデザインの決定について話し、トーナメントビューアに直接移動することが最も理にかなっている理由を説明します。
結論と次のステップ
ティムはこれまでの作業をまとめて締めくくります:
ダッシュボードがトーナメントを読み込みます
ドロップダウンが正しく設定されています
トーナメント作成フォームが正常に開かれます
彼は、トーナメントを作成した後のリストの更新は後で処理されることに言及しています。
次のレッスンでは、ティムがトーナメントビューアーフォームをプレビューします。このフォームでは、ラウンド、マッチアップ、スコアリング、進行が実装され、トーナメントシステムが活性化されます。このレッスンの将来のバージョンでは、WinFormsや.NETの新バージョンリリースに関連した更新を含め、追加機能や改善点についても取り上げます。
このレッスンでは、WinFormsダッシュボードが単なるUIではなく、モデル、データアクセス、ナビゲーション間の調整ポイントであることを、ティムが段階的に丁寧に示しています。
WinFormsは、その安定性、高速な開発速度、およびWindowsオペレーティングシステムとの深い統合により、依然として非常に重要です。

