Tim Coreyのトーナメントビューアーを通してのWinFormsデータバインディング解説
はじめに
C# App Start to Finishシリーズのレッスン22では、ティム・コーリーがTournament Viewerフォームの作業を開始し、WinFormsデータバインディングに重点を置いています。 ティムは、このレッスンがデータベースやテキストファイルにデータを保存することに関するものではないと説明しています。それは後で扱います。 代わりに、このビデオの全目的は、UIを接続し、コントロールを設定し、データがモデルとWinFormsのコントロールの間でどのように移動するかをデータバインディングを使用して理解することです。
ティムは、WinFormsのデータバインディングが扱いづらく、混乱を招き、時にはストレスを感じることがあると明言しています。 そのため、このレッスンはデータバインディングが実際にどのように動作するか、何がそれを壊すのか、そしてそれをどのように修正するのかについての深く実践的なガイドになります。 ティムのデバッグの過程を追うことで、WinFormsのバインディングメカニズムに対する現実的で価値のある理解を得ることができます。
トーナメントビューアフォームの概要
ティムは、トーナメントビューワーフォームが何をするべきかを説明することから始めます。 フォームに表示されます:
トーナメント名
トーナメントラウンドを含むドロップダウン
選択されたラウンドの対戦を表示するリストボックス
選択された試合のチーム名とスコア
Tim は、これらすべての情報を同期させ続けることの重要性を強調しています。 ラウンドが変更されると、対戦を更新する必要があります。 マッチアップが変更された場合、チーム名とスコアを更新する必要があります。 この要件は、データバインディングに関する議論全体を駆動します。 同じデータソースにバインドされたコントロール、またはデータバウンドコントロールは、自動的に同期を保ちます。 BindingNavigatorコントロールは、レコードリスト内の項目へのポインタを常に最新に保つことで、データへのバインディングを処理します。 CurrencyManager クラスは、リストコントロールとデータソースオブジェクトの間のバインディングのコレクションを管理し、位置の追跡と変更通知を可能にします。 テキストボックスやラベルなどのバウンドコントロールは、これらのメカニズムを通じてデータソースにリンクされ、自動的な同期が保証されます。
トーナメントオブジェクトをフォームに渡す
Timは、トーナメントビューアフォームがどのトーナメントをロードするかを決定すべきではないことを説明します。 その責任はダッシュボードにあります。 したがって、トーナメントビューアフォームは、コンストラクターを通じてTournamentModelを受け取る必要があります。
彼は、渡されたトーナメントオブジェクトがフォームレベルのプライベートフィールドに格納され、フォーム内のすべてのメソッドでアクセス可能になる方法を示します。 このトーナメントオブジェクトが、すべてのデータバインディング操作の信頼できる情報源となります。 単純なデータバインディングでは、コントロールを単一のデータ要素(単一データテーブルからの値など)にバインドすることができ、個別のデータポイントを表示または編集できます。 BindingSourceは、単純なバインディングと複雑なバインディングの両方のシナリオで使用できます。
フォームデータ読み込みメソッド
TimはLoadFormDataと呼ばれるプライベートメソッドを紹介します。 このメソッドは、トーナメントモデルからデータを抽出し、UIコントロールにプッシュします。
例えば:
- トーナメント名ラベルはtournament.TournamentNameから直接値を取得します。 これは、例えば、テキストボックスコントロールのテキストプロパティなどをデータソースの値に設定することを指します。
Timは、これがデータバインディングの最も単純な形式であり、値を手動で割り当てることで、リストやコレクションを扱う前の良いスタート地点であることを強調します。 単純なバインディングは、コントロールの単一のプロパティをデータソースの単一の値に接続し、通常は一度に1つのレコードを表示します。
ダッシュボードボタンのワイヤリング
Timは、ユーザーがトーナメントを選択して"トーナメントをロード"をクリックすると、トーナメントビューアフォームが開くようにするためにダッシュボードを変更する方法を説明します。
ここで、Timは選択されたドロップダウンアイテムをTournamentModelにキャストし、それをビューアフォームに渡します。 彼はアプリケーションを実行し、トーナメント名が正しく表示されることを確認して、ワイヤリングが機能していることを確認します。
これにより、リストバインディングに進む前に、基本的なオブジェクトの受け渡しとUIの更新が機能していることが確認されます。
データソースからドロップダウンへのラウンドの読み込み
現在、Timはリストバインディングに進み、トーナメントラウンドから始めます。
彼はラウンドが文字列ではなく整数のリストとして表現されるべきであることを説明します。 Timはこの選択が生活を楽にする理由を明示しています:
整数はドロップダウンにクリーンにバインドされます
整数は文字列解析なしで取得できます
- 選択された値は直接整数にキャストできます
ComboBoxコントロールは、効率的にデータを表示および選択できるように、指定されたテーブルまたはリストにバインドすることができます。 ComboBoxコントロールをバインドする際には、ユーザーに表示されるフィールドを指定するためのDisplayMemberプロパティと、基礎となる値として使用されるフィールドを決定するためのValueMemberプロパティを使用できます。 同様に、DataGridViewコントロールをデータテーブルに含まれる情報にバインドすることもできます。
Timはトーナメントのラウンドをループし、一意のラウンド番号を抽出し、それらをリストに格納します。
データバインディングによるラウンドドロップダウンのワイヤリング
Timは最初の重要なWinFormsバインディングルールを紹介します:
リセットする前にDataSourceを必ずnullにセットします。
彼はドロップダウンのデータソースをクリアし、その次にラウンドリストを割り当てます。 コントロールをデータソースにバインドすると、データソースがINotifyCollectionChangedなどのインターフェースを実装している場合、データが変更されるとコントロールは自動的にUIを更新します。 これにより、データとその視覚的表現の間でリアルタイムの同期が保証されます。 さらに、UIコントロールまたは基礎となるデータソースの変更は、設定に基づいて(単方向または双方向)、バインディングの他の端を自動的に更新します。 整数は自然に文字列に変換されるため、ここではDisplayMemberが必要ないことを彼は説明します。
次にTimは、ロードメソッドを呼び出すのを忘れて、ドロップダウンが空になるという一般的な間違いを示します。
SelectedIndexChangedイベントと動的な更新
Timは、WinFormsが特にSelectedIndexChangedに大きく依存していることを説明します。
彼はラウンドドロップダウンのSelectedIndexChangedイベントを、選択されたラウンドの対戦をロードするメソッドに接続します。 WinFormsデータバインディングでは、イベントハンドラはイベントをトリガーしたコントロールを特定するobject senderパラメータを受け取ります。 カスタマイズしたデータフォーマットとバリデーションには、FormatやParseなどのイベントを処理できます; BindingクラスのFormatおよびParseイベントは、データバインディングプロセス中にデータの特別なフォーマットおよびバリデーションを可能にします。 他のコントロールも同様のイベント処理を通じてバインドおよび同期化できます。
Timは、イベントハンドラに直接コードを配置する代わりに、ロジックをプライベートヘルパーメソッドに抽出することを好みます。 彼はこの方法でコードが再利用可能でクリーンになることを説明します。
選択されたラウンドに基づいて対戦をロードする
Timは、ドロップダウンの選択されたアイテムを整数に再キャストして選択されたラウンドを取得します。
彼はトーナメントのラウンドを再びループしますが、今度は、マッチアップラウンドが選択されたラウンドと等しいマッチアップをフィルタリングします。 これらのマッチアップは選択されたマッチアップリストに配置され、そのリストがマッチアップリストボックスのデータソースになります。
これにより、複雑なオブジェクトのリストのバインディングの課題が生じます。
バインディングのための表示プロパティを作成する
Timは、マッチアップモデルにはUI表示に適した自然な文字列表現がないことを説明します。
UIにロジックを押し込む代わりに、Timはモデルに読み取り専用のDisplayNameプロパティを追加します。 このプロパティは以下のような文字列を構築します:
チームA対チームBチームが欠けている場合(バイウィークまたは将来のラウンド)、Timは以下を返します:
対戦はまだ決定されていませんDataGridViewのような複雑なバウンドコントロールは、1つのデータテーブルや他の構造から複数のデータ要素を表示および編集できる複雑なバインドシナリオをサポートします。 複雑なデータバインディングにより、コントロールに複数のデータ要素をバインドすることができ、例えば、基となるレコードソースから複数の列または行をバインドすることができます。 ADO.NETは、DataTable、DataView、および他の構造を含む、バインディングに適した多くのデータ構造を提供し、Windows Formsは複数のデータソースへのバインディングをサポートします。 バインディングクラスはデータソースフィールドとコントロールプロパティの論理的リンクを管理し、IBindingList、IEditableObject、INotifyPropertyChangedのようなインターフェースはソート、変更通知、およびロールバックサポートを提供します。 データの表示方法を制御するデフォルトフィルタをデータビューに設定することができ、バインディングコンテキストとCurrencyManagerにより、データバウンドコントロールが最終的に同期されます。 Windows FormのBindingContextプロパティは、フォームのCurrencyManagerオブジェクトを管理し、各データソースには単一のCurrencyManagerオブジェクトがあり、同じデータソースにバインドされたすべてのコントロールを同期させます。 必要なデータバインディングインターフェースを実装することにより、標準のデータバウンドコントロールのように振る舞うカスタムコントロールをWindows Formsで作成できます。
これはTimが強調するキーとなるWinFormsデータバインディング原則です:
モデルはどのように表示されるかを決定するべきであり、UIではありません。
バインディングバグのデバッグ
Timはいくつかのバグに遭遇します:
ラウンド2が正しく表示されません
マッチアップが更新されない
- イベントが予期せず発火する
これらの問題を隠す代わりに、Timは各デバッグステップを順を追って説明します。彼は、たとえ新しいリストに有効なデータが含まれていたとしても、リストが置き換えられるとバインディングが壊れる方法を説明します。
これにより、重要なWinFormsの教訓が得られます。
次のコードは、データバインディングプロセス中に特別なフォーマットとバリデーションを提供するためのBindingクラスのFormatおよびParseイベントを処理する方法を示します。 formatイベントとparseイベントは、UIとデータソース間でデータがどのように変換および検証されるかをカスタマイズするために使用できます。
Windows FormsデータバインディングにおけるBindingSourceとBindingList
TimはBindingSourceを試し、UIコントロールとデータの間に配置します。 彼はこれがかつては推奨されていたアプローチであったことを説明しますが、それが複雑さと混乱をもたらすことを認めます。 BindingSourceコンポーネントは、データソースとWindows Formsコントロール間のプロキシとして機能し、データテーブル、データビュー、バインディングリスト、および配列などのバインドに適したさまざまなデータ構造と連携します。
彼は次にBindingListを紹介し、それがリストが変更されるとバウンドされたコントロールを自動的に更新することを説明します。 データソースがINotifyCollectionChangedなどの適切なインターフェースを実装している場合、Windows Formsのデータバインディングは、基礎となるデータが変化するとコントロールを自動的に更新するサポートをしています。
しかし、Timは重要なルールを発見します:
BindingListを新しいものに置き換えてはいけません。
その代わりに、あなたはする必要があります:
既存のBindingListをクリアします
- アイテムを再び追加する
リストを置き換えると、バインディング接続が壊れます。
リストをクリアして壊れたバインディングを修正する
Timはバインディング問題の根本原因を確認します:
新しい BindingList() を割り当てると、UI が切断されます
- アイテムをクリアして再追加することでバインディングが保たれます
彼はラウンドとマッチアップの両方をこのパターンで更新します。 一貫して適用すると、UIは最終的に正しく更新されます。
初期選択を手動で読み込む
Timは、WinFormsがアイテムがロードされるとSelectedIndexChangedを自動的に発火しないことを説明します。
これを修正するために、彼は手動で:
ラウンドを読み込んだ後にラウンド1のマッチアップを読み込みます
- プログラム的に最初のマッチアップを選択します
これにより、ユーザーの操作を必要とせずにUIが正しく初期化されることが保証されます。
最終結果と授業のまとめ
授業の終わりには、Timは確認します:
ラウンドが正しく更新されます
マッチアップが正しく更新されます
チーム名とスコアが正しくロードされます
- バイウィークと将来のラウンドが意味のあるテキストを表示します
彼は、このレッスンが完璧さではなく、WinFormsデータバインディングがどのように実際に動作するか、包括的にその限界を理解することを目的としていたことを強調します。
Timは、スコアリングとフィルタリング("未プレイのみ"など)は、実際の状態の変更があれば次のレッスンで処理されることを説明して終わります。
締めくくりの考え
レッスン22は実用的なWinFormsデータバインディングのマスタークラスであり、すべてがスムーズに機能するからではなく、Tim Coreyがリアルタイムであらゆる失敗、修正、およびデザインの決定を通して説明するからです。
Timのビデオに従うことで、開発者は次のことについて現実的な理解を得ることができます:
なぜWinFormsバインディングが壊れやすいように感じるのか
BindingListがどのように機能するのか
リストをクリアすることがなぜ重要なのか
- UIとモデルがどのように相互作用するべきか
WinFormsデータバインディングに苦労したことがあるなら、このレッスンとTimの説明が"なぜ"をやっと理解させてくれます。

