简体   繁体   English

无法从控制列表中处置和删除控件

[英]Unable to dispose and remove controls from control list

thanks for reading. 谢谢阅读。

I have a C#.NET form with buttons that switch controls in a main panel. 我有一个C#.NET表单,其中的按钮可以切换主面板中的控件。 I didn't have any issues until I upgraded to Visual Studio 2012 and Advanced Installer. 在升级到Visual Studio 2012和Advanced Installer之前,我没有遇到任何问题。 Target Framework is 4.0, not 4.5. 目标框架是4.0,而不是4.5。

When I change controls, I dispose and remove the previous before adding the new one, but I'm getting an error when there aren't any controls yet (ie, when the first one loads). 当我更改控件时,我会在添加新控件之前处理并删除前一个控件,但是当没有任何控件时(即第一个加载时)我收到错误。

The original loop crashed with something about iterating while modifying the collection, so now I'm trying to just remove one control after ensuring it's there. 在修改集合时,原始循环崩溃了一些关于迭代的东西,所以现在我试图在确保它在那之后删除一个控件。

This errors with: Index 0 is out of range. 此错误:索引0超出范围。

This all works fine on the dev machine, and it wasn't an issue using the old built-in VS installer. 这一切在dev机器上运行正常,使用旧的内置VS安装程序不是问题。

Any ideas? 有任何想法吗? 4.0 framework issue? 4.0框架问题? Missing reference not being deployed? 缺少参考未部署?

Thanks! 谢谢!

panelMain.SuspendLayout();
int control_count = panelMain.Controls.Count;
if (control_count > 1) {
    Log.Write("More than one control found in main panel.", ErrorLevel.Error);
}
if (control_count > 0) {
    Control current_ctrl = panelMain.Controls[0];
    current_ctrl.Dispose();
    panelMain.Controls.Remove(current_ctrl);
}

//foreach (Control ctrl in panelMain.Controls) {
//    ctrl.Dispose();
//    panelMain.Controls.Remove(ctrl);
//}

The issue with the foreach loop that you've commented out is that you cannot add items to or remove items from a collection that you are currently enumerating. 您已注释掉的foreach循环的问题是您无法向当前枚举的集合中添加项目或从中删除项目。 That means that if you want to loop through a collection and remove items then you must use a for loop. 这意味着如果你想循环一个集合并删除项目,那么你必须使用for循环。 If you want to remove multiple items then you must loop backwards. 如果要删除多个项目,则必须向后循环。

The issue with the second if statement is that disposing a control automatically removes it from its parent's Controls collection. 第二个if语句的问题是,处理控件会自动将其从父控件集合中删除。 That means that, as soon as you call Dispose on the control, there is no longer an item in the Controls collection so the Remove call fails. 这意味着,只要在控件上调用Dispose,Controls集合中就不再有项目,因此Remove调用失败。

So, the moral of the story is that you should use a for loop, loop backwards and use just Dispose to destroy and remove. 因此,故事的寓意是你应该使用for循环,向后循环并使用Dispose来销毁和删除。

Here is a simple recursive method to dispose of controls if anyone is interested. 如果有人感兴趣,这是一个简单的递归方法来处理控件。 Using the advice of jmcilhinney above. 使用上面jmcilhinney的建议。

NOTE: make sure you read all comments about Visible property and setting it back to true. 注意:请确保阅读有关Visible属性的所有注释并将其重新设置为true。

    // Start by calling a parent control containing the controls you want to 
    // destroy such as a form, groupbox or panel
    private void DisposeControls(Control ctrl)
    {
        // Make control disappear first to avoid seeing each child control 
        // disappear. This is optional (if you use - make sure you set parent 
        // control's Visible property back to true if you create controls 
        // again)
        ctrl.Visible = false;
        for (int i = ctrl.Controls.Count - 1; i >= 0; i--)
        {
            Control innerCtrl = ctrl.Controls[i];

            if (innerCtrl.Controls.Count > 0)
            {
                // Recurse to drill down through all controls
                this.DisposeControls(innerCtrl);
            }

            innerCtrl.Dispose();
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM