如何在C#中将选中行转移至另一DataGridView后删除原选中行?
解决方法:转移选中行后删除原列表中的对应行
你的现有代码已经实现了把dgAvailable中选中的行转移到dgSelected,但直接在遍历过程中删除行会触发集合修改异常(因为foreach遍历的集合不能在遍历中被修改)。正确的做法是先收集所有需要删除的行,再统一删除,具体修改如下:
修改后的完整代码(收集待删除行版)
private void BtnRight_Click(object sender, EventArgs e) { // 先创建一个列表存储需要删除的行 List<DataGridViewRow> rowsToDelete = new List<DataGridViewRow>(); foreach(DataGridViewRow item in dgAvailabe.Rows) { // 跳过新行(如果允许用户添加行的话) if (item.IsNewRow) continue; DataGridViewCheckBoxCell chkchecking = item.Cells[0] as DataGridViewCheckBoxCell; if (Convert.ToBoolean(chkchecking.Value) == true) { // 转移行到dgSelected int n = dgSelected.Rows.Add(); dgSelected.Rows[n].Cells[0].Value = item.Cells[1].Value.ToString(); dgSelected.Rows[n].Cells[1].Value = item.Cells[2].Value.ToString(); dgSelected.Rows[n].Cells[2].Value = item.Cells[3].Value.ToString(); dgSelected.Rows[n].Cells[3].Value = item.Cells[4].Value.ToString(); dgSelected.Rows[n].Cells[4].Value = item.Cells[5].Value.ToString(); // 将当前行加入待删除列表 rowsToDelete.Add(item); } } // 统一删除选中的行 foreach (DataGridViewRow row in rowsToDelete) { dgAvailabe.Rows.Remove(row); } }
关键说明
- 收集待删除行:用
List<DataGridViewRow>存储所有需要删除的行,避免在foreach遍历dgAvailabe.Rows时直接修改集合,防止抛出InvalidOperationException。 - 跳过新行:如果你的
dgAvailable开启了AllowUserToAddRows(默认是开启的),需要判断item.IsNewRow跳过最后一行的空行,避免误处理。 - 统一删除:遍历待删除列表,调用
Rows.Remove(row)删除对应行,这一步不会影响原集合的遍历安全。
备选方案:倒序for循环直接删除
如果你想减少中间集合的内存占用,也可以用倒序for循环直接遍历删除(倒序遍历不会因为前面的行被删除而导致索引偏移),代码示例如下:
private void BtnRight_Click(object sender, EventArgs e) { // 倒序遍历dgAvailabe的行 for (int i = dgAvailabe.Rows.Count - 1; i >= 0; i--) { DataGridViewRow item = dgAvailabe.Rows[i]; if (item.IsNewRow) continue; DataGridViewCheckBoxCell chkchecking = item.Cells[0] as DataGridViewCheckBoxCell; if (Convert.ToBoolean(chkchecking.Value) == true) { // 转移行到dgSelected int n = dgSelected.Rows.Add(); dgSelected.Rows[n].Cells[0].Value = item.Cells[1].Value.ToString(); dgSelected.Rows[n].Cells[1].Value = item.Cells[2].Value.ToString(); dgSelected.Rows[n].Cells[2].Value = item.Cells[3].Value.ToString(); dgSelected.Rows[n].Cells[3].Value = item.Cells[4].Value.ToString(); dgSelected.Rows[n].Cells[4].Value = item.Cells[5].Value.ToString(); // 直接删除当前行,倒序遍历不会有索引问题 dgAvailabe.Rows.RemoveAt(i); } } }
两种方法都可以解决问题,第一种更直观易读,第二种内存占用略低,根据你的场景选择即可。
内容的提问来源于stack exchange,提问作者Godofsleepy
相关产品推荐
相关产品推荐

