2015-03-31 38 views
0

我正在處理一個自定義winforms控件,該控件公開了很多影響控件外觀的屬性(不同顏色的背景,文本和不同的狀態,如懸停,點擊以及圖標等)。對其中一個屬性的更改會重新進行重繪,因此此時每個屬性都有一個吸氣器和吸氣器,吸氣器和吸氣器呼叫Invalidate()。這對代碼來說非常煩人,如果多個屬性同時被更改,它們中的每一個都會導致重新繪製,即使重新繪製一次就足夠了。對每個屬性更改都無效()自定義控件?

我有以下想法,但我不知道他們是否是可能的,或者如何實現它們:

  1. 幾毫秒的高速緩存屬性更改,然後Invalidate()
  2. 使用某種反射到檢測呼叫者是否要更換下一行中的另一個屬性,如果是這樣,則將呼叫延遲到Invalidate()
  3. 可能需要重繪屬性之前的某些屬性或所有此類屬性的列表展開爲getters /編譯器在編譯時

如果這些想法有意義/可能,並指出如何實施它們,您能給我一些建議嗎?

+0

_if一次更改多個屬性,_ ??你的意思是代碼而不是用戶?爲此可以使用Suspend/ResumeLayout,否? – TaW 2015-04-01 06:42:41

+0

@TaW是的我的意思是代碼。我不知道掛起/ resumelayout,我會研究它。謝謝 ! – user1950929 2015-04-01 07:11:36

回答

0

只是一個說明,我會遠離選項2.關於選項1,以屬性更改已被系統緩存的方式,它只會在UI線程返回處理消息後重繪。至於方案3,似乎有點牽扯。

但是在回答你的問題時,最簡單的方法就是在你的班級中創建一個計時器,該計時器在給定的時間間隔內啓動。然後有一個布爾,如果它是真的計時器的Tick處理程序將調用Invalidate()並將其設置爲false。最後製作一個你將用來代替Invalidate的方法,它將bool標記爲true。

有可能是我不知道在你的情況的危害,但這裏有一個例子:

public class InvalidationUserControl : UserControl 
{ 
    bool _isInvalid = false; 
    int _data; 
    Timer t = new Timer(); 

    public InvalidationUserControl() 
    { 
     InitializeComponent(); 
     t.Interval = 100; // Go ahead an play with this number, the higher 
         // it is the greater the latency 
     t.Tick += t_Tick; 
     t.Start(); 
    } 

    void InvalidateIfNeeded() 
    { 
     _isInvalid = true; 
    } 

    void t_Tick(object sender, EventArgs e) 
    { 
     if (_isInvalid) 
     { 
      _isInvalid = false; 
      Invalidate(); 
     } 
    } 

    public int Data 
    { 
     get { return _data; } 
     set 
     { 
      _data = value; 
      InvalidateIfNeeded(); 
     } 
    } 
} 

可能有更好的辦法在那裏,但,這是一個快速的解決方案,它可以工作必須是您需要它。

所有你需要做的就是調用InvalidateIfNeeded()而不是Invalidate(),它應該工作。

+0

謝謝,我會試試這個 – user1950929 2015-04-01 07:37:54

+0

當在設計器中刪除控件時,這可能會導致競爭條件。 – 2017-01-10 15:31:59