学习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. 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. 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. 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. 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. 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. 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. 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浅析的更多相关文章

  1. 在VS2005编程中,有的时候DataGridView数据源有几个表的联合查询,而系统又有限制为一个表,怎么办?

    在VS2005编程中,有的时候DataGridView数据源有几个表的联合查询,而系统又有限制为一个表,怎么办? 解决方法:在SqlServer的企业管理器里增加一个视图吧!!!!!!!!(从来没用过 ...

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

    在SharePoint中,我们经常需要对列表进行简单的筛选,这时,数据视图就有作用了,我们可以定制对于字段的筛选,来进行展示:特别的,筛选不同于搜索,并没有对于附件或者文档的全文检索,如果需要全文检索 ...

  3. SharePoint 2013 Designer系列之数据视图

    在SharePoint使用中,数据展示是一块很重要的部分,很多时候我们会采用webpart的形式,但是有一些情况,我们不必使用开发,仅需使用Designer即可,下面让我简单介绍下数据视图的使用. 1 ...

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

    Atitit..组件化事件化的编程模型--(2)---------Web datagridview 服务器端控件的实现原理and总结 1. 服务端table控件的几个流程周期 1 1.1. 确认要显示 ...

  5. ADO.NET事务处理,初始回调函数,多张表的数据在同一个DataGridView中展示

    执行ADO.NET事务包含四个步骤,接下来以Transaction对象为例介绍. (1)调用SQLConnection对象的BeginTransaction()方法,创建一个SQLTransactio ...

  6. DataGridView绑定数据库,取得的数据插入到DataGridView指定列(一)

    实现: 点击button1,从数据库中获得数据,指定数据库的某列数据插入到DataGridView指定列 一.双击button1进入事件代码 private void button1_Click(ob ...

  7. SharePoint开发 - Excel数据导入到SharePoint自定义列表(数据视图方式)

    博客地址 http://blog.csdn.net/foxdave 本篇讲解一个有些新颖的SharePoint实例应用,给甲方做过项目的都有过体会,数据太多了,客户有Excel,要求实现批量导入. 效 ...

  8. C# winform编程中多线程操作控件方法

    private void Form1_Load(object sender, EventArgs e) { Thread newthread = new Thread(new ThreadStart( ...

  9. C#使用oledb方式将excel数据导入到datagridview后数据被截断为 255 个字符

    问题描述:在使用oledb方式将excel数据导入到datagridview中,在datagridview单元格中的数据没有显示全,似乎只截取了数据源中的一段 解决方案:1.关于该问题,微软官方答案: ...

随机推荐

  1. 【转载】菜鸟Ubuntu下安装Android Studio

    原文:http://forum.android-studio.org/forum.php?mod=viewthread&tid=236&extra=page%3D1%26filter% ...

  2. iOS 删除 Main.storyboard 和 LaunchScreen.storyboard

    第一步: 右键选中Main.storyboard —- delete —— Move to Trash LaunchScreen同理 第二步 点击工程名,就是最顶级目录 右侧出现general选项卡 ...

  3. Objective-C之@类别小实例

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  4. MySql下载安装(Mac平台) 终端启动 XMAPP启动

    1,下载 2,点击MySQL Community Server之后,然后看到需要注册登录的节目,我们就点击最下面just start my download直接下载.懒的注册或者登陆: 3.下载后,& ...

  5. 深入理解java虚拟机(1)------内存区域与内存溢出

    在C++领域,关于C++的内存存储,结构等等,有一本书:深度探索C++对象模型,讲解的非常透彻. 而Java确把这一工作交给了虚拟机来处理. 我们首先来看看关于内存的问题. 1.问题: 1)java ...

  6. URL、表单数据、IP等处理类

    <?php class ev { public $cookie; public $post; public $get; public $file; public $url; public $G; ...

  7. 如何在Java Filter 中注入 Service

    在项目中遇到一个问题,在 Filter中注入 Serivce失败,注入的service始终为null.如下所示: public class WeiXinFilter implements Filter ...

  8. 在MVC3中使用code first生成数据局库并操作数据库

    1.建立Users和UserInfos两个实体类 对应的是数据库中的表 public class User { //类名+Id(User+Id)组成的字符串在数据库表中会设置该字段是主键且是按1的增量 ...

  9. 使用DateLocaleConverter和SimpleDateFormat实现字符串转换成日期

    使用DateLocaleConverter: public static void change() { String birthday = "1990-12-32"; DateL ...

  10. runv start container 流程分析

    1.runv/start.go func startContainer(context *cli.Context, container, address string, config *spec.Sp ...