[C#.NET][Winform] 使用 BindingSource 與控制項連動並使用 Entity Framework Code First 實作 CRUD
我常使用 BindingSource 處理控制項連動的中間層物件,它為我省掉不少的程式碼
BindingNavigator 綁定 BindingSource,用來處理資料位置,上一筆、下一筆…等等,也省了不少 hard code 的時間
DataGridView.DataSource 屬性可以綁定 BindingSource,不少夥伴以為 DataSource 只吃 DataSet、DataTable,查看 MSDN 應該可以更瞭解 DataSource 到底支援什麼物件型態
以前寫過的相關文章
http://www.dotblogs.com.tw/yc421206/archive/2011/04/19/23072.aspx
http://www.dotblogs.com.tw/yc421206/archive/2011/03/07/21706.aspx
情境:
需要 Master-Detial 連動(使用 BindingSource.PositionChanged 事件)
為 BindingSource 綁定 IEnumerable<T>,資料變更後(CRUD),按下存檔即存到資料庫
資料顯示有巡覽列,第一筆、上一筆、下一筆、最後一筆
本文連結
事前準備,此範例會使用 Code First 建立資料庫,以下是 POCO 定義
- BusinessFlowDao 實作 IBusinessFlowDao
- 使用 EF 進行資料 CRUD,程式碼還蠻簡單的
完整程式碼如下:
本來還想切 BLL 出來,因為想不到用什麼情境當範例,就沒寫
UI 層基本上就是去調用 DAO 物件,什麼時間點要去發動調用的動作,就要看 UI 控制項的互動
透過 DataSource Designer,幫我們產生控制項綁定程式碼,可以省掉不少的程式碼,當控制項越多的時候省越多
把 DataSource 拖到 Winform 上,做一些調整,最後畫面長這樣
Account_BindingSource 被以下控制項綁定
-
- Account_BindingNavigator.BindingSource = Account_BindingSource
- Account_DataGridView.DataSource = Account_BindingSource
AccountLog_BindingSource 被以下控制項綁定
-
- AccountLog_BindingNavigator.BindingSource = AccountLog_BindingSource
- AccountLog_DataGridView.DataSource = AccountLog_BindingSource
BindingSource則是綁定我們剛剛建立的 DataSource
-
- Account_BindingSourc.DataSource = Simple.BindingSourceEF.DAL.Model.Account
- AccountLog_BindingSource.DataSource = Simple.BindingSourceEF.DAL.Model.AccountLog
完整程式碼如下:
準備好 Account_BindingSource_AddingNew 方法,當按下 Account_BindingNavigator 新增圖形後,
它會觸發 BindingSource.AddingNew 事件,Account_BindingSource_AddingNew 方法就會被調用,這個方法有兩個動作
- 為Account_BindingSource 新增資料,指定 AddingNewEventArgs.NewObject 屬性
- 為資料庫新增一筆Account,this.BusinessFlowDao.InsertAccount(account)
{ var account = new Account(); e.NewObject = account; this.BusinessFlowDao.InsertAccount(account); }
很可惜 BindingSource 沒有 Delete 事件,我也不知道怎麼取得被刪除的物件,所以刪除目前無法與 BindingSource 連動,只能自己來,程式碼也很簡單
- 為Account_BindingSource 刪除資料,調用 Account_BindingSource.Remove(account)
- 從資料庫刪除資料,調用this.BusinessFlowDao.DeleteAccount(account)方法
- 動作要能夠正確執行,要把 Account_BindingNavigator.Delete=none
{ var account = (Account)this.Account_BindingSource.Current; this.BusinessFlowDao.DeleteAccount(account); this.Account_BindingSource.Remove(account); }
這部份 BindingSource跟EF幫我們處理了,不用寫 code
當 Master 資料列被點選時會觸發 Account_BindingSource_PositionChanged 事件,得知目前哪一列已被選取,再根據查詢條件取得 Detail
{ var source = (BindingSource)sender; if (source.Position < 0) { this.AccountLog_BindingSource.DataSource = null; return; } this._currentAccount = (Account)source.Current; var queryAccountLogs = this.BusinessFlowDao.GetAllAccountLogs(this._currentAccount.Id); if (!queryAccountLogs.Any()) { this.AccountLog_BindingSource.DataSource = null; return; } this.AccountLog_BindingSource.DataSource = queryAccountLogs.ToList(); }
把資料存到資料庫
{ this.Validate(); this.BusinessFlowDao.Commit(); }
完整程式碼如下:
文章出自:http://www.dotblogs.com.tw/yc421206/archive/2014/12/11/147603.aspx
專案位置:https://dotblogsamples.codeplex.com/SourceControl/latest#Simple.BindingSourceEF/
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET