目录
一、前端界面
二、模块代码
1.初始化列表代码
2.点击单元格按钮事件(datagridview双击进入)
3.一键选中(checkbox)双击进入
4.查看选中(button)双击进入
5.点击按钮获取选中的一行实体
6.点击单元格获取实体
7.点击单元行头获取实体
8.获取数据列表
9.列头居中对齐的方法
三、整体代码
四、测试结果
五、样式
六、高度封装的数据填充方法
七、高度封装的分页方法
八、小结
一、前端界面
添加的datagridview应该如下设置:
1.只设置启用编辑
2.设置好每列的名称、控件类型、提示中文(页眉文本),选择【可见】等选项(建议TextBox选可见+只读,Checkbox选可见即可,Button选可见即可。选择只读后,不能被编辑或选中。)
3.如果不需要默认列,可以设置:RowHeadersVisibed = False
二、模块代码
【实体列表】
1.初始化列表代码
【备注】1.建立列表是模拟查数据库。2.“如果学生名为"小苏",则移除查看详情按钮”是一个题目要求,实际中不需要该功能可注释掉该代码。3.数据实体绑定于Tag上,Tag能识别哪行被点击或选中。
/// <summary> /// 初始化填充数据 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_Load(object sender, EventArgs e) { #region 建立列表 Student student1 = new Student { ID = 1, Name = "小苏", Remarks = "小苏的备注" }; Student student2 = new Student { ID = 2, Name = "小明", Remarks = "小明的备注" }; Student student3 = new Student { ID = 3, Name = "小花", Remarks = "小花的备注" }; var list = new List<Student>(); list.Add(student1); list.Add(student2); list.Add(student3); #endregion // 清空现有数据 dataGridView1.Rows.Clear(); //添加数据 foreach (var item in list) { int rowIndex = dataGridView1.Rows.Add(); dataGridView1.Rows[rowIndex].Cells["ID"].Value = item.ID;//字段 dataGridView1.Rows[rowIndex].Cells["StuName"].Value = item.Name;//字段 dataGridView1.Rows[rowIndex].Cells["Details"].Value = "查看详情";//按钮名称 dataGridView1.Rows[rowIndex].Tag = item; // 如果学生名为"小苏",则移除查看详情按钮 if (item.Name == "小苏") { dataGridView1.Rows[rowIndex].Cells["Details"] = new DataGridViewTextBoxCell();//重新初始化 dataGridView1.Rows[rowIndex].Cells["Details"].ReadOnly = true; // 设置为只读 } } }
【扩展】也可以直接选择绑定而不写上述代码:(灵活性降低)
2.点击单元格按钮事件(datagridview双击进入)
作用:点击查看详情跳出备注信息
/// <summary>/// 点击查看详情/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e){ if (e.ColumnIndex == dataGridView1.Columns["Details"].Index && e.RowIndex >= 0)//若点击了标签为【Details】列的按钮 { // 获取当前行对应的实体对象【注意修改此处Student类】,此处能获取到Remarks字段(虽然没有显示在界面上,但也绑定到Tag了) var item = dataGridView1.Rows[e.RowIndex].Tag as Student; //将list实体中的Remarks展示出来(item包含的字段:ID,Name,Remarks) MessageBox.Show(item.Remarks, "内容详情"); //【补充一:获取按钮上的文字】 }}
【补充一:获取按钮上的文字】
DataGridViewButtonCell buttonCell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex] as DataGridViewButtonCell;//获取点击的按钮if (buttonCell != null && buttonCell.Value != null){ if (buttonCell.Value.ToString() == "借出")//按钮字样为借出 { ;// 执行借出操作 } else if (buttonCell.Value.ToString() == "归还")//按钮字样为归还 { ;// 执行归还操作 }}
3.一键选中(checkbox)双击进入
作用:点击一键选中按钮,选中列表所有的checkbox
/// <summary>/// 一键选中/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void checkBox1_CheckedChanged(object sender, EventArgs e){ if(checkBox1.Checked) { foreach (DataGridViewRow row in dataGridView1.Rows) { DataGridViewCheckBoxCell checkBox = row.Cells["ManySelect"] as DataGridViewCheckBoxCell;//获取【ManySelect】的checkbox列 if (checkBox != null) { checkBox.Value = true; } } }}
4.查看选中(button)双击进入
作用:点击查看选中按钮,获得一个选中的列表
方法一:
/// <summary>/// 点击查看选中/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void button1_Click(object sender, EventArgs e)//点击触发{ //获取【DataGridView1】的checkbox选中的实体 var selectlist = new List<Student>();//将【Student】类存放入列表 //遍历获取数据 foreach (DataGridViewRow row in dataGridView1.Rows) { DataGridViewCheckBoxCell checkBox = row.Cells["ManySelect"] as DataGridViewCheckBoxCell; if (checkBox != null && checkBox.Value != null && (bool)checkBox.Value) { // 获取与选中CheckBox相关联的实体,假设实体类型为Student var entity = row.Tag as Student; //【Student】实体 if (entity != null) { selectlist.Add(entity); } } } //后续可对selectlist操作}
方法二:(获取单一内容)
private void button3_Click(object sender, EventArgs e){ // 创建一个列表来存储选中的内容 List<string> selectedContents = new List<string>(); // 遍历所有行 foreach (DataGridViewRow row in dataGridView1.Rows) { // 检查该行是否被选中 if (Convert.ToBoolean(row.Cells["Select"].Value) == true) { // 获取 "Content" 列的值,并添加到列表中 string contentValue = row.Cells["Content"].Value.ToString(); selectedContents.Add(contentValue); } } // 显示选中的内容(可以根据需要进行其他处理) MessageBox.Show(string.Join(", ", selectedContents));}
5.点击按钮获取选中的一行实体
前提条件:需要默认列,可以设置 RowHeadersVisibed = True ,即获取点击单元行头的实体
private void button3_Click(object sender, EventArgs e){ if (dataGridView2.SelectedRows.Count == 1)//当选中了一行时 { // 获取选中的那行,转化为【StuMessage】实体 var selectedEntity = dataGridView2.Rows[dataGridView2.SelectedRows[0].Index].Tag as StuMessage; ; }}
6.点击单元格获取实体
private void dataGridView2_CellContentClick(object sender, DataGridViewCellEventArgs e){ var stumodel = dataGridView2.Rows[e.RowIndex].Tag as StuMessage;}
//如果单纯获取点击的内容:string clickedContent = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
7.点击单元行头获取实体
private void dataGridView2_RowHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e){ var stumodel = dataGridView2.Rows[e.RowIndex].Tag as StuMessage;}
8.获取数据列表
封装方法
/// <summary> /// 获取指定datagridview的列表,并转化为T实体 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataGridView"></param> /// <returns></returns> private List<T> GetDataGridList<T>(DataGridView dataGridView) where T : class { List<T> list = new List<T>(); foreach (DataGridViewRow row in dataGridView.Rows) { var item = row.Tag as T; list.Add(item); } return list; }
调用方法:请将Notice替换为您的实体
var list = GetDataGridList<Notice>(dataGridView1);
9.列头居中对齐的方法
三、整体代码
【注意】此代码为Demo代码,并不符合编写规范,旨在帮助开发者找到灵感。
using System.Collections.Generic;namespace WinFormsApp2{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } class Student { public int ID { get; set; } public string Name { get; set; } public string Remarks { get; set; } } /// <summary> /// 初始化填充数据 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_Load(object sender, EventArgs e) { #region 建立列表 Student student1 = new Student { ID = 1, Name = "小苏", Remarks = "小苏的备注" }; Student student2 = new Student { ID = 2, Name = "小明", Remarks = "小明的备注" }; Student student3 = new Student { ID = 3, Name = "小花", Remarks = "小花的备注" }; var list = new List<Student>(); list.Add(student1); list.Add(student2); list.Add(student3); #endregion // 清空现有数据 dataGridView1.Rows.Clear(); //添加数据 foreach (var item in list) { int rowIndex = dataGridView1.Rows.Add(); dataGridView1.Rows[rowIndex].Cells["ID"].Value = item.ID;//字段 dataGridView1.Rows[rowIndex].Cells["StuName"].Value = item.Name;//字段 dataGridView1.Rows[rowIndex].Cells["Details"].Value = "查看详情";//按钮名称 dataGridView1.Rows[rowIndex].Tag = item; // 如果学生名为"小苏",则移除查看详情按钮 if (item.Name == "小苏") { dataGridView1.Rows[rowIndex].Cells["Details"] = new DataGridViewTextBoxCell();//重新初始化 dataGridView1.Rows[rowIndex].Cells["Details"].ReadOnly = true; // 设置为只读 } } } /// <summary> /// 点击查看选中 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button1_Click(object sender, EventArgs e)//点击触发 { //获取【DataGridView1】的checkbox选中的实体 var selectlist = new List<Student>();//将【Student】类存放入列表 //遍历获取数据 foreach (DataGridViewRow row in dataGridView1.Rows) { DataGridViewCheckBoxCell checkBox = row.Cells["ManySelect"] as DataGridViewCheckBoxCell; if (checkBox != null && checkBox.Value != null && (bool)checkBox.Value) { // 获取与选中CheckBox相关联的实体,假设实体类型为Student var entity = row.Tag as Student; //【Student】实体 if (entity != null) { selectlist.Add(entity); } } } //后续可对selectlist操作 } /// <summary> /// 点击查看详情 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == dataGridView1.Columns["Details"].Index && e.RowIndex >= 0)//若点击了标签为【Details】列的按钮 { // 获取当前行对应的实体对象【注意修改此处Student类】,此处能获取到Remarks字段(虽然没有显示在界面上,但也绑定到Tag了) var item = dataGridView1.Rows[e.RowIndex].Tag as Student; //将list实体中的Remarks展示出来(item包含的对象:ID,Name,Remarks) MessageBox.Show(item.Remarks, "内容详情"); } } /// <summary> /// 一键选中 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void checkBox1_CheckedChanged(object sender, EventArgs e) { if(checkBox1.Checked) { foreach (DataGridViewRow row in dataGridView1.Rows) { DataGridViewCheckBoxCell checkBox = row.Cells["ManySelect"] as DataGridViewCheckBoxCell;//获取【ManySelect】多选框列 if (checkBox != null) { checkBox.Value = true; } } } } }}
四、测试结果
1.通过debug发现选中有效(测试通过)
2.发现小苏对应按钮被删除(测试通过)
3.发现一键多选奏效(测试通过,图略)
4.发现查看详情有效(测试通过)
五、样式
修改某行的字体颜色:
if (item.Name == "小明"){ dataGridView1.Rows[rowIndex].DefaultCellStyle.ForeColor = Color.Red;//文字颜色 dataGridView1.Rows[rowIndex].DefaultCellStyle.BackColor = Color.Yellow;//背景颜色}
六、高度封装的数据填充方法
【封装方法】
/// <summary> /// 获取DataGridView,需传入控件、数据列表、标题列表 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataGridView"></param> /// <param name="list"></param> /// <param name="headtext"></param> /// <exception cref="Exception"></exception> private void GetDataGridView<T>(DataGridView dataGridView,List<T> list,List<string> headtext) where T : class { //设置表头样式和属性 dataGridView.AllowUserToAddRows = false;//不允许添加、删除 dataGridView.AllowUserToDeleteRows = false; dataGridView.ReadOnly = true;//设置可读 dataGridView.RowHeadersVisible = false;//隐藏最左边的空白栏 dataGridView.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;//表头居中对齐 dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;//自适应宽度 //dataGridView.RowTemplate.Height = 80;//设置行高 //获取字段列表 var field = typeof(T).GetProperties(); //判断输入标题 if (headtext.Count != field.Length) { throw new Exception("表头的标题个数要和字段长度一致!"); } // 设置表头样式 dataGridView.ColumnHeadersDefaultCellStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter, // 中间对齐 BackColor = Color.LightGray, // 表头背景色 ForeColor = Color.Black, // 表头文字颜色 Font = new Font("微软雅黑", 12F, FontStyle.Bold), // 表头字体 }; //设置表格内容(按实体顺序依次设置名字) dataGridView.Columns.Clear(); foreach (var item in headtext) { dataGridView.Columns.Add(new DataGridViewTextBoxColumn //增加文字列 { DefaultCellStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter }, HeaderText = item,//中文标题 MinimumWidth = 6, Name = field[headtext.FindIndex(x=>x==item)].Name,//字段的名字 例如ID Name ReadOnly = true, SortMode = DataGridViewColumnSortMode.NotSortable, Width = 110 }); } //dataGridView.Columns.Add(new DataGridViewButtonColumn //增加按钮 //{ // DefaultCellStyle = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter }, // HeaderText = "操作",//中文标题 // MinimumWidth = 6, // Name = "btn1",//字段的名字 例如ID Name // ReadOnly = true, // SortMode = DataGridViewColumnSortMode.NotSortable, // Width = 110 //}); //dataGridView.Columns[0].Width = 200; // 手动调节宽度 //dataGridView.Columns[1].Width = 200; // 手动调节宽度 // dataGridView.Columns[2].Width = 80; // 手动调节宽度 // dataGridView.Columns[3].Width = 80; // 手动调节宽度 // dataGridView.Columns[4].Width = 80; // 手动调节宽度 // dataGridView.Columns[5].Width = 80; // 手动调节宽度 // dataGridView.Columns[6].Width = 300; // 手动调节宽度 // 清空现有数据 dataGridView.Rows.Clear(); //添加数据 foreach (var item in list) { int rowIndex = dataGridView.Rows.Add(); foreach (var jtem in field) { dataGridView.Rows[rowIndex].Cells[jtem.Name.ToString()].Value = jtem.GetValue(item);//字段 dataGridView.Rows[rowIndex].DefaultCellStyle.ForeColor = Color.Black; //if (jtem.Name.ToString().Equals("time"))//对特定的字段处理 //{ //dataGridView.Rows[rowIndex].Cells[jtem.Name.ToString()].Value = ((DateTime)(jtem.GetValue(item))).ToString("yyyy年MM月dd日"); //} //dataGridView.Rows[rowIndex].Cells["btn1"].Value = "点击我";//按钮名称 //移除按钮(两步) //if (false) //{ // dataGridView.Rows[rowIndex].Cells["btn1"] = new DataGridViewTextBoxCell();//重新初始化 // dataGridView.Rows[rowIndex].Cells["btn1"].ReadOnly = true; // 设置为只读 //} } dataGridView.Rows[rowIndex].Tag = item;//绑定到Tag上方便后续调用 } }
【调用示例】
private void checkBox1_CheckedChanged(object sender, EventArgs e){ string sql = @"SELECT types,time,objects FROM BuyTable "; var entity = new Notice(); //从数据库中获取列表存入list var list = entity.QueryBySQL(sql); //设置标题 var headtext = new List<string>() { "购买类型", "购买时间","购买物品" }; //获取dataGridView GetDataGridView(dataGridView10,list, headtext);}
七、高度封装的分页方法
/// <summary> /// 查询数据 /// </summary> private void GetData() { var list = GetList().ToList();//假设这里是查表操作 list = GetPageList(list, label7, label6, button2, button3);//【步骤一】传入相关控件实现分页 List<string> title = new List<string> { { "开奖期数" }, { "开奖时间" }, { "平均值" }, { "最大值" }, { "最小值" }, { "跨度值" }, { "开奖号码" } }; GetDataGridView(dataGridView1, list, title);//渲染到DataGridView中 } private int currentIndex = 1; // 当前页索引 private int totalPages = 0; // 总页数 private List<T> GetPageList<T>(List<T> list, Label total, Label Pagedetails, Button lastpage, Button nextpage, int pagesize = 7) { lastpage.Enabled = false; nextpage.Enabled = false; var count = list.Count; totalPages = (count + pagesize - 1) / pagesize; // 计算总页数 if (Pagedetails.Text.Equals("第1页/共x页")) // 【 步骤二 winform默认设置好Pagedetails="第1页/共x页"】,此处代表第一次进入 { currentIndex = 1; // 初始化当前页 } else { // 创建正则表达式对象 Regex regex = new Regex(@"第(\d+)页/共(\d+)页"); // 尝试匹配字符串 Match match = regex.Match(Pagedetails.Text); currentIndex = Convert.ToInt32(match.Groups[1].Value); } // 更新页数显示 Pagedetails.Text = $"第{currentIndex}页/共{totalPages}页"; total.Text = $"共{count}条数据"; // 更新按钮状态 lastpage.Enabled = currentIndex > 1; // 如果不是第一页,启用上一页按钮 nextpage.Enabled = currentIndex < totalPages; // 如果不是最后一页,启用下一页按钮 return list.Skip((currentIndex - 1) * pagesize).Take(pagesize).ToList(); // 获取当前页的数据 } //上一页(双击按钮订阅此事件) private void button2_Click(object sender, EventArgs e) { if (currentIndex > 1) // 检查是否可以向前翻页 { currentIndex--; // 当前页减一 label6.Text = $"第{currentIndex}页/共{totalPages}页";//【步骤三】更新 Pagedetails 标签 GetData(); } } //下一页(双击按钮订阅此事件) private void button3_Click(object sender, EventArgs e) { if (currentIndex < totalPages) // 检查是否可以向后翻页 { currentIndex++; // 当前页加一 label6.Text = $"第{currentIndex}页/共{totalPages}页";//【步骤三】更新 Pagedetails 标签 GetData(); } }
八、小结
1.增: 建议用textbox、combobox等工具增,而不是直接datagridview新增,一来代码编写麻烦,二来输入工具不能多样化(比如说时间控件、多选框控件)。
2.删:建议每条数据加一个删除按钮,方便操作
3.改:建议选中某条数据然后将数据信息转移到textbox上,label显示“您已选中xxx数据”,然后点击button去修改相应信息(选中数据和点击按钮都能获取到对应实体)
4.查:同第2条
5.如果单纯用datagridview作增删查改,虽然能实现,但是代码复杂难以维护,而且输入条件单一,容易操作失误,不建议这么做。