2013-07-23 69 views
0

我正在WPF中編寫自定義控件。該控件具有多個屬性,可以更新控件的邏輯樹。有這種形式的幾種方法:避免頻繁更新WPF自定義控件

private static void OnXXXPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
{ 
    ((MyControl)obj).RebuildTree(); 
} 

假設RebuildTree()方法是非常複雜的,lenghty如果用戶改變了幾個屬性,這種方法稱爲多次造成應用減速和懸掛。

我想介紹一些類似於BeginUpdate()EndUpdate()方法的Windows窗體方式(以確保更新只被調用一次),但是這種做法在WPF中被廣泛阻擋。

我知道渲染具有較低的優先級和閃爍可能不會出現,但仍爲什麼要通過調用相同的更新方法多次糟蹋寶貴的運行時間?

是否有關於如何進行多依賴屬性的有效的更新任何官方的最佳實踐(而不更新設置每一個後整個控制)?

+0

張貼了'RebuildTree()'方法的代碼。另外,你的自定義控件是做什麼的? –

+0

@HighCore該方法創建一個複雜的3D模型(大量點),然後創建幾個控件,每個控件都具有自定義着色器效果。我沒有一個完整的代碼,但我想解決這個一般問題(例如,想象一下,每次調用它時,該方法都會創建1 000個控件)。我希望應用程序在所有屬性都設置完畢後才向用戶顯示最終結果,而不是中間步驟以及所有應該在「引擎蓋下」發生的事情。 – Libor

回答

2

只需設置一個標誌,當這些屬性發生了變化,並有刷新方法排隊到調度一次。

private static void OnXXXPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
{ 
    ((MyControl)obj).NeedsRefresh = true; 
    ((MyControl)obj).OnNeedsRefresh(); 
} 

void OnNeedsRefresh() 
{ 
    Dispatcher.BeginInvoke((Action)(() => 
    { 
    if (NeedsRefresh) 
    { 
     NeedsRefresh = false; 
     RebuildTree(); 
    } 
    }),DispatcherPriority.ContextIdle); 
} 

這樣一來,所有的屬性將被更新,然後調度人員會打電話給你BeginInvoke,該標誌設置爲false,並刷新一次。

+0

一個聰明的把戲。還有一個缺點:在設置完第一個屬性之後,刷新完成,並且由於'NeedsRefresh'標誌,所以其他刷新調用被避免。 _last_屬性設置後,理想狀態將會更新。不管怎麼說,還是要謝謝你。也許在'Binding'中有''Delay''屬性,在提交任何更改之前會等待一定的時間。但是如果在WPF中沒有標準的方法,我會添加自定義的'BeginUpdate'和'EndUpdate' - 這會使用戶得到最優化。 – Libor

+0

@Libor'還有一個缺點是,在設置完第一個屬性後刷新完成,其他調用因爲NeedsRefresh標誌而被刪除 - 我不明白。 ContextIdle優先級應該強制所有綁定更新PRIOR來調用Refresh()。這就是你想要的嗎? –

+0

哦,我明白了。我會嘗試優先級設置。 – Libor