通過Tim Corey的競賽查看程式解釋的WinForms資料綁定
[[academy-video-youtube({"vid": "mg7TlkPgq2Y", "start_time": "0", "title": "C# App Start To Finish Lesson 22 - Tournament Viewer Part 1", "creator": "Tim Corey", "length": "1h 11m 40s"})]]
介紹
在C# App Start to Finish系列的第22課中,Tim Corey開始製作Tournament Viewer表單,專注於WinForms資料綁定。 Tim解釋說,這一課並不涉及將資料保存到資料庫或文字文件中——那將在之後進行。 相反,這段影片的全部目的是連接UI、填充控制項,並了解資料如何通過資料綁定在模型和WinForms控制項之間移動。
Tim明確指出WinForms資料綁定可能顯得笨拙、混亂,有時甚至令人沮喪。 因此,這一課成為深入了解資料綁定實際行為、破壞它的原因以及如何修復的實用指南。 通過跟蹤Tim的除錯過程,我們獲得了關於WinForms綁定機制的真實而有價值的理解。
Tournament Viewer表單概述
Tim首先描述Tournament Viewer表單應該做的事情。 表單顯示:
錦標賽名稱
包含錦標賽回合的下拉選單
顯示所選回合比賽的列表方塊
- 所選比賽的隊名和比分
Tim強調所有這些資訊必須同步。 當回合更改時,比賽組合必須更新。 當比賽組合更改時,隊名和比分必須更新。 這一要求推動了圍繞資料綁定的整個討論。 綁定到相同資料源的控件,也稱為資料綁定控件,將自動同步。 BindingNavigator控件通過保持指向記錄列表中項目的指標當前來處理資料綁定。 CurrencyManager類管理列表控件和資料源物件之間的綁定集合,允許位置跟蹤和更改通知。 每個綁定控件,例如TextBox或Label,通過這些機制連結到資料源,以確保自動同步。
將Tournament物件傳入表單
Tim解釋Tournament Viewer表單不應決定載入哪個錦標賽。 這個責任屬於儀表板。 因此,Tournament Viewer表單必須通過其構造函式接收一個TournamentModel。
他展示了傳入的錦標賽物件如何儲存在表單層的私有字段中,從而可以被表單中的每個方法存取。 該錦標賽物件成為所有資料綁定操作的單一事實來源。 在簡單資料綁定中,一個控件可以綁定到單個資料元素,例如來自單個資料表的值,以允許您顯示或編輯個別資料點。 BindingSource可以用於簡單和複雜的綁定場景。
載入表單資料方法
Tim引入了一個名為LoadFormData的私有方法。 這個方法從錦標賽模型中拉取資料並將其推送到UI控件中。
例如:
- 錦標賽名稱標籤直接從tournament.TournamentName獲取其值。 這涉及設置控件的屬性,如文字框控件的文字屬性,為資料來源中的值。
Tim強調這是最簡單的資料綁定形式——手動分配值——在處理列表和集合之前它是一個很好的起點。 簡單綁定將控件的單個屬性連接到資料源中的單個值,通常一次顯示一條記錄。
連接Dashboard按鈕
Tim演示如何修改儀表板,以便當使用者選擇一個錦標賽並點擊"Load Tournament"時,Tournament Viewer表單會打開。
在這裡,Tim將所選的下拉項目強制轉換為TournamentModel並傳入查看器表單。 他通過運行應用程式並看到錦標賽名稱正確地出現,確認接線工作正常。
這確認了基本物件傳遞和UI更新的功能在進入列表綁定之前正常運作。
從資料源將回合載入到下拉選單中
現在Tim進入列表綁定,從錦標賽回合開始。
他解釋回合最好表示為整數列表,而不是字串。 Tim明確表示這一選擇使生活更輕鬆,因為:
整數清晰綁定到下拉選單
整數可以在不進行字串解析的情況下檢索
- 所選值可以直接轉回為int
一個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顯示的自然字串表示。
Tim不強迫將邏輯放入UI中,而是將只讀的DisplayName屬性新增到模型中。 該屬性會構建一個像這樣的字串:
Team A vs. Team B如果隊伍缺席(輪空周或未來回合),Tim將返回:
比賽尚未確定複雜的綁定控件,如DataGridView,支持複雜的綁定場景,其中可以顯示和編輯來自資料表或其他結構的多個資料元素。 複雜資料綁定允許您將多個資料元素綁定到一個控件,譬如從底層記錄源綁定多列或多行。 ADO.NET提供了許多適合綁定的資料結構,包括DataTable、DataView和其他結構,而Windows Forms支持綁定到多個資料源。 綁定類管理資料源字段和控件屬性之間的邏輯連結,並且像IBindingList、IEditableObject和INotifyPropertyChanged這樣的接口提供排序、更改通知和回滾支持。 您可以在資料視圖上設置預設過濾器來控制資料顯示方式,而綁定上下文和CurrencyManager最終決定資料綁定控件的同步方式。 Windows Form的BindingContext屬性管理表單的CurrencyManager物件,每個資料源都有一個CurrencyManager物件,保持所有綁定到相同資料源的控件同步。 可以在Windows Forms中建立自定義控件,通過實現必要的資料綁定接口,使其行為類似於標準資料綁定控件。
這是Tim強調的一個關鍵的WinForms資料綁定原則:
模型應該決定其顯示方式——而不是UI。
偵錯綁定錯誤
Tim遇到多個錯誤:
第二回合顯示錯誤
比賽未刷新
- 事件意外觸發
Tim不隱藏這些問題,而是逐步完成每個偵錯步驟。他解釋當列表被替換時,即使新列表包含有效資料,綁定會如何中斷。
這導致了一個關鍵的WinForms課程。
以下程式碼演示如何處理Binding類的Format和Parse事件,以在資料綁定過程中提供特殊的格式化和驗證。 格式事件和解析事件可用來自定義資料在UI和資料源之間如何轉換和驗證。
Windows Forms資料綁定中的BindingSource與BindingList
Tim嘗試使用BindingSource,將其置於UI控件和資料之間。 他解釋這曾經是推薦的方法,但承認這引入了複雜性和混亂。 BindingSource組件作為資料源和Windows Forms控件之間的代理,它能夠與適合綁定的各種資料結構一起工作,如DataTables、DataViews、BindingLists和陣列。
然後,他介紹了BindingList,解釋它在列表更改時會自動更新綁定控件。 如果資料源實現了適當的接口,例如INotifyCollectionChanged,Windows Forms中的資料綁定支持在底層資料更改時自動更新控件。
然而,Tim發現了一條關鍵規則:
您絕不能用一個新的BindingList來替換它。
相反,您必須:
清空現有的BindingList
- 將項目重新新增到其中
替換列表會破壞綁定連接。
通過清空列表來修復損壞的綁定
Tim確認綁定問題的根本原因:
分配新的BindingList() 會斷開UI
- 清空和重新新增項目保留綁定
他更新了回合和比賽組合,採用了這種模式。 一旦一致應用,UI終於正確更新。
手動載入初始選擇
Tim解釋WinForms在載入項目時不會自動觸發SelectedIndexChanged。
為了解決這個問題,他手動:
在載入回合後載入第一回合比賽組合
- 程式化地選擇第一個比賽組合
這確保UI在不需要使用者互動的情況下正確初始化。
最終結果和課程總結
在課程結束時,Tim確認:
回合正確更新
比賽組合正確更新
隊名和比分正確載入
- 輪空周和未來回合顯示有意義的文字
他強調這堂課不是關於完美,而是關於理解WinForms資料綁定的真正行為——包括其局限性。
Tim結束時解釋得分和過濾(如"僅未完成")將在下一課處理,一旦有實際的狀態變更可以進行處理。
結語
第22課是一個實用的WinForms資料綁定的大師班,不是因為一切都運行順利,而是因為Tim Corey實時地展示了每個失誤、修復和設計決策。
通過觀看Tim的影片,開發者獲得對以下問題的現實理解:
為什麼WinForms綁定感覺脆弱
BindingList如何工作
為什麼清除列表重要
- UI和模型應該如何互動
如果您曾經苦於WinForms資料綁定,這堂課——以及Tim的解釋——使"為什麼"最終水落石出。

