2010-01-06 34 views
6

我有一個程序,增加了一系列的「光點」的一個圖:在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時,是否有方法更改blip的背景顏色?每個blip都與ListBox中的選擇相關聯,並且我想在用戶選擇它時更改blip的顏色。

回答

24

每個人都忘記了一個非常重要細節:你要的Dispose()的控制,否則將永遠泄漏:

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

我會放一些更強調永遠是子句,在評論中對它有很多的鼓譟,Control類不像任何其他的.NET類。一個控件通過其Handle屬性保持活着。其中存儲本地Windows句柄。只要本地窗口存在,Control對象就不能被銷燬。

這需要在使用Clear()或Remove()並將控件從其父項中移除時人爲地保持活動狀態。 Winforms使用所謂的「停車窗口」作爲這種控件的主機。這是一個普通的本地窗口,就像任何其他窗口一樣,它只是不可見。它的工作就是成爲這種孤兒控制的母體。

停車窗口允許很多整潔的技巧,通常很難在Windows中完成。例如,您可以在運行時打開和關閉ShowInTaskbar屬性。通常只能在創建窗口時指定的窗口屬性(在CreateWindowEx()調用中指定的WS_EX_APPWINDOW樣式)。即使在創建窗口後,Winforms也可以將窗體的控件移動到停靠窗口,破壞窗口,再次創建窗體並將控件移回。整齊。

但是對於這個答案的主題不太清楚的掛斷,如果您刪除控件並且不要調用它的Dispose()方法,那麼它將繼續在停車窗口中生存。永遠。真實的泄漏。垃圾收集器無法做到這一點,它會看到對該對象的有效引用。對於IDisposable合同的嚴重違反,調用Dispose()是可選的,但對於Control類,它不是而是

幸運的是,這樣的錯誤很容易診斷,它不需要任何特殊的工具,您可以在任務管理器的進程選項卡中看到泄漏。添加「USER對象」列。

+1

+ 1 ..感謝,完全忘了。實際上控件的配置方法調用parent.Controls.Remove(this) – 2010-01-06 16:38:37

+1

它不會永遠泄漏......它只會在垃圾收集器出現之前泄漏......然後希望PictureBox的析構函數包含對Dispose的調用。 – Nick 2010-01-06 16:38:38

+1

@Stan R - 它呢?很酷......我不知道! – Nick 2010-01-06 16:39:30

4
this.Controls.Clear(); 
+2

可選的,因爲控制和動態創建,「清除」按鈕,可以簡單地只是重建與完全回發的控制沒有什麼。 – NotMe 2010-01-06 16:16:17

+0

這將刪除所有的控件,不管它們是否是PictureBox。 – 2010-01-06 16:17:34

+0

這將清除所有控件。我只想清除創建的「blip」控件。 – Brodie 2010-01-06 16:18:23

2

您可能希望將曇花一現添加到列表中,然後當用戶點擊「清除」按鈕,只需遍歷列表,請從控件集合的曇花一現,然後清除列表。

就改變背景顏色而言,爲什麼不使用if語句?

blip.BackColor = callsign == "SpecialSign"? System.Drawing.Color.Red : System.Drawing.Color.Lime 
+0

Jonathan Keith提到this.Controls.Clear()可能有效,但取決於(this)的上下文,也可能會清除其他控件。但是,如果上下文允許,喬納森的答案可能需要少兩個時鐘週期。 – hackerhasid 2010-01-06 16:15:55

3

這將刪除所有來自特定容器中的圖片框控件的(ⅰ假設你的情況的曲線圖)。

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

       control.Dispose(); 
      } 
0

Hans Passant似乎忘記了一個非常重要的細節(或者他只是增加了現有的答案,沒有提交完整的答案)。無論如何,這是我必須做既invisiblize和處置我的動態控制:

Panel p = tp.Controls[panelName] as Panel; 
p.Controls.Clear(); 
for (int i = 0; i < p.Controls.Count; i++) 
{ 
    p.Controls[i].Dispose(); 
} 
+0

他忘記了什麼是非常重要的細節? – 2017-10-29 16:29:54