MD5的全稱是message-digest algorithm 5,MD5演算法屬於hash演算法的一類,對消息進行運算,產生一個128位的消息摘要(32位數字字母),並且加密不可逆,相同數據的加密結果一定相同。 C# 實現MD5加密。MD5加密16位和32位 ...
Freezable是WPF中一個特殊的基類,用於創建可以凍結(Freeze)的可變對象。凍結一個對象意味著將其狀態設置為只讀,從而提高性能並允許在多線程環境中共用對象。
Freezable的應用
我們定義畫刷資源的時候常常會這樣寫:
<SolidColorBrush x:Key="RedBrush" Color="Red" o:Freeze="True"/>
代碼中的o:Freeze="True"
其實就是使用Freezable
的 Freeze
方法凍結畫刷,使之不可修改,系統不必監視該畫刷對象,從而減少資源消耗。
o:Freeze="True"
乍一看像附加屬性,其實並不是的。Freeze
屬性是http://schemas.microsoft.com/winfx/2006/xaml/presentation/options
XML命名空間中定義的唯一屬性或其他編程元素。Freeze
屬性專門存在於此特殊命名空間中,以便在根元素聲明中可以使用。處理Freeze
屬性的功能專門內置於處理已編譯應用程式的 XAML的XAML處理器中。
那是不是WPF中的所有資源都可以(需要)使用Freeze
方法凍結來提高性能呢?
Freezable類通常用於WPF中的資源和動畫,例如創建可重用的畫刷、幾何圖形和動畫。從Freezable
繼承的類型包括Brush
、Transform
和Geometry
類。由於它們包含非托管資源,因此系統必須監視這些對象發生的修改,然後在原始對象發生更改時更新對應的非托管資源。即使實際上並未修改圖形系統對象,系統仍必須消耗一些資源來監視該對象,以防更改它。
例如,假設創建一個SolidColorBrush畫筆並用它來繪製按鈕的背景。
<Window.Resources>
<SolidColorBrush x:Key="RedBrush" Color="Red"/>
</Window.Resources>
<Button Background="{StaticResource RedBrush}"/>
呈現按鈕時,WPF圖形子系統使用你提供的信息來繪製一組像素,以創建按鈕的外觀。儘管使用純色畫筆來描述按鈕的繪製方式,但純色畫筆實際上並沒有進行繪製。圖形系統為按鈕和畫筆生成快速、低級別的對象,實際顯示在屏幕上的就是這些對象。
如果要修改畫筆,則必須重新生成這些低級別對象。Freezable
類使畫筆能夠找到生成的相應低級別對象併在更改時更新它們。
註意事項
並非每個Freezable
對象都可以凍結。為避免引發InvalidOperationException
,請在嘗試凍結Freezable
對象之前檢查該對象的CanFreeze屬性值,以確定是否可以將其凍結。如果滿足以下任一條件,則無法凍結Freezable:
- 它具有動畫屬性或數據綁定屬性。
- 它具有由動態資源設置的屬性。
- 它包含無法凍結的Freezable子對象。
Freezable
對象調用Freeze
方法凍結後,就無法解凍。修改凍結對象屬性時會引發InvalidOperationException
。但是,可以使用Clone
或CloneCurrentValue
方法創建(深拷貝)解凍的副本。如果Freezable
包含其他已凍結的 Freezable
對象,它們也會被克隆並變為可修改。
無論使用哪種克隆方法,動畫都不會複製到新的 Freezable。
由於無法對凍結的Freezable
進行動畫處理,因此使用Storyboard
對其進行動畫處理時,動畫系統會自動創建凍結的Freezable
對象的可修改克隆。為了消除克隆導致的性能開銷,如果需要對對象進行動畫處理,請讓其保持解凍狀態。
附加屬性實現XAML中Freeze
上文中提到o:Freeze="True"
並不是通過附加屬性實現,而是內置於XAML處理器中實現。我們自己也可以通過附加屬性的方式實現,代碼如下:
public class PresentationOptionsAttach
{
public static bool GetFreeze(Freezable freezable)
{
return (bool)freezable.GetValue(FreezeProperty);
}
public static void SetFreeze(Freezable freezable, bool value)
{
freezable.SetValue(FreezeProperty, value);
}
public static readonly DependencyProperty FreezeProperty =
DependencyProperty.RegisterAttached("Freeze", typeof(bool), typeof(PresentationOptionsAttach), new PropertyMetadata(false, OnFreezeChanged));
private static void OnFreezeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (DesignerProperties.GetIsInDesignMode(d)) return;
if ((bool)e.NewValue)
{
Freezable freezable = d as Freezable;
if (freezable.CanFreeze)
freezable.Freeze();
}
}
}
小結
Freezable
是一個我們既熟悉又陌生的類,熟悉是因為我們經常使用,陌生是因為很少關註其優化性能的機制以及需要註意的地方。本文簡單介紹了Freezable
優化性能的機制以及註意事項,並提供了通過附加屬性的方式在XAML中凍結資源(純屬探索,實際意義不大)。