如何在DataGridView中将选中行移至顶部并优化性能?
高效实现DataGridView选中行移至DataTable顶部
我明白你遇到的痛点——原代码通过两次遍历DataGridView的UI行来重组数据,不仅在数据量大时性能拉胯,还存在冗余逻辑。下面给出两种针对性的高效优化方案,重点减少遍历开销、避开UI层低效操作,直接针对DataTable核心数据处理:
方案一:基于HashSet快速筛选,单次遍历原DataTable
这个方案的核心是先把选中行存入HashSet(实现O(1)时间复杂度的存在性判断),然后仅遍历一次原DataTable,就能完成新表的重组:
if (MainWindow.table_G_Level_Data.dataGridView1.SelectedRows.Count <= 0) return; // 1. 获取绑定的原DataTable,直接操作数据源而非UI控件 var originalTable = (DataTable)MainWindow.table_G_Level_Data.dataGridView1.DataSource; // 2. 收集选中行,用HashSet加速后续判断 var selectedRowSet = new HashSet<DataRow>(); var selectedRowList = new List<DataRow>(); foreach (DataGridViewRow uiRow in MainWindow.table_G_Level_Data.dataGridView1.SelectedRows) { var dataRow = ((DataRowView)uiRow.DataBoundItem).Row; selectedRowSet.Add(dataRow); selectedRowList.Add(dataRow); } // 3. 创建新表并导入数据 var newTable = originalTable.Clone(); // 先导入选中行实现置顶 foreach (var row in selectedRowList) { newTable.ImportRow(row); } // 再导入未选中行,仅遍历一次原DataTable foreach (DataRow row in originalTable.Rows) { if (!selectedRowSet.Contains(row)) { newTable.ImportRow(row); } } // 4. 重新绑定并恢复选中状态 MainWindow.table_G_Level_Data.dataGridView1.DataSource = newTable; for (int i = 0; i < selectedRowList.Count; i++) { MainWindow.table_G_Level_Data.dataGridView1.Rows[i].Selected = true; }
优化点说明:
- 避免重复遍历UI行:UI元素的访问开销远高于直接操作DataTable,这里仅遍历一次选中行集合,再遍历一次原DataTable(比遍历UI行效率提升明显)
- HashSet加速判断:
Contains操作的时间复杂度为O(1),替代原代码的两次循环判断,大幅减少计算量 - 逻辑更清晰:明确分离“收集选中行”和“重组新表”的步骤,减少冗余代码
方案二:利用DataView排序(无需创建新表)
如果你的需求只是显示上置顶选中行,不需要修改原DataTable的物理顺序,这个轻量方案更适合:给DataTable加一个临时排序列,通过标记优先级实现显示置顶:
if (MainWindow.table_G_Level_Data.dataGridView1.SelectedRows.Count <= 0) return; var originalTable = (DataTable)MainWindow.table_G_Level_Data.dataGridView1.DataSource; // 1. 添加临时排序列(不存在则创建) if (!originalTable.Columns.Contains("SortPriority")) { originalTable.Columns.Add("SortPriority", typeof(int)); } // 2. 设置排序优先级:选中行设为0(优先显示),未选中设为1 foreach (DataRow row in originalTable.Rows) { row["SortPriority"] = 1; } foreach (DataGridViewRow uiRow in MainWindow.table_G_Level_Data.dataGridView1.SelectedRows) { ((DataRowView)uiRow.DataBoundItem).Row["SortPriority"] = 0; } // 3. 通过DataView排序实现置顶 var sortedView = new DataView(originalTable); sortedView.Sort = "SortPriority ASC"; MainWindow.table_G_Level_Data.dataGridView1.DataSource = sortedView; // 可选:如果不需要保留临时列,排序后可移除 // originalTable.Columns.Remove("SortPriority");
方案优势:
- 无需创建新DataTable,内存开销更小
- 操作更轻量,适合数据量较大的场景
- 原DataTable物理顺序不变,仅通过视图排序改变显示效果
根据你的实际需求选择方案:如果需要永久修改DataTable的行顺序,用方案一;如果只是临时显示置顶,方案二更高效。
内容的提问来源于stack exchange,提问作者flyingAlemannian
相关产品推荐
相关产品推荐

