C# Win Forms 删除动态创建的控件时出现问题

C# Win Forms issues deleting dynamically created controls

我有一个函数可以从数据库中读取信息,并在从组合框中选择菜单项时动态创建复选框控件。

当用户从组合框中选择不同的项目时,我试图删除页面上已有的任何现有复选框。但是,删除功能只会删除每隔一个复选框。知道我做错了什么吗?

表单非常基本,只有一个表单,没有选项卡,只有这个组合框和动态创建的复选框。

  private void serverModels_SelectedIndexChanged(object sender, EventArgs e)
    {
        DeleteBoxes();

        List<string> eqpIDs = new List<string>();
        try
        {
            DataExtractor dataExtract = new DataExtractor(DataBase.TCDBServerName, DataBase.TCDBname, DataBase.TCDBUserID, DataBase.TCDBPassword);
            eqpIDs = dataExtract.GetToolsByServerModel(Convert.ToString(serverModels.SelectedItem));
        }
        catch (Exception ex)
        {
            Logger.InsertSystemLog(e.ToString());
            MessageBox.Show(ex.ToString());
            return;
        }


        for(int i = 0; i < eqpIDs.Count; i++)
        {
            CheckBox box = new CheckBox();
            box.Checked = true;
            box.Tag = "TOOL";
            box.Text = eqpIDs[i];
            box.AutoSize = true;
            box.Location = new Point(50 + 75 * (i / 17), (i % 17) * 25 + 120);
            this.Controls.Add(box);
        }
    }

    private void DeleteBoxes()
    {
        foreach (Control c in this.Controls)
        {
            if (c is CheckBox && c.Tag.ToString() == "TOOL" )
                c.Dispose();
        }
    }

这似乎是因为您正在修改控件的 Controls 集合,同时迭代它。尝试这样的事情:

private void DeleteBoxes()
{
    List<Control> toDispose = new List<Control>();
    foreach (Control c in this.Controls)
    {
        if (c is CheckBox && c.Tag.ToString() == "TOOL" )
            toDispose.Add(c);
    }
    foreach (Control c in toDispose)
    {
        c.Dispose();
    }
}

Dispose 正在从 Controls 集合中移除控件并释放该控件。

如前所述here

When a Control is removed from the control collection, all subsequent controls are moved up one position in the collection.

这就是您的逻辑跳过所有其他 CheckBox 的原因。

尝试像这样反向使用 for 循环:

for (int ii = Controls.Count - 1; ii >= 0; ii--)
{
    if (Controls[ii] is CheckBox && Controls[ii].Tag.ToString() == "TOOL")
        Controls[ii].Dispose();
}