- A+
在用 winform 的时候,我们操作表格数据一般使用 GridView 会比较多,这里我总结下我在使用的过程中遇到的一些问题
一、首先创建窗体和表格,将表格简单设置一下,去除最后一行编辑行,去除默认的第一列空白列,将背景设置为白色
AllowUserToAddRows 去除最后一行编辑行
RowHeadersVisible 去除默认的第一列空白列
BackgroudColor 将表格背景设为其他颜色
二、读取数据很简单 DataSource 可以接受 DataTable 或者 List 等数据格式
一般我们每行数据后面会有一个操作列,那么在使用操作列时,这里提供两种方法,一种使用代码添加,一种使用表格属性添加
第一种,表格属性添加,保存后,就会出现一个操作列,按钮的显示文本一定要在 DefaultCellStyle 中设置,然后打开 GridView 的属性,添加 CellContentClick 事件,给按钮一个事件
1 private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) 2 { 3 if (this.dataGridView1.Columns[e.ColumnIndex].Name == "Column10") 4 { 5 //获取当前数据 ID 6 int id = Convert.ToInt32(this.dataGridView1.Rows[e.RowIndex].Cells[1].Value); 7 8 MessageBox.Show($"当前数据ID:{id}"); 9 } 10 }
第二种,使用代码添加按钮,添加完成后,同样也要给一个事件,事件的方法同第一种一样,这里就不重复贴代码了
1 dataGridView2.DataSource = dt; 2 3 //创建按钮 4 DataGridViewButtonColumn btnOpenFile = new DataGridViewButtonColumn(); 5 btnOpenFile.Name = "SelectDetail"; 6 btnOpenFile.HeaderText = "查看详情"; 7 btnOpenFile.DefaultCellStyle.NullValue = "查看详情"; 8 dataGridView2.Columns.Add(btnOpenFile); 9 10 //加载按钮点击事件 11 dataGridView2.CellContentClick += DataGridView2_CellContentClick;
那么我们开始为什么加一个 tabControl 的控件呢?这里是为了演示一个问题,我们在切换两个 tab 的时候,实际上时每次都去读取数据并显示,那么就会出现一个问题,使用代码添加的按钮,会重复出现多次按钮,因为每次加载时都会创建按钮(有可能有解决方案,但是我这里没查到,欢迎评论留言解决方案)。而使用表格属性添加的按钮则不会。
我们这里在加个常用功能,增加 CheckBox 选择数据并删除
这里只需要增加一个 CheckBox 类型的列就行了
选择数据后点击删除按钮
private void button1_Click(object sender, EventArgs e) { int count = 0; //获取选择数据的条数 for (int i = 0; i < this.dataGridView1.RowCount; i++) { if (this.dataGridView1.Rows[i].Cells[0].EditedFormattedValue.ToString() == "TRUE") { count++; } } if (count == 0) { MessageBox.Show("请选择数据"); return; } else { //定义泛型list IList list = null; List<FileData> list1 = new List<FileData>(); for (int i = 0; i < this.dataGridView1.RowCount; i++) { if (this.dataGridView1.Rows[i].Cells[0].EditedFormattedValue.ToString() == "TRUE") { //赋值给泛型list list = (IList)this.dataGridView1.DataSource; //将数据从泛型list删除 list.RemoveAt(this.dataGridView1.CurrentRow.Index); } } //遍历泛型Gridview数据 foreach (var item in list)
{
//var obj = new { ClientId = 7, ClientName = "ACME Inc.", Jobs = 5 }; System.Type types = item.GetType(); string path = (string)types.GetProperty("Path").GetValue(item, null); double size = (double)types.GetProperty("Size").GetValue(item, null); string type = (string)types.GetProperty("Type").GetValue(item, null); string name = (string)types.GetProperty("Name").GetValue(item, null); //添加至新的list里 list1.Add(new FileData() { Size = size, Path = path, Type = type, Name = name }); } //将新的list内容赋值给旧的对象 listFile = list1; //this.dataGridView1.DataSource = null; //重新给gridview赋值,不可清空gridview在赋值,会出现格式数据被清除 this.dataGridView1.DataSource = listFile.Select(group => new { Size = group.Size, Path = group.Path, Type = group.Type, Name = group.Name }).ToList(); } }
我这里的做法是,将 DataSource 直接赋值给一个泛型的List对象,然后通过这个泛型List删除 数据,最后将泛型List转为对应的显示数据对象,如果不转成对应的对象,就会出现列头的直接显示为你的数据库表字段名
下面是全选,反选的方法
/// <summary> /// 全选 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button5_Click(object sender, EventArgs e) { for (int i = 0; i < this.dataGridView1.Rows.Count; i++) { this.dataGridView1.Rows[i].Cells[0].Value = "TRUE"; } } /// <summary> /// 反选 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button6_Click(object sender, EventArgs e) { for (int i = 0; i < this.dataGridView1.Rows.Count; i++) { if (Convert.ToString(this.dataGridView1.Rows[i].Cells[0].Value) == "TRUE") this.dataGridView1.Rows[i].Cells[0].Value = "FALSE"; else this.dataGridView1.Rows[i].Cells[0].Value = "TRUE"; } }