Удаление динамично созданных средств управления в C#

У меня есть программа, которая добавляет серию "вспышек" к графику:

PictureBox blip = new PictureBox();
blip.Location = new Point(blipHours, blipAltitude);
blip.Size = new Size(6, 6);
blip.BackColor = System.Drawing.Color.Lime;
blip.Text = "";
blip.Name = callsign;
this.Controls.Add(blip);
this.Controls.SetChildIndex(blip, 0);
  1. Как у меня есть кнопка ясной все "вспышки", которые были созданы с этим кодом?

  2. Есть ли способ изменить цвет фона вспышки, когда его имя равно определенному callsign? Каждая вспышка связана с выбором в a ListBox, и я хотел бы изменить цвет вспышки, когда пользователь выбирает его.

6
задан Peter Mortensen 29 October 2017 в 14:09
поделиться

4 ответа

Все забывают очень важную деталь: вам нужно Dispose () элемента управления, иначе он будет протекать вечно:

for (int ix = this.Controls.Count - 1; ix >= 0; ix--) {
    if (this.Controls[ix] is PictureBox) this.Controls[ix].Dispose();
}

Я уделю больше внимания forever , много шума по этому поводу в комментариях, класс Control не ведет себя как любой другой класс .NET. Control поддерживается своим свойством Handle . В котором хранится собственный дескриптор Windows. Пока существует собственное окно, объект Control не может быть уничтожен.

Это требует, чтобы объект поддерживался искусственно, когда вы используете Clear () или Remove () и удаляете элемент управления из его родительского элемента. Winforms использует так называемое «окно парковки» в качестве узла таких элементов управления. Это обычное родное окно, как и любое другое, просто его не видно. Его работа состоит в том, чтобы быть родителем таких осиротевших элементов управления.

Окно парковки позволяет выполнять множество изящных трюков, которые обычно очень сложно выполнить в Windows. Например, вы можете включать и выключать свойство ShowInTaskbar во время выполнения. Свойство окна, которое обычно можно указать только при создании окна (стиль WS_EX_APPWINDOW, указанный в вызове CreateWindowEx ()). Winforms может сделать это даже после того, как вы создали окно, перемещая элементы управления формы в окно парковки, уничтожая окно, создавая его снова и перемещая элементы управления назад. Аккуратный.

Но с не очень аккуратным зависанием, о котором идет речь в этом ответе, если вы удалите элемент управления и не вызовите его метод Dispose (), он продолжит работать в окне парковки. . Навсегда. Настоящая утечка. Сборщик мусора ничего не может с этим поделать, он видит действительную ссылку на объект. Довольно грубое нарушение контракта IDisposable, вызов Dispose () является необязательным, но это не для класса Control.

К счастью, такую ​​ошибку довольно легко диагностировать, она не требует каких-либо специальных инструментов. Вы можете увидеть утечку на вкладке «Процессы» диспетчера задач. Добавьте столбец «Объекты ПОЛЬЗОВАТЕЛЯ».

25
ответ дан 8 December 2019 в 02:46
поделиться
this.Controls.Clear();
4
ответ дан 8 December 2019 в 02:46
поделиться

Возможно, вы захотите добавить фрагмент в Список, а затем, когда пользователь нажмет кнопку "Очистить", просто провести итерацию по списку, удалить фрагмент из коллекции элементов управления, а затем очистить список.

Что касается изменения цвета фона, почему бы вам просто не использовать утверждение if?

blip.BackColor = callsign == "SpecialSign"? System.Drawing.Color.Red : System.Drawing.Color.Lime
2
ответ дан 8 December 2019 в 02:46
поделиться

Это приведет к удалению всех элементов управления PictureBox из конкретного контейнера (в вашем случае я предполагаю, что это график).

 for (int i = this.Controls.Count - 1; i >= 0; i--)
            {
                PictureBox control = this.Controls[i] as PictureBox;
                if (control == null)
                    continue;

                control.Dispose();
            }
2
ответ дан 8 December 2019 в 02:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: