学习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里的重要属性:
①AutoGenerateColumns 属性(请参见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时也可以如此操作。
现在,我们试着增加难度,将员工对应打卡记录的签到信息显示出来。不少会举一反三的朋友可能会进行如下操作:
事实证明,这样是不行的……
这种做法是不被支持的。
另外一个问题其实我们也希望一并解决:性别,我们肯定希望是显示中文的男和女。怎么做呢?其实有一个事件可以做:
③RowsAdded 事件(参见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 }
善于利用控件的属性和事件会让我们的开发事半功倍!
WinForm编程数据视图之DataGridView浅析的更多相关文章
-
在VS2005编程中,有的时候DataGridView数据源有几个表的联合查询,而系统又有限制为一个表,怎么办?
在VS2005编程中,有的时候DataGridView数据源有几个表的联合查询,而系统又有限制为一个表,怎么办? 解决方法:在SqlServer的企业管理器里增加一个视图吧!!!!!!!!(从来没用过 ...
-
SharePoint 2013 Designer系列之数据视图筛选
在SharePoint中,我们经常需要对列表进行简单的筛选,这时,数据视图就有作用了,我们可以定制对于字段的筛选,来进行展示:特别的,筛选不同于搜索,并没有对于附件或者文档的全文检索,如果需要全文检索 ...
-
SharePoint 2013 Designer系列之数据视图
在SharePoint使用中,数据展示是一块很重要的部分,很多时候我们会采用webpart的形式,但是有一些情况,我们不必使用开发,仅需使用Designer即可,下面让我简单介绍下数据视图的使用. 1 ...
-
Atitit..组件化事件化的编程模型--(2)---------Web datagridview 服务器端控件的实现原理and总结
Atitit..组件化事件化的编程模型--(2)---------Web datagridview 服务器端控件的实现原理and总结 1. 服务端table控件的几个流程周期 1 1.1. 确认要显示 ...
-
ADO.NET事务处理,初始回调函数,多张表的数据在同一个DataGridView中展示
执行ADO.NET事务包含四个步骤,接下来以Transaction对象为例介绍. (1)调用SQLConnection对象的BeginTransaction()方法,创建一个SQLTransactio ...
-
DataGridView绑定数据库,取得的数据插入到DataGridView指定列(一)
实现: 点击button1,从数据库中获得数据,指定数据库的某列数据插入到DataGridView指定列 一.双击button1进入事件代码 private void button1_Click(ob ...
-
SharePoint开发 - Excel数据导入到SharePoint自定义列表(数据视图方式)
博客地址 http://blog.csdn.net/foxdave 本篇讲解一个有些新颖的SharePoint实例应用,给甲方做过项目的都有过体会,数据太多了,客户有Excel,要求实现批量导入. 效 ...
-
C# winform编程中多线程操作控件方法
private void Form1_Load(object sender, EventArgs e) { Thread newthread = new Thread(new ThreadStart( ...
-
C#使用oledb方式将excel数据导入到datagridview后数据被截断为 255 个字符
问题描述:在使用oledb方式将excel数据导入到datagridview中,在datagridview单元格中的数据没有显示全,似乎只截取了数据源中的一段 解决方案:1.关于该问题,微软官方答案: ...
随机推荐
-
validate表单验证插件
1.引入validate.js包 <script src="xx/xx/jquery.validate.min.js"></script> 2.表单验证 / ...
-
<;<;<; html编码中js和html编码不一致导致乱码
在html中,有时把编码设置成UTF-8之后,引入js,页面不会有乱码,但是有关js的东西会出现乱码, 大概问题就是js默认编码不是UTF-8, 解决办法:将js文件用记事本打开,在另存为,保存的时候 ...
-
SQL2008根据日志恢复
--创建测试数据库 CREATE DATABASE Db GO --对数据库进行备份 BACKUP DATABASE Db TO DISK='c:\db.bak' WITH FORMAT GO --创 ...
-
C语言排序算法
(1)“冒泡法” 冒泡法大家都较熟悉.其原理为从a[0]开始,依次将其和后面的元素比较,若a[0]>a[i],则交换它们,一直比较到a[n].同理对a[1],a[2],...a[n-1]处理,即 ...
-
从内部剖析C# 集合之--Dictionary
Dictionary和hashtable用法有点相似,他们都是基于键值对的数据集合,但实际上他们内部的实现原理有很大的差异, 先简要概述一下他们主要的区别,稍后在分析Dictionary内部实现的大概 ...
-
PHP中的ob_start() 的使用
1.在PHP编程中, 我们经常会遇到一些直接产生输出的函数, 如passthru(),readfile(), var_dump() 等. 但有时我们想把这些函数的输出导入到文件中,或者先经过处理再输出 ...
-
javascript 之原型理解
最近一直在了解javascript原型的问题,也算是理解了一点,希望把我所理解的,用简单的例子和说明,让更多人清除的去理解javascript原型 1,原型 prototype 是一个什么东西 我们创 ...
-
2.2 sikuli中编程运行
http://www.cnblogs.com/Flint/p/4951703.html a.如果需要指定点击的具体坐标,需要使用click(patten.targetoffset(x, y)). b. ...
-
[JZOJ5511] 送你一个DAG
题目描述: 给出一个 \(n\) 个点 \(m\) 条边的 \(DAG\) 和参数 \(k\). 定义一条经过 \(l\) 条边的路径的权值为 \(l^k\). 对于 \(i = 1-n\), 求出所 ...
-
python 聊天程序(基于UDP)
from threading import Thread from socket import * updSocket = socket(AF_INET,SOCK_DGRAM) updSocket.b ...