让DataGridView智能生成列集
2014-07-29汪莹
【摘要】 DataGridView是一个非常实用的显示和编辑多行数据的控件,通过对它进行适当的扩展后,使它可以智能地根据数据源的基础类型有选择地自动生成列,如果想要对显示的列集进行变动,只要修改逻辑层中对应的基础类型的属性即可,表现层不要作任何修改,大大地提高了工作效率,而且避免了出错的可能,这完全符合代码和表现分离的设计理念。
【关键词】 智能生成列 C# 组件 DataGridView 泛型函数 反射
一、引言
NET Framework 类库提供的 DataGridView 控件,可以显示和编辑来自多种不同类型的数据源的表格数据。深受编程人员的喜爱。它有两种生成列集的方式:当AutoGenerateColumns设置为false时(此为默认设置),由用户手动生成列集,当AutoGenerateColumns设置为true时,由DataGridView根据数据源自动生成列集。第二种方式简单方便,但它是无选择地将数据源所有的列对象都显示出来,在很多场合下是不符合用户的要求的。第一种方式虽然灵活有选择,但必须逐个地生成每一个列对象,很麻烦,当数据源的列对象数比较大时更是如此,而且当数据源的列对象名称有变化时,还必须得手动更新DataGridView的列集中对应的列,不仅费时费力,而且很容易出错。
二、思路
为了让DataGridView能够识别哪些列需要显示,哪些列不需要显示,可在给数据源的基础类型的列属性取名时做好特别的记号。笔者是让需要显示的列属性的名称前面加上由下划线分隔的前缀。如下所示,Empolyee有两个公开属性,其中 “P_是否在岗”这个列属性有前缀”P”表示需要生成列对象进行显示,“籍贯”这列属性没有前缀表示不需要显示:
public class Empolyee
{
private Boolean _是否在岗;
public Boolean P_是否在岗
{
get { return _是否在岗; }
set { _是否在岗 = value; }
}
private string _籍贯 = "";
public string 籍贯
{
get { return _籍贯; }
set
{
if (_籍贯 != value)
{
_籍贯 = value;
}
}
}
}
然后创建一个组件,让这个组件继承自DataGridView并扩展一个泛型函数GenerateColumns
将这个组件编译成DLL类库以便重复使用。
三、应用实例
本文以Microsoft Visual Studio 2005集成环境中的C#语言为例,说明具体操作技术。
新建一个项目,选择”类库”模板,且项目取名为”MyLibrary”,然后添加对 “System.Windows.Forms”和” System.Drawing”的引用,最后将其中代码改成如下内容并生成类库文件MyLibrary.dll备用,然后关闭包含此项目的解决方案。
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;
}
///
/// 属性名称必须是由下划线相连的两部分组成的
/// 第二部分(建议用汉字)将成为生成列的标题
/// 如果是布尔型,则使用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,必须在类库中包含了对它的定义,读者在调试时可将此行注释
else
col = new DataGridViewTextBoxColumn();
col.Name =
col.DataPropertyName = n.Name;
col.HeaderText = n.Name.Substring(x + 1);
this.Columns.Add(col);
}
}
}
}
}
再新建一个项目, 选择”Windows 应用程序”模板,且将项目取名为”Demo” ,在此项目中,添加一个”新建项”,选择”类”模板,并取名为Empolyee,然后将类代码改成如下内容:
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._工作单位 = "黎川县职业中专";
t._出生日期 = System.DateTime.Parse("1984-01-01");
t._移动电话 = "13812345678";
t._籍贯 = "江西省黎川县";
list.Add(t);
return list;
}
}
}
在项目中添加对刚才生成的“MyLibrary.dll”的引用。
在项目中打开Form1.cs[设计]界面,右击工具箱,在弹出的快捷菜单中执行”添加选项卡”命令,并将新生成的选项卡命名为”MyToolsBox”,然后将“MyLibrary.dll”文件拖动到此选项卡中,此时在工具箱中可以看到”MyToolsBox”选项卡中有一个组件”MyDataGridView”,从工具箱中拖动这个组件到Form1的窗体中,并适当调整大小与位置。
最后将其中Form1.cs的代码改成如下内容并生成文件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
//獲取演示数据 this.myDataGridView1.DataSource = Demo.Empolyee.GetDemoList();
this.myDataGridView1.ReadOnly = false;
}
}
}
开始执行,可看到如下的画面。从中可以看到Empolyee的7个公开属性,只显示了其中的六个,“籍贯”这个属性由于其名称中不包含用下划线分隔的前缀,因此没有在画面中出现:
四、小结
DataGridView是一个非常实用的显示和编辑多行数据的控件,通过对它进行适当的扩展后,使它可以智能地根据数据源的基础类型有选择地自动生成列,如果想要对显示的列集进行变动,只要修改逻辑层中对应的基础类型的属性即可,表现层不要作任何修改,大大地提高了工作效率,而且避免了出错的可能,这完全符合代码和表现分离的设计理念。