闲话WPF之二六(WPF性能优化点)
在建立漂亮UI的同時,我們還需要關(guān)注應(yīng)用程序的性能,WPF尤其如此。下面從MS的文檔中總結(jié)出了一些有用的性能優(yōu)化點(diǎn)。在實(shí)際編寫的過程中,可以參考。這個Post非完全原創(chuàng),是根據(jù)一些文檔總結(jié)出來的。
1、建立邏輯樹的時候,盡量考慮從父結(jié)點(diǎn)到子結(jié)點(diǎn)的順序構(gòu)建。因為當(dāng)邏輯樹的一個結(jié)點(diǎn)發(fā)生變化時(比如添加或刪除),它的父結(jié)點(diǎn)和所有的子結(jié)點(diǎn)都會激發(fā)Invalidation。我們應(yīng)該避免不必要的Invalidation。
2、當(dāng)我們在列表(比如ListBox)顯示了一個CLR對象列表(比如List)時,如果想在修改List對象后,ListBox也動態(tài)的反映這種變化。此時,我們應(yīng)該使用動態(tài)的ObservableCollection對象綁定。而不是直接的更新ItemSource。兩者的區(qū)別在于直接更新ItemSource會使WPF拋棄ListBox已有的所有數(shù)據(jù),然后全部重新從List加載。而使用ObservableCollection可以避免這種先全部刪除再重載的過程,效率更高。
3、在使用數(shù)據(jù)綁定的過程中,如果綁定的數(shù)據(jù)源是一個CLR對象,屬性也是一個CLR屬性,那么在綁定的時候?qū)ο驝LR對象所實(shí)現(xiàn)的機(jī)制不同,綁定的效率也不同。
A、數(shù)據(jù)源是一個CLR對象,屬性也是一個CLR屬性。對象通過TypeDescriptor/PropertyChanged模式實(shí)現(xiàn)通知功能。此時綁定引擎用TypeDescriptor來反射源對象。效率最低。
B、數(shù)據(jù)源是一個CLR對象,屬性也是一個CLR屬性。對象通過INotifyPropertyChanged實(shí)現(xiàn)通知功能。此時綁定引擎直接反射源對象。效率稍微提高。
C、數(shù)據(jù)源是一個DependencyObject,而且屬性是一個DependencyProperty。此時不需要反射,直接綁定。效率最高。
4、訪問CLR對象和CLR屬性的效率會比訪問DependencyObject/DependencyProperty高。注意這里指的是訪問,不要和前面的綁定混淆了。但是,把屬性注冊為DependencyProperty會有很多的優(yōu)點(diǎn):比如繼承、數(shù)據(jù)綁定和Style。所以有時候我們可以在實(shí)現(xiàn)DependencyProperty的時候,利用緩存機(jī)制來加速訪問速度:看下面的緩存例子:
public static readonly DependencyProperty MagicStringProperty =
??? DependencyProperty.Register("MagicString", typeof(string), typeof(MyButton), new PropertyMetadata(new PropertyInvalidatedCallback(OnMagicStringPropertyInvalidated),new GetValueOverride(MagicStringGetValueCallback)));
?private static void OnMagicStringPropertyInvalidated(DependencyObject d)
? {
??? // 將緩存的數(shù)據(jù)標(biāo)識為無效
??? ((MyButton)d)._magicStringValid = false;
? }
? private static object MagicStringGetValueCallback(DependencyObject d)
? {
??? // 調(diào)用緩存的訪問器來獲取值
??? return ((MyButton)d).MagicString;
? }
? // 私有的CLR訪問器和本地緩存
? public string MagicString
? {
??? get
??? {
????? // 在當(dāng)前值無效時,獲取最新的值保存起來
????? if (!_magicStringValid)
????? {
??????? _magicString = (string)GetValueBase(MagicStringProperty);
??????? _magicStringValid = true;
????? }
????? return _magicString;
??? }
??? set
??? {
????? SetValue(MagicStringProperty, value);
??? }
? }
? private string _magicString;
? private bool _magicStringValid;
另外,因為注冊的DependencyProperty在默認(rèn)是不可繼承的,如果需要繼承特性,也會降低DependencyProperty值刷新的效率。注冊DependencyProperty屬性時,應(yīng)該把DefaultValue傳遞給Register方法的參數(shù)來實(shí)現(xiàn)默認(rèn)值的設(shè)置,而不是在構(gòu)造函數(shù)中設(shè)置。
5、使用元素TextFlow和TextBlock時,如果不需要TextFlow的某些特性,就應(yīng)該考慮使用TextBlock,因為它的效率更高。
6、在TextBlock中顯式的使用Run命令比不使用Run命名的代碼要高。
7、在TextFlow中使用UIElement(比如TextBlock)所需的代價要比使用TextElement(比如Run)的代價高。
8、把Label(標(biāo)簽)元素的ContentProperty和一個字符串(String)綁定的效率要比把字符串和TextBlock的Text屬性綁定的效率低。因為Label在更新字符串是會丟棄原來的字符串,全部重新顯示內(nèi)容。
9、在TextBlock塊使用HyperLinks時,把多個HyperLinks組合在一起效率會更高??聪旅娴膬煞N寫法,后一種效率高。
A、
<TextBlock Width="600" >
? <Hyperlink TextDecorations="None">MSN Home</Hyperlink>
</TextBlock>
<TextBlock Width="600" >
? <Hyperlink TextDecorations="None">My MSN</Hyperlink>
</TextBlock>
B、
<TextBlock Width="600" >
? <Hyperlink TextDecorations="None">MSN Home</Hyperlink>
? <Hyperlink TextDecorations="None">My MSN</Hyperlink>
</TextBlock>
10、任與上面TextDecorations有關(guān),顯示超鏈接的時候,盡量只在IsMouseOver為True的時候顯示下劃線,一直顯示下劃線的代碼高很多。
11、在自定義控件,盡量不要在控件的ResourceDictionary定義資源,而應(yīng)該放在Window或者Application級。因為放在控件中會使每個實(shí)例都保留一份資源的拷貝。
12、如果多個元素使用相同的Brush時,應(yīng)該考慮在資源定義Brush,讓他們共享一個Brush實(shí)例。
13、如果需要修改元素的Opacity屬性,最后修改一個Brush的屬性,然后用這個Brush來填充元素。因為直接修改元素的Opacity會迫使系統(tǒng)創(chuàng)建一個臨時的Surface。
14、在系統(tǒng)中使用大型的3D Surface時,如果不需要Surface的HitTest功能,請關(guān)閉它。因為默認(rèn)的HitTest會占用大量的CPU時間進(jìn)行計算。UIElement有應(yīng)該IsHitTestVisible屬性可以用來關(guān)閉HitTest功能。
轉(zhuǎn)載于:https://www.cnblogs.com/YilingLai/archive/2007/01/19/624714.html
總結(jié)
以上是生活随笔為你收集整理的闲话WPF之二六(WPF性能优化点)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ajax: PopupControlEx
- 下一篇: 学习ASP.NET一定要学习ASP.NE