如何忽略隐藏行内容 仅根据可见单元格自动调整DataGridView列宽
实现方案
你当前使用的DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader枚举本身的设计逻辑就是仅基于当前可见的行内容计算列宽,不需要额外遍历过滤后的数据,你现有代码的问题是把列宽适配逻辑写在了ColumnWidthChanged事件里,修改列宽的操作会再次触发该事件,导致递归调用、界面抖动等问题,以下是两种可行的实现方式:
方案1:直接使用内置自动适配属性(推荐)
不需要手动编写宽度计算逻辑,直接在数据源绑定完成后设置列的自动调整模式即可,代码修改如下:
private void Form1_Load(object sender, EventArgs e) { string colName = "aaaaaaaaaaaaaaaaaaaa"; DataTable tbl = new DataTable(); tbl.Columns.Add(colName); DataRow row = tbl.NewRow(); row[colName] = "ss"; tbl.Rows.Add(row); row = tbl.NewRow(); string val2 = "vvvvvvvvvvvvvvv"; row[colName] = val2; tbl.Rows.Add(row); dataGridView1.DataSource = tbl; tbl.DefaultView.RowFilter = colName + " <> '"+ val2 + "'"; // 绑定完成后设置自动调整模式,仅根据可见行适配,不含表头 dataGridView1.Columns[colName].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader; // 如果要所有列都生效,可以遍历所有列设置 // foreach(DataGridViewColumn col in dataGridView1.Columns) // { // col.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCellsExceptHeader; // } }
- 如果后续需要动态关闭自动适配,直接把
AutoSizeMode改回DataGridViewAutoSizeColumnMode.None即可
方案2:手动计算列宽(适用于需要自定义适配规则的场景)
如果需要自主控制计算逻辑,可以遍历DataGridView的可见行,计算每个单元格的内容宽度,取最大值作为列宽:
private void AutoSizeColumnsByVisibleRows() { using (Graphics g = dataGridView1.CreateGraphics()) { foreach (DataGridViewColumn col in dataGridView1.Columns) { if (!col.Visible) continue; int maxWidth = 0; // 仅遍历可见行 foreach (DataGridViewRow row in dataGridView1.Rows) { if (!row.Visible) continue; object cellValue = row.Cells[col.Index].Value; if (cellValue == null) continue; int cellWidth = (int)g.MeasureString(cellValue.ToString(), dataGridView1.Font).Width; if (cellWidth > maxWidth) { maxWidth = cellWidth; } } // 加上单元格内边距避免文字被截断 col.Width = maxWidth + dataGridView1.DefaultCellStyle.Padding.Left + dataGridView1.DefaultCellStyle.Padding.Right + 2; } } }
你可以在需要触发列宽调整的时机(比如筛选完成、数据源更新后)调用这个方法即可。
内容的提问来源于stack exchange,提问作者Angus B.
相关产品推荐
相关产品推荐

