为什么控件不想被删除?

发布于 2024-12-20 19:22:10 字数 432 浏览 1 评论 0原文

我试图删除 winform 面板中包含的所有控件,但它们只是不想被删除 - 其中一些被删除,有些则没有。我已经尝试了 2 种方法,但什么也没有:

  1. foreach

    foreach(在 this.contentsPanel.Controls 中控制 controlEntry)
    {
        this.contentsPanel.Controls.Remove(controlEntry);
    }
    
  2. for

    for (int i = 0; i < this.contentsPanel.Controls.Count; i++)
    {
        this.contentsPanel.Controls.RemoveAt(i);
    }
    

会发生这种情况?

I am trying to remove all the controls that are contained in my winform panel but they simply do not want to get removed - some of them are removed and some of them not. I have tried 2 approaches already and nothing:

  1. foreach

    foreach (Control controlEntry in this.contentsPanel.Controls)
    {
        this.contentsPanel.Controls.Remove(controlEntry);
    }
    
  2. for

    for (int i = 0; i < this.contentsPanel.Controls.Count; i++)
    {
        this.contentsPanel.Controls.RemoveAt(i);
    }
    

Why is this happening ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

人│生佛魔见 2024-12-27 19:22:10

您必须留意这样的代码,像这样从容器中删除控件会产生不可恢复的资源泄漏。 Controls.Remove/At() 或其他发帖者建议的 Controls.Clear() 方法从集合中删除控件并将其重新托管到“停车窗口”。原本看不见的窗户,原生窗户可以在其中找到一个好客的家,而不必被摧毁。准备好重新托管给另一位家长。

这就是陷阱,您通常不会将其移至另一个父级。该控件将继续在停车窗口中生存,消耗本机 Windows 资源。垃圾收集器无法回收这些资源。最终,当 Windows 拒绝为您的进程提供更多窗口时,您的程序将崩溃。异常消息将显示“创建句柄时出错”。

相反,您必须处置该控件。这也会自动从其父控件中删除该控件。正确的代码是:

 while (contentsPanel.Controls.Count > 0) contentsPanel.Controls[0].Dispose();

或者如果您发现这看起来有点太奇怪,则向后迭代。

You have to watch out for code like this, removing controls from their container like this produces an unrecoverable resource leak. Controls.Remove/At(), or the Controls.Clear() method as suggested by other posters, removes the control from the collection and re-hosts it to the "parking window". An otherwise invisible window where the native window can find a hospitable home without having to be destroyed. Ready to be re-hosted on another parent.

Which is the trap, you typically don't move it to another parent. The control will continue to survive on the parking window, consuming native Windows resources. The garbage collector cannot recover these resources. Eventually your program will crash when Windows refuses to provide more windows to your process. The exception message will say "Error creating handle".

Instead, you must dispose the control. Which also automatically removes the control from its parent. The proper code is:

 while (contentsPanel.Controls.Count > 0) contentsPanel.Controls[0].Dispose();

Or iterate backwards if you find this a bit too bizarre looking.

后知后觉 2024-12-27 19:22:10

每次从集合中删除控件时,集合都会发生变化。当您删除 Controls 的第一个元素时,第二个元素将变为第一个,因此当您继续删除第二个控件时,您实际上是从原始集合中删除第三个元素(跳过第二个元素)。

如果要删除集合中包含的所有控件,请使用 this.contentsPanel.Controls.Clear()。如果您想按 ControlCollection 中的索引删除控件,请首先选择要删除的控件到单独的列表或数组,然后再将其删除。

Each time you remove control from collection, the collection changes. When you remove 1st element of Controls, 2nd element becomes 1st, so when you proceed to delete 2nd control, you are in fact removing 3rd element from original collection (skipping 2nd element).

If you want to remove all controls contained in collection, use this.contentsPanel.Controls.Clear(). If you want to remove controls by their indices in ControlCollection, first select controls to remove to separate list or array and then remove them.

眼趣 2024-12-27 19:22:10

如果你想将它们全部删除,那么就这样做

this.contentsPanel.Controls.Clear()

If you want to remove them all then just do

this.contentsPanel.Controls.Clear()
屌丝范 2024-12-27 19:22:10

foreach 将失败,因为您正在更改集合,这会破坏迭代器。

for 失败,因为您只是删除所有其他项目;考虑:i=0,您删除第零项。现在,曾经第 1 项是第 0 项 - 因此,当您删除第 1 项(下一个循环迭代)时,您已经跳过了第一项。

简短版本:使用 Clear()

contentsPanel.Controls.Clear();

较长版本:向后迭代:

for(int i=contentsPanel.Controls.Count-1; i>=0;i--) {
   contentsPanel.Controls.RemoveAt(i);
}

第一个(Clear)更简单。

The foreach will fail because you are changing the collection, which breaks the iterator.

The for fails because you are only removing every other item; consider: i=0, you remove the zeroth item. Now the item that was item 1 is item 0 - so when you remove item 1 (next loop iteration) you have jumped one.

Short version: use Clear():

contentsPanel.Controls.Clear();

Longer version: iterate backwards:

for(int i=contentsPanel.Controls.Count-1; i>=0;i--) {
   contentsPanel.Controls.RemoveAt(i);
}

The first (Clear) is simpler.

青朷 2024-12-27 19:22:10

在网络浏览器控制的情况下,文件不是免费的
contentPanel.Controls.Clear();
或与
contentPanel.Controls.Remove(i);

使用
while (contentsPanel.Controls.Count > 0) contentPanel.Controls[0].Dispose();

In case of webbrowser control, file is not free with
contentsPanel.Controls.Clear();
or with
contentsPanel.Controls.Remove(i);

use
while (contentsPanel.Controls.Count > 0) contentsPanel.Controls[0].Dispose();

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文