从DataGridView中删除行时出现意外行为

时间:2016-04-29 00:15:59

标签: c# .net winforms datagridview

我使用下面的代码删除选定的行格式DataGridView,但我有问题 此代码将始终删除一半已检查的行

如果我检查了两行中的两行,那么它将删除一行并留下另一行

private void B_DeleteProduct_Click(object sender, EventArgs e)
{
    if (MessageBox.Show("selected row deleted", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
    {
        foreach (DataGridViewRow RowToDelete in DGV_INVOICE.Rows)
        {
            object Cell = RowToDelete.Cells["Edit_Checkbox"].Value;

            if (Cell.ToString() == "True")
            {
                DGV_INVOICE.Rows.Remove(RowToDelete);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:3)

您正在修改正在迭代的集合。通常它会导致无效的操作异常,但在这种情况下不会。

DataGridViewRowCollection 的内部实现可让您在foreach循环中修改集合,因此技术上允许在foreach循环期间修改集合你不会收到例外。 但是如果您执行它就像在代码中执行一样,只会删除一半的项目。

这是因为在删除索引0处的项目后,项目索引将减少1,索引1处的上一项目将转到索引0,依此类推,然后迭代器将索引1用于下一项目,而前一项目位于索引1现在是在索引0。这样一个项目将被删除,一个项目将被绕过,直到收集结束。

要解决此问题,您可以找到要删除的项目并将其保留在列表中,然后迭代列表并将其从原始集合中删除。您可以使用linq Where查找行,ToList将它们存储在提到的列表中,然后将其删除:

this.dataGridView1.Rows.Cast<DataGridViewRow>()
    .Where(row => (bool?)row.Cells[1].Value == true)
    .ToList().ForEach(x =>
    {
        this.dataGridView1.Rows.Remove(x);
    }); 

你也可以使用反向循环,但我认为上面的方法更具可读性。