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里的重要属性:

  ①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         }

  善于利用控件的属性和事件会让我们的开发事半功倍!

  

  

时间: 2024-10-12 14:06:28

WinForm编程数据视图之DataGridView浅析的相关文章

数据绑定和数据网格视图(DataGridView)控件

数据绑定和数据网格视图(DataGridView)控件 数据网格视图控件,不像我们前面看到的控件,它可以显示多个列,但是,数据必须格式化,使数据网格知道要显示哪一列.有两种实现方法:一个是把数据网格视图绑定到数据表(DataTable),另一个是把网格到绑定对象列表,对象有许多属性,不同的属性就成为网格的列. 下面的例子是一种简单的解决方案,绑定到数据集(DataSet): open System open System.Collections.Generic open System.Confi

Android开发学习笔记:数据存取之SQLite浅析

一.SQLite的介绍 1.SQLite简介 SQLite是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入 式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了.它能够支持 Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如Tcl.PHP.Java.C++..Net等,还有ODBC接口,同样比起 Mysql.PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的

模版与数据视图

模板是sencha touch的基石,先把这句话记着再说-- 没有了模板,就陷入到了html的拼接当中-- 基本模板:Ext.Template 基础模版输出只能遍历store一个个进行输出,太麻烦了 高级模板Ext.XTemplate有更高级的功能,可以用for来自动填充数组中的数据 而数据视图dataview则是将高级模板和store结合起来使用 基本数据视图的使用

WPF数据视图学习

当你绑定集合到ItemsControl,数据视图被安静地在幕后创造.视图位于数据源和绑定控件之间.数据视图是通往数据源的一个窗口.它跟踪当前项目,它支持诸如排序,过滤,和分组特征.这些特征独立于数据对象本身,意味着你能以不同的方式.在窗口的不同部分(或应用的不同部分)绑定相同的数据.例如,你能绑定相同的产品集合到两个不同的列表但是过滤他们显示不同的记录. 视图对象依赖于数据对象的类型.所有的视图派生自CollectionView,但是两个特殊的实现派生自CollectionView:ListCo

Atitit..组件化事件化的编程模型--(2)---------Web datagridview 服务器端控件的实现原理and总结

Atitit..组件化事件化的编程模型--(2)---------Web datagridview 服务器端控件的实现原理and总结 1. 服务端table控件的几个流程周期 1 1.1. 确认要显示的字段(开始渲染) 1 1.2. 确认要显示的title 1 1.3. 格式化 1 2. Render显示级别 1 2.1. 简单化...grid.toHTML(); 1 2.2. 有些设置(title,field) 1 2.3. 完全的的设置(模板机制) 1 3. 服务器端控件跟模板的分离实现 2

关于Android界面编程与视图(View)组件

UI组件--------------->android.widget.* View组件------------->android.view.* 视图(View)组件 所有UI组件都是建立在视图(View)组件.容器(ViewGroup)组件基础之上的. UI组件继承之View组件 ViewGroup----------->作为其他组件的容器使用. ViewGroup包含View组件即 (UI组件---->继承自View组件. ViewGroup组件---->继承自View组件

SharePoint 2013 Designer系列之数据视图筛选

在SharePoint中,我们经常需要对列表进行简单的筛选,这时,数据视图就有作用了,我们可以定制对于字段的筛选,来进行展示:特别的,筛选不同于搜索,并没有对于附件或者文档的全文检索,如果需要全文检索,可以使用列表的垂直搜索功能. 1.新建一个测试页面,然后右键在高级模式下编辑,如下图: 2.在PlaceHolderMain节点里,加入webpartzone,用来添加数据视图: 3.数据视图选择News列表,如下图: 4.列表视图就选择第一个就可以了,如下图: 5.查看测试页面,如下图: 6.在

tableau desktop(三)--构建数据视图(二)

前段时间忙于工作的事情,好久没有来记录一点东西了,今天利用周末做点记录吧,最近由于工作的原因,也有两三周没有用tableau了.今天继续上一篇构建数据试图(二). 3.7 参考线和参考区间 参考线通常用来标记轴上的某个特定值或区域.例如,当您在分析多种产品的月销售额时,可能需要在平均销售额标记处包含一条参考线,这样可以将每一种产品的业绩与平均值进行比较..或者您可能需要用阴影沿轴标出某一特定区域.最后,您可能需要使用参考线指定某种分布. ableau 不限制添加的参考线条数.使用"添加参考线&q

探索通用可编程数据平面

引言:相比传统网络数据平面,通用可编程数据平面让网络用户可以自定义数据包的完整处理流程,实现理想的协议无关网络数据处理.作为一种理想的SDN数据平面,通用可编程数据平面还不够完善,还需要在不断的尝试中摸索前进. 本文选自<重构网络:SDN架构与实现>. 相比传统网络数据平面,通用可编程数据平面让网络用户可以自定义数据包的完整处理流程,实现理想的协议无关网络数据处理.而当下的OpenFlow模型还无法成为一种完全的通用可编程数据转发模型,还无法实现协议无关的转发.只有实现了真正的通用可编程数据平