【摘要】 DataGridView是一個(gè)非常實(shí)用的顯示和編輯多行數(shù)據(jù)的控件,通過對它進(jìn)行適當(dāng)?shù)臄U(kuò)展后,使它可以智能地根據(jù)數(shù)據(jù)源的基礎(chǔ)類型有選擇地自動生成列,如果想要對顯示的列集進(jìn)行變動,只要修改邏輯層中對應(yīng)的基礎(chǔ)類型的屬性即可,表現(xiàn)層不要作任何修改,大大地提高了工作效率,而且避免了出錯(cuò)的可能,這完全符合代碼和表現(xiàn)分離的設(shè)計(jì)理念。
【關(guān)鍵詞】 智能生成列 C# 組件 DataGridView 泛型函數(shù) 反射
一、引言
NET Framework 類庫提供的 DataGridView 控件,可以顯示和編輯來自多種不同類型的數(shù)據(jù)源的表格數(shù)據(jù)。深受編程人員的喜愛。它有兩種生成列集的方式:當(dāng)AutoGenerateColumns設(shè)置為false時(shí)(此為默認(rèn)設(shè)置),由用戶手動生成列集,當(dāng)AutoGenerateColumns設(shè)置為true時(shí),由DataGridView根據(jù)數(shù)據(jù)源自動生成列集。第二種方式簡單方便,但它是無選擇地將數(shù)據(jù)源所有的列對象都顯示出來,在很多場合下是不符合用戶的要求的。第一種方式雖然靈活有選擇,但必須逐個(gè)地生成每一個(gè)列對象,很麻煩,當(dāng)數(shù)據(jù)源的列對象數(shù)比較大時(shí)更是如此,而且當(dāng)數(shù)據(jù)源的列對象名稱有變化時(shí),還必須得手動更新DataGridView的列集中對應(yīng)的列,不僅費(fèi)時(shí)費(fèi)力,而且很容易出錯(cuò)。
二、思路
為了讓DataGridView能夠識別哪些列需要顯示,哪些列不需要顯示,可在給數(shù)據(jù)源的基礎(chǔ)類型的列屬性取名時(shí)做好特別的記號。筆者是讓需要顯示的列屬性的名稱前面加上由下劃線分隔的前綴。如下所示,Empolyee有兩個(gè)公開屬性,其中 “P_是否在崗”這個(gè)列屬性有前綴”P”表示需要生成列對象進(jìn)行顯示,“籍貫”這列屬性沒有前綴表示不需要顯示:
public class Empolyee
{
private Boolean _是否在崗;
public Boolean P_是否在崗
{
get { return _是否在崗; }
set { _是否在崗 = value; }
}
private string _籍貫 = "";
public string 籍貫
{
get { return _籍貫; }
set
{
if (_籍貫 != value)
{
_籍貫 = value;
}
}
}
}
然后創(chuàng)建一個(gè)組件,讓這個(gè)組件繼承自DataGridView并擴(kuò)展一個(gè)泛型函數(shù)GenerateColumns
將這個(gè)組件編譯成DLL類庫以便重復(fù)使用。
三、應(yīng)用實(shí)例
本文以Microsoft Visual Studio 2005集成環(huán)境中的C#語言為例,說明具體操作技術(shù)。
新建一個(gè)項(xiàng)目,選擇”類庫”模板,且項(xiàng)目取名為”MyLibrary”,然后添加對 “System.Windows.Forms”和” System.Drawing”的引用,最后將其中代碼改成如下內(nèi)容并生成類庫文件MyLibrary.dll備用,然后關(guān)閉包含此項(xiàng)目的解決方案。
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Reflection;
using System.Windows.Forms;
using System.Drawing;
namespace MyToolsBox
{
///
public partial class MyDataGridView : DataGridView
{
public MyDataGridView()
{
InitializeComponent();
this.AutoGenerateColumns = false;
}
///
/// 屬性名稱必須是由下劃線相連的兩部分組成的
/// 第二部分(建議用漢字)將成為生成列的標(biāo)題
/// 如果是布爾型,則使用DataGridViewCheckBoxColumn列
/// 如果是日期型,則使用自定義的CalendarColumn列
/// 其它類型,則使用DataGridViewTextBoxColumn列
///
public void GenerateColumns
{
DataGridViewColumn col;
Type MyType = typeof(T);
PropertyInfo[] Mypropertyinfo = MyType.GetProperties();
foreach (PropertyInfo n in Mypropertyinfo)
{
int x = n.Name.IndexOf('_');
if (x > 0 && x + 1 < n.Name.Length)//有前綴
{
if (n.PropertyType == typeof(System.Boolean))
col = new DataGridViewCheckBoxColumn();
else if (n.PropertyType == typeof(System.DateTime))
col = new CalendarColumn();//此句使用了筆者自定義的日期類型列CalendarColumn,必須在類庫中包含了對它的定義,讀者在調(diào)試時(shí)可將此行注釋
else
col = new DataGridViewTextBoxColumn();
col.Name =
col.DataPropertyName = n.Name;
col.HeaderText = n.Name.Substring(x + 1);
this.Columns.Add(col);
}
}
}
}
}
再新建一個(gè)項(xiàng)目, 選擇”Windows 應(yīng)用程序”模板,且將項(xiàng)目取名為”Demo” ,在此項(xiàng)目中,添加一個(gè)”新建項(xiàng)”,選擇”類”模板,并取名為Empolyee,然后將類代碼改成如下內(nèi)容:
namespace Demo
{
public class Empolyee
{
private string _檔案編號 = "";
public string P_檔案編號
{
get { return _檔案編號; }
}
private string _姓名 = "";
public string P_姓名
{
get { return _姓名; }
}
private string _工作單位 = "";
public string P_工作單位
{
get { return _工作單位; }
}
private DateTime _出生日期 = System.DateTime.Now.Date;
public DateTime P_出生日期
{
set
{
if (_出生日期 != value)
_出生日期 = value;
}
get { return _出生日期;}
}
private string _移動電話 = "";
public string P_移動電話
{
get { return _移動電話; }
set
{
if (_移動電話 != value)
{
_移動電話 = value;
}
}
}
private Boolean _是否在崗;
public Boolean P_是否在崗
{
get { return _是否在崗; }
set { _是否在崗 = value; }
}
private string _籍貫 = "";
public string 籍貫
{
get { return _籍貫; }
set
{
if (_籍貫 != value)
{
_籍貫 = value;
}
}
}
///
///
static public List
{
List
Empolyee t = new Empolyee();
t._檔案編號 = "200018";
t._姓名 = "汪瑩";
t._工作單位 = "黎川縣職業(yè)中專";
t._出生日期 = System.DateTime.Parse("1984-01-01");
t._移動電話 = "13812345678";
t._籍貫 = "江西省黎川縣";
list.Add(t);
return list;
}
}
}
在項(xiàng)目中添加對剛才生成的“MyLibrary.dll”的引用。
在項(xiàng)目中打開Form1.cs[設(shè)計(jì)]界面,右擊工具箱,在彈出的快捷菜單中執(zhí)行”添加選項(xiàng)卡”命令,并將新生成的選項(xiàng)卡命名為”MyToolsBox”,然后將“MyLibrary.dll”文件拖動到此選項(xiàng)卡中,此時(shí)在工具箱中可以看到”MyToolsBox”選項(xiàng)卡中有一個(gè)組件”MyDataGridView”,從工具箱中拖動這個(gè)組件到Form1的窗體中,并適當(dāng)調(diào)整大小與位置。
最后將其中Form1.cs的代碼改成如下內(nèi)容并生成文件Demo.exe文件:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace Demo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//智能生成列集 this.myDataGridView1.GenerateColumns
//獲取演示數(shù)據(jù) this.myDataGridView1.DataSource = Demo.Empolyee.GetDemoList();
this.myDataGridView1.ReadOnly = false;
}
}
}
開始執(zhí)行,可看到如下的畫面。從中可以看到Empolyee的7個(gè)公開屬性,只顯示了其中的六個(gè),“籍貫”這個(gè)屬性由于其名稱中不包含用下劃線分隔的前綴,因此沒有在畫面中出現(xiàn):
四、小結(jié)
DataGridView是一個(gè)非常實(shí)用的顯示和編輯多行數(shù)據(jù)的控件,通過對它進(jìn)行適當(dāng)?shù)臄U(kuò)展后,使它可以智能地根據(jù)數(shù)據(jù)源的基礎(chǔ)類型有選擇地自動生成列,如果想要對顯示的列集進(jìn)行變動,只要修改邏輯層中對應(yīng)的基礎(chǔ)類型的屬性即可,表現(xiàn)層不要作任何修改,大大地提高了工作效率,而且避免了出錯(cuò)的可能,這完全符合代碼和表現(xiàn)分離的設(shè)計(jì)理念。