前言

datagridview是开发winform的一个列表展示,类似于表格。学会下面的基本特征用法,再辅以经验,基本功能开发没问题。

基本的数据渲染

根据提供的数据展示出效果。

提供给datagridview数据源有很多方式,大致有如下三种:

直接增加,每个单元格类型都是datagridviewtextboxcell

int index=this.datagridview1.rows.add();
this.datagridview1.rows[index].cells[0].value = "1";
this.datagridview1.rows[index].cells[1].value = "2";
this.datagridview1.rows[index].cells[2].value = "3";

直接增加一行,在行上的每天单元格内添加数据,缺点是太单一

直接增加,但我们可以指定单元格类型

datagridviewrow row = new datagridviewrow();
datagridviewtextboxcell textboxcell = new datagridviewtextboxcell();
textboxcell.value = "aaa";
row.cells.add(textboxcell);
datagridviewcomboboxcell comboxcell = new datagridviewcomboboxcell();
row.cells.add(comboxcell);
datagridview1.rows.add(row);

可选的类型如下图:

使用vo对象

上面2种都不是我想要的,因为列表展示的数据大部分情况下是复杂的后台回传的数据。所以我建议使用vo。
新建infovo.cs类

public class infovo
 {
  /// <summary>
  /// 
  /// </summary>
  public string uiditem { get; set; }
  /// <summary>
  /// 
  /// </summary>
  public string uiditemrevision { get; set; }
  /// <summary>
  /// 
  /// </summary>
  public string primarytag { get; set; }
 }

构造一个list,将infovo放进list对象里,然后将list对象赋值给datagridview.datasource即可。
在窗体的load事件里添加如下代码

private void searchinfo_load(object sender, eventargs e)
  {
  	list<infovo> list = new list<infovo>();
    list.add(new infovo(){ uiditem="1", uiditemrevision ="1", primarytag ="1"});
    list.add(new infovo(){ uiditem="2", uiditemrevision ="2", primarytag ="2"});
    datagridview.autogeneratecolumns = false;
    datagridview.datasource = null;
    datagridview.datasource = list;
  }

直接赋值datagridview.datasource = list即可。这里的autogeneratecolumns是禁止datagridview自动根据vo属性创建列。

在窗体上选中datagridview,在属性面板里点击columns选项。如下图

在打开的面板里,我们可以创建列。选择是否可见,设置抬头
datapropertyname:指定列绑定的数据源属性字段。
在dolumntype里我们可以指定单元格类型,如下图

比如下拉框,或者单元框。
至此,我们可以渲染出datagridview组件里,下面看一些属性。

datagridview

列宽自适应

foreach (datagridviewcolumn column in datagridview.columns)
 {
  column.autosizemode = datagridviewautosizecolumnmode.allcells;
 }

成员名称 说明
notset 列的大小调整行为从datagridview.autosizecolumnsmode 属性继承。
none 列宽不会自动调整。
allcells 调整列宽,以适合该列中的所有单元格的内容,包括标题单元格。
allcellsexceptheader 调整列宽,以适合该列中的所有单元格的内容,不包括标题单元格。
displayedcells 调整列宽,以适合当前屏幕上显示的行的列中的所有单元格的内容,包括标题单元格。
displayedcellsexceptheader 调整列宽,以适合当前屏幕上显示的行的列中的所有单元格的内容,不包括标题单元格。
columnheader 调整列宽,以适合列标题单元格的内容。
fill 调整列宽,使所有列的宽度正好填充控件的显示区域,只需要水平滚动保证列宽在datagridviewcolumn.minimumwidth属性值以上。相对列宽由相对datagridviewcolumn.fillweight属性值决定。

如果想让列宽能按比例填充显示区域则 column.autosizemode = datagridviewautosizecolumnmode.fill;

禁止缩放单元格大小

2个属性

  • allowusertoresizecolumns:true:禁止缩放列
  • allowusertoresizerows:true:禁止缩放行

用户自定义列的顺序

用户可以拖动的方式排序列展示
allowusertoordercolumns:true

是否可以编辑单元格

  • 窗体的readonly为false
  • 在columns弹出的列编辑窗口里,选择列的readonly为false
  • selectionmode为rowreadselect(这是默认值)

行头,列头不显示

在属性面板里选中rowheadersvisible和columnheadersvisible,置为false

列表显示不完全,必需鼠标移到组件上才能显示的bug

将rowheadersvisible置为false即可。

行头显示行号

为rowstatechanged事件添加监听,(在属性面板右边闪电图标下找)。

private void datagridview1_rowstatechanged(object sender, datagridviewrowstatechangedeventargs e)
{
 //显示在headercell上
 for (int i = 0; i < this.datagridview1.rows.count; i++)
 {
  datagridviewrow r = this.datagridview1.rows[i];
  r.headercell.value = string.format("{0}", i + 1);
 }
 this.datagridview1.refresh();
}

行号没有完全显示出来的解决办法是将datagridview的rowheaderswidthsizemode属性设置为autosizetoallheaders、autosizetodisplayedheaders或者autosizetofirstheader。

禁止自动创建列

如果我们提供的vo对象,datagrid会自动根据属性创建列,这不是我想要的,我希望能控制显示。如下设置即可
datagridview.autogeneratecolumns = false;

修改单元格类型

单元格可以显示文件,也可以显示单元框,下拉框,图片和超链拉。只要在编辑列窗口里选择columntype下拉框,选择一下即可。当然选择的不同,数据设置不同,比如
单选框datagridviewcheckboxcolumn如下

下拉框datagridviewcomboboxcolumn

选中模式

可以指定选中是整个行被选中还是每个小单元格被选中
selectionmode,全部可选如下

其它

当然还有其它,只要我们熟悉,在属性面板上几乎都能找到。

选中事件

cellclick是选中事件,不用它即可,不要用cellcontentclick,因为如果单元格无内容,这个cellcontentclick事件不会触发。

取得当前单元格内容 :datagridview1.currentcell.value
取得当前单元格的列 index:datagridview1.currentcell.columnindex
取得当前单元格的行 index:datagridview1.currentcell.rowindex
取得当前行:datagridview.currentrow;
获得绑定的vo

datagridviewrow datagridviewrow = datagridview.currentrow;
   infovo infovo = datagridviewrow.databounditem as infovo ;
   infovo .uiditemrevision ;

如果表格可编辑,那么编辑完表格会同步更新databounditem绑定的vo对象

遍历列表里所有单元格

	foreach (datagridviewrow item in datagridview.rows)
   {
     //item是每行的对象,cells是单元格集合
    if (null != item.cells[0].value && (boolean)item.cells[0].value)
    {
			item.cells[0].value.tostring();
		}
	}

使用 datagridview.currentcelladdress 属性(而不是直接访问单元格)来确定单元格所在的
行: datagridview.currentcelladdress.y
列: datagridview.currentcelladdress.x 。

当前的单元格可以通过设定 datagridview 对象的 currentcell 来改变。可以通过 currentcell 来设定
datagridview 的激活单元格。将 currentcell 设为 nothing(null) 可以取消激活的单元格。

datagridview datagridviewcheckboxcolumn编辑时实时触发事件

正常响应cellvaluechanged()事件时,当改变checkbox状态时,只有当焦点离开该单元格时才能触发cellvaluechanged()事件,

如果要改变checkbox值时实时触发cellvaluechanged()事件,需要借用currentcelldirtystatechanged()事件来提交未提交控件的更改。

private void datagridview1_currentcelldirtystatechanged(object sender, eventargs e)
  {
   if (datagridview1.iscurrentcelldirty)
   {
    datagridview1.commitedit(datagridviewdataerrorcontexts.commit);
   }
  }

事实上,当调用datagridview1.commitedit(datagridviewdataerrorcontexts.commit);时,就提交了当前的修改,很多其它事件都会有响应,其中cellvaluechanged就是其中之一。
这样cellvaluechanged()事件就可以随着checkbox的值的改变实时触发。
以全选/反选为例说明当datagridviewcheckboxcolumn发生变化时怎么处理全选/反选。
checkbox有3种状态:选中(checkstate.checked)/取消(checkstate.unchecked)/部分选中(checkstate.indeterminate)
在winform组件里拖拽一个checkbox命名为selectallcheckbox,text为全选,拖拽一个linklabel命名为revselectlinklbl,text为反选。

 //全选
  private void selectallcheckbox_checkedchanged(object sender, eventargs e)
  {
   checkbox c = sender as checkbox;
   if(c.checkstate == checkstate.checked)
   {
    changedatasourcechecked(true);
   }
   else if(c.checkstate == checkstate.unchecked)
   {
    changedatasourcechecked(false);
   }
  }

  private void changedatasourcechecked(boolean isselected)
  {
   foreach (saveplmbomresponsevo saveplmbomresponsevo in datasource)
   {
    saveplmbomresponsevo.checkedc = isselected;
   }
   datagridview.datasource = null;
   datagridview.datasource = datasource;
  }
  /// <summary>
  /// 反选
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  private void revselectlinklbl_linkclicked(object sender, linklabellinkclickedeventargs e)
  {
   if (this.selectallcheckbox.checkstate == checkstate.checked)
   {
    this.selectallcheckbox.checkstate = checkstate.unchecked;
   }
   else if(this.selectallcheckbox.checkstate == checkstate.unchecked)
   {
    this.selectallcheckbox.checkstate = checkstate.checked;
   }
   else
   {
    //部分选中
    foreach (saveplmbomresponsevo saveplmbomresponsevo in datasource)
    {
     if (saveplmbomresponsevo.checkedc)
     {
      saveplmbomresponsevo.checkedc = false;
     }
     else
     {
      saveplmbomresponsevo.checkedc = true;
     }
    }
    datagridview.datasource = null;
    datagridview.datasource = datasource;
   }
  }

  /// <summary>
  /// 处理datasource数据变化时,全选/反选选中状态
  /// </summary>
  private void calselectallcheckboxstate()
  {
   int selectedcount = 0;
   foreach (saveplmbomresponsevo saveplmbomresponsevo in datasource)
   {
    if (saveplmbomresponsevo.checkedc)
    {
     ++selectedcount;
    }
   }
   if (selectedcount == 0)
   {
    if(this.selectallcheckbox.checkstate != checkstate.unchecked)
    {
     this.selectallcheckbox.checkstate = checkstate.unchecked;
    }
   }
   else if (selectedcount == datasource.count)
   {
    if (this.selectallcheckbox.checkstate != checkstate.checked)
    {
     this.selectallcheckbox.checkstate = checkstate.checked;
    }
   }
   else
   {
    if (this.selectallcheckbox.checkstate != checkstate.indeterminate)
    {
     this.selectallcheckbox.checkstate = checkstate.indeterminate;
    }
   }
  }

  /// <summary>
  /// 提交修改状态
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  private void datagridview_currentcelldirtystatechanged(object sender, eventargs e)
  {
   if (this.datagridview.iscurrentcelldirty)
   {
    this.datagridview.commitedit(datagridviewdataerrorcontexts.commit);
   }
  }

  //行值变化
  private void datagridview_cellvaluechanged(object sender, datagridviewcelleventargs e)
  {
   calselectallcheckboxstate();
  }

到此这篇关于c#开发winform之datagridview开发详解的文章就介绍到这了,更多相关c# datagridview开发内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!