第五天 -- 《2014-07-21 三層架構》-- 在DataGridView控件上直接修改和Update


一、上午《01、修改dgv控件中下拉列表的添加》--《03、添加了ValueMenber之后列綁定屬性的修改》

1、將DataGridView中的列指定為需要的類型。

如下圖:創建DataGridViewColumn時需要指定為真正需要的子類型。這樣才能更好地編輯行數據。這些類型有:Button、CheckBox、ComboBox、Image、Link、TextBox 

  這些子類型的列,正如其名。與同名的單獨控件有類似的屬性、功能和事件。比如DataGridViewButtonColumn就像一個Button控件;而DataGridViewComboBoxColumn就像一個ComboBox控件,可以綁定下拉列表的數據源,可以指定項應該顯示綁定對象的什么屬性,選中值應該對應綁定對象的什么屬性。等等。

 

2、指定下拉項的數據源。

如以下代碼:

 1 //在DataGridView表格控件綁定數據源之前,先綁定下拉列表列的數據源。如此一來,用戶編輯該列時,可以下拉選擇可選項。
 2 var  column = this.dgvList.Columns["cname"] as DataGridViewComboBoxColumn;//注意:表格列名 = 數據庫列名 = 實體類屬性名。推薦這樣的命名方式。必須將列顯式轉為子類型。
 3 if (column != null)
 4 {
 5     column.DisplayMember = "cname"; //顯示值。即綁定實體對象的屬性名。
 6     column.ValueMember = "cid";//實際值  有更高的優先級,如果同時指定了這兩項屬性,那么真正的對應字段是ValueMember.以后拿出來進行匹配的就是cid值。與之匹配的也必須是對應類型和意義的字段或者屬性名稱
 7     column.DataSource = cm.GetAllClassesList(false);//BLL層通過DAL層獲取實體對象集合——“班級表”的查詢結果集
 8     column.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;//非編輯時,不顯示下拉按鈕
 9 }
10 
11 this.dgvList.DataSource = pm.GetAllPersonList(false);//DataGridView綁定數據源(BLL層從DAL層獲取的實體對象集合)

注意:ValueMember指定屬性的數據類型必須與該列的綁定數據源屬性的數據類型一致。

  針對上例來說:ValueMember指定的是Classes實體類的CID屬性。該DataGridViewComboBoxColumn列綁定的是Person實體類的PCID屬性。(這兩個屬性就是主外鍵關系,Person表的外鍵PCID對應Classes表的主鍵CID)。所以:Classes實體類的CID屬性和Person實體類的PCID屬性都是int整型。這個必須要一致。

 

3、下拉列異常分析

當彈出下圖異常時,要冷靜分析,該異常說明了這樣幾個問題:

(1)從哪個單元格開始沒加載,說明哪筆數據綁定到表格控件時出了問題。(紅圈處)

(2)“所在班級”列的下拉列表中不存在紅圈內的項

(3)觀察數據源可知,Person表ID為39的記錄其PCID值為64(PCID是外鍵,指向Classes表的CID),而從Classes班級表獲取的結果集中,不存在CID為64的記錄。(可能是某些歷史原因)

表中數據如下:

 

4、DataGridView其他注意事項

(1)每次綁定DataGridView.DataSource數據源的時候,都會觸發SelectionChanged事件。

也就是說如果你訂閱了SelectionChanged事件,每次對DataSource賦值后,下一句馬上就去執行該事件處理的代碼。當這個事件處理方法結束,才會接着執行賦值語句下一行。流程如下圖所示:

                            

  因為DataGridView控件的SelectionMode有5個類型,分別代表選中模式(單元格選中、整行選中、整列選中、點單元格只選單元格點行頭選中整行、點單元格只選單元格點列頭選中整列)詳見上右圖。所以如果你訂閱了SelectionChanged事件,每次對DataSource賦值后,都會進入5次SelectionChanged事件處理方法。

 

(2)手動讓單元格進入編輯狀態

  允許用戶編輯單元格時,默認情況下用戶需要先選擇行(或單元格),再雙擊單元格才能開始編輯(我試了試開始編譯一個未選中的單元格需要點擊3次鼠標左鍵)。有的人喜歡選中單元格時直接進入編輯狀態。可以使用如下代碼,手動進入編輯狀態。

1 //點擊單元格,指定立馬進入該單元格的編輯狀態
2 private void dgvList_CellClick(object sender, DataGridViewCellEventArgs e)
3 {//點擊單元格,指定進入到編輯狀態
4     this.dgvList.BeginEdit(true); 5 } 

注意:但是這樣做也有不爽的地方,有的人閱讀內容的時候喜歡在字里行間點來點去,一不小心修改了內容並換了行。那就直接Update了。

 

二、上午《04、添加切換行和判斷是否進入編輯狀態的事件》--《07完成直接在dgv控件中進行的修改操作》 --直接在DataGridView的行上修改數據后Update到數據庫

1、訂閱DataGridView的CellBeginEditSelectionChanged事件,實現行數據修改后Update到數據庫的功能。

 1 //下面字段用於標識單元格編輯后,只有在數據被改變才Update數據庫。
 2 private bool _isEdited = false;//選中行是否進入過編輯狀態
 3 private bool _isFirst = true;//單元格是不是該行第一個進入修改的單元格。顯而易見一行可以有多個單元格被編輯,每個單元格被編輯都會進入CellBeginEdit事件處理。
 4 private Person _current;//選中行綁定項
 5 private Person _original = new Person();//編輯前的實體對象(用來在用戶選中其他行后,把編輯前和現在綁定的對象數據做對比,只有真正修改了才去Update數據庫)
 6 
 7 private void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
 8 {//選中單元格進入編輯狀態時觸發。(主要用來保存編輯前的數據)
 9     _isEdited = true;
10     _current = this.dataGridView1.CurrentRow.DataBoundItem as Person;//這是編輯前。_current就是選中行綁定項
11     if (_isFirst)
12     {//如果本單元格是該行第一個進入編輯的,應該把_current存到_original中,也就是把編輯前對象存好。而編輯后_current的內容會隨之改變。
13         _original.PCID = _current.PCID;
14         _original.PCName = _current.PCName;
15         _original.PGender = _current.PGender;
16         _original.PEmail = _current.PEmail;
17         _original.PType = _current.PType;
18         _isFirst = false;
19     }
20 }
21 
22 private void dataGridView1_SelectionChanged(object sender, EventArgs e)
23 {//當用戶選中另一行之后,如果剛才編輯的行數據修改了,應該Update數據庫。 24     if (_isEdited)//如果上一個選中行被編輯過(進過編輯狀態)
25     {
26         if (_original.PCID != _current.PCID || _original.PCName != _current.PCName || _original.PGender != _current.PGender
27             || _original.PType != _current.PType || _original.PEmail != _current.PEmail)
28         {//如果上一個選中行綁定的數據做了編輯修改
29 
30             if (UpdatePerson(_current) == 1)
31             {//Update實體對象到數據庫
32                 MessageBox.Show("ok");
33                 _isEdited = false;
34                 this.dataGridView1.DataSource = GetList();
35             }
36         }
37         _isFirst = true;
38         _isEdited = false;
39     }
40 }

注意:每個時間點上,獲取的this.dataGridView1.CurrentRow.DataBoundItem綁定項,都是綁定的實時的數據(實體對象)。

也就是說每次改動了綁定項的數據,下次再獲取該綁定項,獲取的就是每次修改后的實體對象。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM