DataGridView列右移功能优化求助:大文件卡顿问题
DataGridView列右移功能优化方案
问题背景
我给DataGridView做了个上下文菜单,用来处理各种非规范的制表符分隔旧财务数据。现在要实现指定列右侧所有列右移的功能,试了.Insert、.Add和.Clone方法都没成功。当前代码处理大文件时卡顿严重,求优化思路。另外最终会改成传递列表,不用全局列表。
原实现代码
private void dgv_MoveColumnRight(DataGridView dgv, int cIndex) { dgv.ColumnCount = dgv.ColumnCount + 1; int cCount = dgv.ColumnCount - 2; if (dgv.RowCount <= 1) { return; } while (cCount >= cIndex) { dgv_CopyColumn(dgv, cCount); dgv_PasteColumn(dgv, cCount + 1); cCount--; Application.DoEvents(); } for (int n = 0; n < dgv.RowCount; n++) { dgv.Rows[n].Cells[cIndex].Value = " "; } } List<string> colData = new List<string>(); private void dgv_CopyColumn(DataGridView dgv, int cIndex) { colData.Clear(); for (int n = 0; n < dgvStatement.RowCount; n++) { if(dgv.Rows[n].Cells[cIndex].Value != null) { colData.Add(dgv.Rows[n].Cells[cIndex].Value.ToString()); } else { colData.Add(" "); } showMe.Comment = n.ToString() + " " + colData[n]; } } private void dgv_PasteColumn(DataGridView dgv, int cIndex) { if (colData.Count == 0) { return; } for (int n = 0; n < dgvStatement.RowCount; n++) { dgv.Rows[n].Cells[cIndex].Value = colData[n]; } }
优化思路
- 暂停控件重绘:操作前后分别调用
dgv.SuspendLayout()和dgv.ResumeLayout(false),避免每一步单元格修改都触发UI刷新,大幅降低卡顿。 - 直接操作数据源:如果DataGridView绑定了
DataTable这类数据源,直接在数据源层面插入列、转移数据,控件会自动同步,比直接操作单元格效率高一个数量级。 - 移除冗余UI操作:删掉
Application.DoEvents()(会强制刷新UI,加重负担)和showMe.Comment的实时更新(调试用代码,正式场景无意义)。 - 替换全局列表为局部传递:让
dgv_CopyColumn返回List<string>,直接作为参数传给dgv_PasteColumn,避免全局状态的潜在问题。 - 批量设置空值:不用逐行设置目标列的空值,可通过遍历数据源行或者利用列默认值一次性处理。
优化后示例代码(基于数据源操作)
假设你的DataGridView绑定的是DataTable,可以这样实现:
private void MoveColumnsRight(DataGridView dgv, int targetColumnIndex) { if (dgv.DataSource is not DataTable dt || dt.Rows.Count == 0) return; // 暂停控件重绘 dgv.SuspendLayout(); // 在目标位置右侧插入新列 dt.Columns.Add($"TempCol_{Guid.NewGuid()}", typeof(string)); // 从右往左移动列数据 for (int colIdx = dt.Columns.Count - 2; colIdx >= targetColumnIndex; colIdx--) { foreach (DataRow row in dt.Rows) { row[colIdx + 1] = row[colIdx] ?? " "; } } // 清空目标列 foreach (DataRow row in dt.Rows) { row[targetColumnIndex] = " "; } // 恢复控件重绘 dgv.ResumeLayout(false); dgv.Refresh(); }
优化后示例代码(直接操作控件,无数据源绑定)
private void dgv_MoveColumnRight(DataGridView dgv, int cIndex) { if (dgv.RowCount <= 1) return; // 暂停控件重绘 dgv.SuspendLayout(); dgv.ColumnCount += 1; int cCount = dgv.ColumnCount - 2; while (cCount >= cIndex) { // 直接复制列数据,用局部变量替代全局列表 var columnData = new List<string>(); foreach (DataGridViewRow row in dgv.Rows) { columnData.Add(row.Cells[cCount].Value?.ToString() ?? " "); } // 粘贴到右侧列 for (int i = 0; i < dgv.Rows.Count; i++) { dgv.Rows[i].Cells[cCount + 1].Value = columnData[i]; } cCount--; } // 批量清空目标列 foreach (DataGridViewRow row in dgv.Rows) { row.Cells[cIndex].Value = " "; } // 恢复重绘 dgv.ResumeLayout(false); dgv.Refresh(); }
内容的提问来源于stack exchange,提问作者Mike Sr
相关产品推荐
相关产品推荐

