WinForm编程数据视图之DataGridView浅析
學習C#語言的朋友們肯定或多或少地接觸到了WinForm編程,在C#語言的可視化IDE中(如VS.NET中)使用設計器可以讓我們輕松地完成窗體、按鈕、標簽、圖片框等等控件的組合,我們可以輕易地做出界面友好的WinForm應用程序。我們還可以通過WinForm程序中強大的事件處理機制來使我們的應用程序更加豐滿。
當然,我們這次不談窗體、不談按鈕……
我們談談DataGridView(數據網格視圖)。
作為真正與用戶進行信息交互的界面,很大程度上需要向用戶完整地展示數據,而在WinForm相關的強大控件中就有用于數據顯示的。數量很多,但作為列表視圖顯示的控件,首推ListView和DataGridView。在顯示多行多列的數據時,兩者往往可以互相替換。
由于筆者認為DataGridView的界面不如ListView友好,所以是盡量使用ListView而非DataGridView的,而最近卻喜歡使用DataGridView了,主要原因當屬它強大的數據處理。
它可以智能處理綁定到的數據源,而且可作為數據源綁定的類型也非常之多。
DataGridView 類支持標準的 Windows 窗體數據綁定模型。 這意味著數據源可以是實現下列接口之一的任何類型:
IList 接口,包括一維數組。
IListSource 接口,例如,DataTable 和 DataSet 類。
IBindingList 接口,例如,BindingList(Of T) 類。
IBindingListView 接口,例如,BindingSource 類。?
詳情請參見?http://msdn.microsoft.com/zh-cn/library/system.windows.forms.datagridview.datasource.aspx(DataGridView.DataSource 屬性)
對于我們平時的編程來講,可能將DataTable和List<T>綁定到DataGridView的DataSource是比較多的情況。
但其實我想說的一點是(個人觀點,不保證正確,真的):如果是DataTable,最好用DataTable的DataView;如果是IList<T>,最好用BindingList <T>。
首先我們看看DataGridView里的重要屬性:
?、貯utoGenerateColumns 屬性(請參見http://msdn.microsoft.com/zh-cn/library/system.windows.forms.datagridview.autogeneratecolumns.aspx)?
這個屬性十分重要,重要的原因之一:在VS的設計器屬性里找不到(不知道為什么它會被加上不出現在屬性列表里的特性……)。這個屬性的作用很簡單也很重要:指定DataGridView是否自動增加列。
如果您希望通過手動添加列指定將要顯示到數據網格視圖綁定對象的屬性,您必須將此屬性設置為true;
比如下面的例子:
我希望在數據網格視圖內顯示自定義對象“員工的信息”:
員工類:
1 using System;2
3 namespace dgvEG
4 {
5 // 員工類
6 public class SE : ICloneable
7 {
8 // 員工信息
9 public string Name { get; set; }
10 public int Age { get; set; }
11 public int WorkNo { get; set; }
12 public Gender Sex { get; set; }
13 public SignRecord Record { get; set; }
14
15 // 構造方法
16 public SE() { }
17
18 public SE(int workNo, string name, int age, Gender sex)
19 {
20 this.WorkNo = workNo;
21 this.Name = name;
22 this.Age = age;
23 this.Sex = sex;
24 this.Record = new SignRecord();
25 }
表示性別的枚舉:
?
1 using System;2
3 namespace dgvEG
4 {
5 /// <summary>
6 /// 性別
7 /// </summary>
8 public enum Gender
9 {
10 Male = 0, // 男
11 Female = 1 // 女
12 }
13 }
員工的帶卡記錄(即簽到簽退的記錄):
1 using System;2
3 namespace dgvEG
4 {
5 /// <summary>
6 /// 打卡記錄
7 /// </summary>
8 public class SignRecord
9 {
10 // 簽到時間
11 public DateTime SignInTime { get; set; }
12 // 簽退時間
13 public DateTime SignOutTime { get; set; }
14 }
15 }
如果我直接將“員工對象”的集合座作為數據源綁定到DataGridView的DataSource,并且也沒有在DataGridView上進行任何過濾的操作,那么結果將是如此: ?
上圖有幾點問題,我們一個個地來解決,首先是列名,我們肯定希望是中文的,如此,我們就需要手動指定列名。
如果您使用VS作為開發工具,可以參考我的做法:
這樣是不是行了呢?我們再次運行程序,卻得到下面的結果:
……估計沒人愿意這樣,我們再回到綁定數據源的代碼:
1 // 定義測試數據2 SE se1 = new SE(10001, "測試1號", 19, Gender.Female);
3 SE se2 = new SE(10002, "測試2號", 20, Gender.Male);
4 SE se3 = new SE(10003, "測試3號", 21, Gender.Female);
5 SE se4 = new SE(10004, "測試4號", 22, Gender.Male);
6 SE se5 = new SE(10005, "測試5號", 23, Gender.Female);
7 SE se6 = new SE(10006, "測試6號", 24, Gender.Male);
8
9 // 利用測試數據制作數據源
10 List<SE> list = new List<SE>();
11 list.AddRange(new SE[] { se1, se2, se3, se4, se5, se6 });
12
13 // 綁定數據源
14 dataGridView1.DataSource = new BindingList<SE>(list);
看起來沒什么問題,這段代碼可以放到例如窗體加載事件里正確執行。
從上面的圖片不難看出:我們手動添加的列是固有的,只是由于DataGridView對數據源的強大處理,它會自動添加列以正常且完整地顯示數據源的信息。
那么我們不讓它自動增加列不就OK了?
在綁定數據源之前加上一句代碼,如下:
1 // ……2 // ……
3 // 指定數據網格視圖不自動增加列
4 dataGridView1.AutoGenerateColumns = false;
5 // 綁定數據源
6 dataGridView1.DataSource = new BindingList<SE>(list);
不出所料,您看到的結果會是下圖:
請您不要急,仔細看看,項數是正確的!說明數據是沒問題的,問題在我們希望用自己的方式顯示數據,那么DataGridView的自動分析數據就不會執行,我們就必須指定哪一行顯示對象的那一個屬性。接下的第二個重要屬性就是如此的作用:
②DataPropertyName屬性(請參見http://msdn.microsoft.com/zh-cn/library/system.windows.forms.datagridviewcolumn.datapropertyname.aspx)?
值得注意的是:這個屬性是DataGridView的列所擁有的,非DataGridView本身。故名思意,就是用來指定DataGridView中哪一列顯示數據源對象的哪一個屬性。您可以通過VS的設計器方便地進行這個屬性的設置,如下圖:
進行了如上圖的設置,我們就能得到如下圖的正確結果了:
同樣的,在將數據表綁定到DataGridView時也可以如此操作。
現在,我們試著增加難度,將員工對應打卡記錄的簽到信息顯示出來。不少會舉一反三的朋友可能會進行如下操作:
事實證明,這樣是不行的……
這種做法是不被支持的。
另外一個問題其實我們也希望一并解決:性別,我們肯定希望是顯示中文的男和女。怎么做呢?其實有一個事件可以做:
?、跼owsAdded 事件(參見http://msdn.microsoft.com/zh-cn/library/system.windows.forms.datagridview.rowsadded(VS.80).aspx)(不保證有更簡易的做法)
? 這個事件是當當前DataGridView中添加一行或多行數據時發生的。
它的用法如下:
1 // DataGridView.RowsAdded事件使用2 private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
3 {
4 // string str = "";
5 for (int i = e.RowIndex; i < e.RowIndex + e.RowCount; i++)
6 {
7 // str += dataGridView1.Rows[i].Cells[2].Value.ToString() + " ";
8 }
9 // MessageBox.Show(str);
10 }
值得注意的是:該事件并不是向DataGridView中添加一行被執行一次,有可能第一次添加一項,第二次添加三項、或者一項、或者剩余的全部……
而且并不是第一次添加過第二次就不會添加……
總之就是沒有規律……
那么我們可以通過從e.RowIndex(當前添加的第一行的索引)到 e.RowIndex + e.RowCount (已經添加項數)的次數的循環,并且通過變化的e.RowIndex的值取得真正被添加的行進行操作。
看看我們如何將Female和Male替換為對應中文的:
1 private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)2 {
3 // 如果能通過對象拿到性別,可以采用如下做法顯示對應中文
4
5 // 取消對列屬性的綁定
6 Column4.DataPropertyName = null;
7
8 for (int i = e.RowIndex; i < e.RowIndex + e.RowCount; i++)
9 {
10 // 通過行(或項)的綁定對象拿到性別
11 dataGridView1.Rows[i].Cells[Column4.Index].Value = // 判斷該如何顯示,此處的DataBoungItem相當于Tag是在綁定數據源時自動綁定的(當然,它是只讀的……)
12 (dataGridView1.Rows[i].DataBoundItem as SE).Sex == Gender.Female ? "女" : "男";
13 }
14 }
善于利用控件的屬性和事件會讓我們的開發事半功倍!?
?
?
?
轉載于:https://www.cnblogs.com/Johness/archive/2012/03/30/2424315.html
總結
以上是生活随笔為你收集整理的WinForm编程数据视图之DataGridView浅析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows常用软件列表(2012.0
- 下一篇: 温故