C#开发WinForm之DataGridView开发

男娘i 2022-04-13 12:49 1144阅读 0赞

C#开发WinForm之DataGridView开发

文章目录

    • C#开发WinForm之DataGridView开发
  • 前言
  • 基本的数据渲染
    • 直接增加,每个单元格类型都是DataGridViewTextBoxCell
    • 直接增加,但我们可以指定单元格类型
  • 使用vo对象
  • dataGridView
    • 列宽自适应
    • 禁止缩放单元格大小
    • 用户自定义列的顺序
    • 是否可以编辑单元格
    • 行头,列头不显示
    • 列表显示不完全,必需鼠标移到组件上才能显示的bug
    • 行头显示行号
    • 禁止自动创建列
    • 修改单元格类型
    • 选中模式
    • 其它
  • 选中事件
  • DataGridView DataGridViewCheckBoxColumn编辑时实时触发事件

前言

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

基本的数据渲染

根据提供的数据展示出效果。
提供给DataGridView数据源有很多方式,大致有如下三种:

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

  1. int index=this.dataGridView1.Rows.Add();
  2. this.dataGridView1.Rows[index].Cells[0].Value = "1";
  3. this.dataGridView1.Rows[index].Cells[1].Value = "2";
  4. this.dataGridView1.Rows[index].Cells[2].Value = "3";

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

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

  1. DataGridViewRow row = new DataGridViewRow();
  2. DataGridViewTextBoxCell textboxcell = new DataGridViewTextBoxCell();
  3. textboxcell.Value = "aaa";
  4. row.Cells.Add(textboxcell);
  5. DataGridViewComboBoxCell comboxcell = new DataGridViewComboBoxCell();
  6. row.Cells.Add(comboxcell);
  7. dataGridView1.Rows.Add(row);

可选的类型如下图:

在这里插入图片描述

使用vo对象

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

  1. public class InfoVo
  2. {
  3. /// <summary>
  4. ///
  5. /// </summary>
  6. public string uidItem { get; set; }
  7. /// <summary>
  8. ///
  9. /// </summary>
  10. public string uidItemRevision { get; set; }
  11. /// <summary>
  12. ///
  13. /// </summary>
  14. public string primaryTag { get; set; }
  15. }

构造一个List,将InfoVo放进List对象里,然后将List对象赋值给dataGridView.DataSource即可。
在窗体的Load事件里添加如下代码

  1. private void SearchInfo_Load(object sender, EventArgs e)
  2. {
  3. List<InfoVo> list = new List<InfoVo>();
  4. list.Add(new InfoVo(){ uidItem="1", uidItemRevision ="1", primaryTag ="1"});
  5. list.Add(new InfoVo(){ uidItem="2", uidItemRevision ="2", primaryTag ="2"});
  6. dataGridView.AutoGenerateColumns = false;
  7. dataGridView.DataSource = null;
  8. dataGridView.DataSource = list;
  9. }

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

在窗体上选中DataGridView,在属性面板里点击Columns选项。如下图
在这里插入图片描述
在打开的面板里,我们可以创建列。选择是否可见,设置抬头
DataPropertyName:指定列绑定的数据源属性字段。
在DolumnType里我们可以指定单元格类型,如下图
在这里插入图片描述
比如下拉框,或者单元框。
至此,我们可以渲染出DataGridView组件里,下面看一些属性。

dataGridView

列宽自适应

  1. foreach (DataGridViewColumn column in dataGridView.Columns)
  2. {
  3. column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
  4. }









































成员名称 说明
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

是否可以编辑单元格

  1. 窗体的ReadOnly为false
  2. 在Columns弹出的列编辑窗口里,选择列的ReadOnly为false
  3. SelectionMode为RowReadSelect(这是默认值)

行头,列头不显示

在属性面板里选中RowheadersVisible和ColumnHeadersVisible,置为false

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

将RowheadersVisible置为false即可。

行头显示行号

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

  1. private void dataGridView1_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
  2. {
  3. //显示在HeaderCell上
  4. for (int i = 0; i < this.dataGridView1.Rows.Count; i++)
  5. {
  6. DataGridViewRow r = this.dataGridView1.Rows[i];
  7. r.HeaderCell.Value = string.Format("{0}", i + 1);
  8. }
  9. this.dataGridView1.Refresh();
  10. }

行号没有完全显示出来的解决办法是将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

  1. DataGridViewRow dataGridViewRow = dataGridView.CurrentRow;
  2. InfoVo infoVo = dataGridViewRow.DataBoundItem as InfoVo ;
  3. infoVo .uidItemRevision ;

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

遍历列表里所有单元格

  1. foreach (DataGridViewRow item in dataGridView.Rows)
  2. {
  3. //item是每行的对象,cells是单元格集合
  4. if (null != item.Cells[0].Value && (Boolean)item.Cells[0].Value)
  5. {
  6. item.Cells[0].Value.toString();
  7. }
  8. }

使用 DataGridView.CurrentCellAddress 属性(而不是直接访问单元格)来确定单元格所在的
行: DataGridView.CurrentCellAddress.Y
列: DataGridView.CurrentCellAddress.X 。

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

DataGridView DataGridViewCheckBoxColumn编辑时实时触发事件

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

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

  1. private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
  2. {
  3. if (dataGridView1.IsCurrentCellDirty)
  4. {
  5. dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
  6. }
  7. }

事实上,当调用dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);时,就提交了当前的修改,很多其它事件都会有响应,其中CellValueChanged就是其中之一。
这样CellValueChanged()事件就可以随着checkbox的值的改变实时触发。
以全选/反选为例说明当DataGridViewCheckBoxColumn发生变化时怎么处理全选/反选。
CheckBox有3种状态:选中(CheckState.Checked)/取消(CheckState.Unchecked)/部分选中(CheckState.Indeterminate)
在winForm组件里拖拽一个CheckBox命名为selectAllCheckBox,Text为全选,拖拽一个LinkLabel命名为revSelectLinkLbl,Text为反选。

  1. //全选
  2. private void selectAllCheckBox_CheckedChanged(object sender, EventArgs e)
  3. {
  4. CheckBox c = sender as CheckBox;
  5. if(c.CheckState == CheckState.Checked)
  6. {
  7. ChangeDataSourceChecked(true);
  8. }
  9. else if(c.CheckState == CheckState.Unchecked)
  10. {
  11. ChangeDataSourceChecked(false);
  12. }
  13. }
  14. private void ChangeDataSourceChecked(Boolean isSelected)
  15. {
  16. foreach (SavePlmBomResponseVo savePlmBomResponseVo in dataSource)
  17. {
  18. savePlmBomResponseVo.checkedC = isSelected;
  19. }
  20. dataGridView.DataSource = null;
  21. dataGridView.DataSource = dataSource;
  22. }
  23. /// <summary>
  24. /// 反选
  25. /// </summary>
  26. /// <param name="sender"></param>
  27. /// <param name="e"></param>
  28. private void revSelectLinkLbl_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
  29. {
  30. if (this.selectAllCheckBox.CheckState == CheckState.Checked)
  31. {
  32. this.selectAllCheckBox.CheckState = CheckState.Unchecked;
  33. }
  34. else if(this.selectAllCheckBox.CheckState == CheckState.Unchecked)
  35. {
  36. this.selectAllCheckBox.CheckState = CheckState.Checked;
  37. }
  38. else
  39. {
  40. //部分选中
  41. foreach (SavePlmBomResponseVo savePlmBomResponseVo in dataSource)
  42. {
  43. if (savePlmBomResponseVo.checkedC)
  44. {
  45. savePlmBomResponseVo.checkedC = false;
  46. }
  47. else
  48. {
  49. savePlmBomResponseVo.checkedC = true;
  50. }
  51. }
  52. dataGridView.DataSource = null;
  53. dataGridView.DataSource = dataSource;
  54. }
  55. }
  56. /// <summary>
  57. /// 处理DataSource数据变化时,全选/反选选中状态
  58. /// </summary>
  59. private void calSelectAllCheckBoxState()
  60. {
  61. int selectedCount = 0;
  62. foreach (SavePlmBomResponseVo savePlmBomResponseVo in dataSource)
  63. {
  64. if (savePlmBomResponseVo.checkedC)
  65. {
  66. ++selectedCount;
  67. }
  68. }
  69. if (selectedCount == 0)
  70. {
  71. if(this.selectAllCheckBox.CheckState != CheckState.Unchecked)
  72. {
  73. this.selectAllCheckBox.CheckState = CheckState.Unchecked;
  74. }
  75. }
  76. else if (selectedCount == dataSource.Count)
  77. {
  78. if (this.selectAllCheckBox.CheckState != CheckState.Checked)
  79. {
  80. this.selectAllCheckBox.CheckState = CheckState.Checked;
  81. }
  82. }
  83. else
  84. {
  85. if (this.selectAllCheckBox.CheckState != CheckState.Indeterminate)
  86. {
  87. this.selectAllCheckBox.CheckState = CheckState.Indeterminate;
  88. }
  89. }
  90. }
  91. /// <summary>
  92. /// 提交修改状态
  93. /// </summary>
  94. /// <param name="sender"></param>
  95. /// <param name="e"></param>
  96. private void DataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e)
  97. {
  98. if (this.dataGridView.IsCurrentCellDirty)
  99. {
  100. this.dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
  101. }
  102. }
  103. //行值变化
  104. private void DataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
  105. {
  106. calSelectAllCheckBoxState();
  107. }

发表评论

表情:
评论列表 (有 0 条评论,1144人围观)

还没有评论,来说两句吧...

相关阅读