Почему элементы управления не хотят быть удалены? - PullRequest
3 голосов
/ 11 декабря 2011

Я пытаюсь удалить все элементы управления, которые содержатся в моей панели winform, но они просто не хотят, чтобы их удалили - некоторые из них удалены, а некоторые нет. Я уже пробовал 2 подхода и ничего:

  1. Еогеасп

    foreach (Control controlEntry in this.contentsPanel.Controls)
    {
        this.contentsPanel.Controls.Remove(controlEntry);
    }
    
  2. для

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

Почему это происходит?

Ответы [ 4 ]

14 голосов
/ 11 декабря 2011

Вы должны остерегаться кода, подобного этому, удаление элементов управления из их контейнера, как это, приводит к неустранимой утечке ресурсов.Controls.Remove / At () или метод Controls.Clear (), как предлагается другими авторами, удаляет элемент управления из коллекции и повторно размещает его в «окне парковки».В противном случае невидимое окно, в котором родное окно может найти гостеприимный дом без необходимости его разрушения.Готова к повторному размещению у другого родителя.

Какова ловушка, вы обычно не перемещаете ее к другому родителю.Элемент управления будет продолжать работать в окне парковки, потребляя ресурсы Windows.Сборщик мусора не может восстановить эти ресурсы.В конце концов ваша программа потерпит крах, когда Windows откажется предоставить больше окон вашему процессу.В сообщении об исключении будет указано «Ошибка создания дескриптора».

Вместо этого вы должны удалить элемент управления.Который также автоматически удаляет элемент управления из его родителя.Правильный код:

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

Или итерируйте в обратном направлении, если вам кажется, что это выглядит слишком странно.

7 голосов
/ 11 декабря 2011

Каждый раз, когда вы удаляете элемент управления из коллекции, коллекция изменяется. Когда вы удаляете 1-й элемент из Controls, 2-й элемент становится 1-м, поэтому при переходе к удалению 2-го элемента управления вы фактически удаляете 3-й элемент из исходной коллекции (пропуская 2-й элемент).

Если вы хотите удалить все элементы управления, содержащиеся в коллекции, используйте this.contentsPanel.Controls.Clear(). Если вы хотите удалить элементы управления по их индексам в ControlCollection, сначала выберите элементы управления для удаления в отдельный список или массив, а затем удалите их.

4 голосов
/ 11 декабря 2011

Если вы хотите удалить их все, просто сделайте

this.contentsPanel.Controls.Clear()
3 голосов
/ 11 декабря 2011

Сбой foreach, потому что вы меняете коллекцию, что нарушает итератор.

Сбой for, потому что вы удаляете только все остальные элементы; рассмотрим: я = 0, вы удаляете нулевой элемент. Теперь элемент, который был элемент 1, является элементом 0 - поэтому, когда вы удаляете элемент 1 (следующая итерация цикла), вы переходите на один элемент.

Короткая версия: используйте Clear():

contentsPanel.Controls.Clear();

Более длинная версия: итерация назад:

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

Первый (Очистить) проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...