Freezable 物件概觀Freezable Objects Overview

本主題說明如何有效使用和建立 Freezable 物件,這些物件會提供可協助改善應用程式效能的特殊功能。This topic describes how to effectively use and create Freezable objects, which provide special features that can help improve application performance. 凍結物件的範例包括筆刷、畫筆、轉換、幾何和動畫。Examples of freezable objects include brushes, pens, transformations, geometries, and animations.

什麼是可凍結的?What Is a Freezable?

Freezable是一種特殊類型的物件,具有兩種狀態:凍結和凍結。A Freezable is a special type of object that has two states: unfrozen and frozen. 當凍結時, Freezable 看起來像任何其他物件一樣。When unfrozen, a Freezable appears to behave like any other object. 當凍結時,無法 Freezable 再修改。When frozen, a Freezable can no longer be modified.

Freezable 提供 Changed 事件,以通知觀察者對物件所做的任何修改。A Freezable provides a Changed event to notify observers of any modifications to the object. 凍結 a Freezable 可以改善其效能,因為不再需要花費資源來變更通知。Freezing a Freezable can improve its performance, because it no longer needs to spend resources on change notifications. 凍結 Freezable 也可以線上程之間共用,但 Freezable 無法凍結。A frozen Freezable can also be shared across threads, while an unfrozen Freezable cannot.

雖然 Freezable 類別有許多應用程式,但 Freezable 中的大部分物件 Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) 都與圖形子系統相關。Although the Freezable class has many applications, most Freezable objects in Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) are related to the graphics sub-system.

Freezable類別可讓您更輕鬆地使用特定圖形系統物件,並且有助於改善應用程式效能。The Freezable class makes it easier to use certain graphics system objects and can help improve application performance. 繼承自的類型範例 Freezable 包括 BrushTransformGeometry 類別。Examples of types that inherit from Freezable include the Brush, Transform, and Geometry classes. 因為它們包含未受管理的資源,所以系統必須監視這些物件以進行修改,然後在原始物件有變更時,更新其對應的非受控資源。Because they contain unmanaged resources, the system must monitor these objects for modifications, and then update their corresponding unmanaged resources when there is a change to the original object. 即使您不會實際修改圖形系統物件,系統仍然必須花一些資源來監視物件,以防您變更它。Even if you don't actually modify a graphics system object, the system must still spend some of its resources monitoring the object, in case you do change it.

例如,假設您建立 SolidColorBrush 筆刷,然後用它來繪製按鈕的背景。For example, suppose you create a SolidColorBrush brush and use it to paint the background of a button.

Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
myButton.Background = myBrush;
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)
myButton.Background = myBrush

當轉譯按鈕時, WPFWPF 圖形子系統會使用您提供的資訊來繪製一組圖元,以建立按鈕的外觀。When the button is rendered, the WPFWPF graphics sub-system uses the information you provided to paint a group of pixels to create the appearance of a button. 雖然您使用單色筆刷來描述按鈕的繪製方式,但您的純色筆刷實際上並不會進行繪製。Although you used a solid color brush to describe how the button should be painted, your solid color brush doesn't actually do the painting. 圖形系統會為按鈕和筆刷產生快速、低層級的物件,而這是實際顯示在畫面上的物件。The graphics system generates fast, low-level objects for the button and the brush, and it is those objects that actually appear on the screen.

如果您要修改筆刷,則必須重新產生這些低層級的物件。If you were to modify the brush, those low-level objects would have to be regenerated. 可凍結的類別可讓筆刷找出其對應的已產生、低層級的物件,並在變更時加以更新。The freezable class is what gives a brush the ability to find its corresponding generated, low-level objects and to update them when it changes. 啟用這項功能時,筆刷稱為「未凍結」。When this ability is enabled, the brush is said to be "unfrozen."

可凍結的 Freeze 方法可讓您停用此自我更新功能。A freezable's Freeze method enables you to disable this self-updating ability. 您可以使用這個方法,讓筆刷變成「凍結」或無法修改。You can use this method to make the brush become "frozen," or unmodifiable.

注意

並非每個可凍結的物件都可以凍結。Not every Freezable object can be frozen. 若要避免擲 InvalidOperationException 回,請檢查可凍結物件的屬性值, CanFreeze 以判斷是否可以在嘗試凍結之前加以凍結。To avoid throwing an InvalidOperationException, check the value of the Freezable object's CanFreeze property to determine whether it can be frozen before attempting to freeze it.

if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}
If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If

當您不再需要修改可凍結時,凍結它可提供效能優勢。When you no longer need to modify a freezable, freezing it provides performance benefits. 如果您在此範例中凍結筆刷,圖形系統將不再需要監視它是否有變更。If you were to freeze the brush in this example, the graphics system would no longer need to monitor it for changes. 圖形系統也可以進行其他優化,因為它知道筆刷不會變更。The graphics system can also make other optimizations, because it knows the brush won't change.

注意

為了方便起見,可凍結的物件會保持未凍結,除非您明確凍結它們。For convenience, freezable objects remain unfrozen unless you explicitly freeze them.

使用 FreezableUsing Freezables

使用未凍結的可凍結類似于使用任何其他類型的物件。Using an unfrozen freezable is like using any other type of object. 在下列範例中,的色彩 SolidColorBrush 會在用來繪製按鈕的背景之後,從黃色變更為紅色。In the following example, the color of a SolidColorBrush is changed from yellow to red after it's used to paint the background of a button. 圖形系統會在幕後運作,以在下次螢幕重新整理時,自動將按鈕從黃色變更為紅色。The graphics system works behind the scenes to automatically change the button from yellow to red the next time the screen is refreshed.

Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
myButton.Background = myBrush;

// Changes the button's background to red.
myBrush.Color = Colors.Red;
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)
myButton.Background = myBrush


' Changes the button's background to red.
myBrush.Color = Colors.Red

凍結凍結Freezing a Freezable

若要使無法 Freezable 修改,您可以呼叫其 Freeze 方法。To make a Freezable unmodifiable, you call its Freeze method. 當您凍結包含可凍結物件的物件時,這些物件也會被凍結。When you freeze an object that contains freezable objects, those objects are frozen as well. 例如,如果您凍結 PathGeometry ,它所包含的資料和區段也會被凍結。For example, if you freeze a PathGeometry, the figures and segments it contains would be frozen too.

如果下列任一條件成立,則 無法 凍結凍結:A Freezable can't be frozen if any of the following are true:

  • 它有動畫或資料系結屬性。It has animated or data bound properties.

  • 它具有動態資源所設定的屬性。It has properties set by a dynamic resource. (如需動態資源的詳細資訊,請參閱 XAML 資源 。 ) (See the XAML Resources for more information about dynamic resources.)

  • 它包含 Freezable 無法凍結的子物件。It contains Freezable sub-objects that can't be frozen.

如果這些條件為 false,而您不想要修改 Freezable ,則應該凍結它以獲得稍早所述的效能優勢。If these conditions are false, and you don't intend to modify the Freezable, then you should freeze it to gain the performance benefits described earlier.

一旦您呼叫可凍結的 Freeze 方法之後,就無法再修改它。Once you call a freezable's Freeze method, it can no longer be modified. 嘗試修改凍結的物件會導致擲回 InvalidOperationExceptionAttempting to modify a frozen object causes an InvalidOperationException to be thrown. 下列程式碼會擲回例外狀況,因為我們會在凍結之後嘗試修改筆刷。The following code throws an exception, because we attempt to modify the brush after it's been frozen.


Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);

if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}

myButton.Background = myBrush;

try {

    // Throws an InvalidOperationException, because the brush is frozen.
    myBrush.Color = Colors.Red;
}catch(InvalidOperationException ex)
{
    MessageBox.Show("Invalid operation: " + ex.ToString());
}


Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)

If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If

myButton.Background = myBrush

Try

    ' Throws an InvalidOperationException, because the brush is frozen.
    myBrush.Color = Colors.Red
Catch ex As InvalidOperationException
    MessageBox.Show("Invalid operation: " & ex.ToString())
End Try

若要避免擲回這個例外狀況,您可以使用 IsFrozen 方法來判斷是否 Freezable 已凍結。To avoid throwing this exception, you can use the IsFrozen method to determine whether a Freezable is frozen.


Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);

if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}

myButton.Background = myBrush;

if (myBrush.IsFrozen) // Evaluates to true.
{
    // If the brush is frozen, create a clone and
    // modify the clone.
    SolidColorBrush myBrushClone = myBrush.Clone();
    myBrushClone.Color = Colors.Red;
    myButton.Background = myBrushClone;
}
else
{
    // If the brush is not frozen,
    // it can be modified directly.
    myBrush.Color = Colors.Red;
}


Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)

If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If

myButton.Background = myBrush


If myBrush.IsFrozen Then ' Evaluates to true.
    ' If the brush is frozen, create a clone and
    ' modify the clone.
    Dim myBrushClone As SolidColorBrush = myBrush.Clone()
    myBrushClone.Color = Colors.Red
    myButton.Background = myBrushClone
Else
    ' If the brush is not frozen,
    ' it can be modified directly.
    myBrush.Color = Colors.Red
End If


在上述程式碼範例中,使用方法將已凍結的物件製作成可修改的複本 CloneIn the preceding code example, a modifiable copy was made of a frozen object using the Clone method. 下一節會更詳細地討論複製。The next section discusses cloning in more detail.

注意

由於凍結的可凍結無法進行動畫,因此 Freezable 當您嘗試以動畫顯示時,動畫系統會自動建立已凍結物件的可修改複本 StoryboardBecause a frozen freezable cannot be animated, the animation system will automatically create modifiable clones of frozen Freezable objects when you try to animate them with a Storyboard. 為了消除複製所造成的效能負擔,如果您想要以動畫顯示物件,請將物件保持未凍結。To eliminate the performance overhead caused by cloning, leave an object unfrozen if you intend to animate it. 如需使用分鏡腳本進行動畫的詳細資訊,請參閱分鏡腳本 總覽For more information about animating with storyboards, see the Storyboards Overview.

從標記凍結Freezing from Markup

若要凍結 Freezable 標記中宣告的物件,請使用 PresentationOptions:Freeze 屬性。To freeze a Freezable object declared in markup, you use the PresentationOptions:Freeze attribute. 在下列範例中, SolidColorBrush 會將宣告為頁面資源並凍結。In the following example, a SolidColorBrush is declared as a page resource and frozen. 然後,它會用來設定按鈕的背景。It is then used to set the background of a button.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" 
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="PresentationOptions">

  <Page.Resources>

    <!-- This resource is frozen. -->
    <SolidColorBrush 
      x:Key="MyBrush"
      PresentationOptions:Freeze="True" 
      Color="Red" />
  </Page.Resources>


  <StackPanel>

    <Button Content="A Button" 
      Background="{StaticResource MyBrush}">
    </Button>

  </StackPanel>
</Page>

若要使用 Freeze 屬性,您必須對應至表示選項命名空間: http://schemas.microsoft.com/winfx/2006/xaml/presentation/optionsTo use the Freeze attribute, you must map to the presentation options namespace: http://schemas.microsoft.com/winfx/2006/xaml/presentation/options. PresentationOptions 是對應此命名空間的建議前置詞:PresentationOptions is the recommended prefix for mapping this namespace:

xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"

由於並非所有的 XAML 讀取器都會辨識此屬性,建議您使用 mc:可忽略屬性 將屬性標示為可 Presentation:Freeze 忽略:Because not all XAML readers recognize this attribute, it's recommended that you use the mc:Ignorable Attribute to mark the Presentation:Freeze attribute as ignorable:

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"

如需詳細資訊,請參閱 mc:可忽略的屬性 頁面。For more information, see the mc:Ignorable Attribute page.

「解除凍結」是凍結的"Unfreezing" a Freezable

一旦凍結,就 Freezable 永遠不能修改或解除凍結,不過,您可以使用或方法來建立未凍結的複製 Clone CloneCurrentValueOnce frozen, a Freezable can never be modified or unfrozen; however, you can create an unfrozen clone using the Clone or CloneCurrentValue method.

在下列範例中,會使用筆刷設定按鈕的背景,然後將筆刷凍結。In the following example, the button's background is set with a brush and that brush is then frozen. 未凍結的複製會使用方法來建立筆刷 CloneAn unfrozen copy is made of the brush using the Clone method. 複製會被修改,並用來將按鈕的背景從黃色變更為紅色。The clone is modified and used to change the button's background from yellow to red.

Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);

// Freezing a Freezable before it provides
// performance improvements if you don't
// intend on modifying it.
if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}

myButton.Background = myBrush;

// If you need to modify a frozen brush,
// the Clone method can be used to
// create a modifiable copy.
SolidColorBrush myBrushClone = myBrush.Clone();

// Changing myBrushClone does not change
// the color of myButton, because its
// background is still set by myBrush.
myBrushClone.Color = Colors.Red;

// Replacing myBrush with myBrushClone
// makes the button change to red.
myButton.Background = myBrushClone;
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)

' Freezing a Freezable before it provides
' performance improvements if you don't
' intend on modifying it. 
If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If


myButton.Background = myBrush

' If you need to modify a frozen brush,
' the Clone method can be used to
' create a modifiable copy.
Dim myBrushClone As SolidColorBrush = myBrush.Clone()

' Changing myBrushClone does not change
' the color of myButton, because its
' background is still set by myBrush.
myBrushClone.Color = Colors.Red

' Replacing myBrush with myBrushClone
' makes the button change to red.
myButton.Background = myBrushClone

注意

無論您使用哪一個複製方法,動畫都不會複製到新的 FreezableRegardless of which clone method you use, animations are never copied to the new Freezable.

CloneCloneCurrentValue 方法會產生無法凍結的深層複本。The Clone and CloneCurrentValue methods produce deep copies of the freezable. 如果可凍結的物件包含其他凍結的可凍結物件,則它們也會進行複製和修改。If the freezable contains other frozen freezable objects, they are also cloned and made modifiable. 例如,如果您複製凍結 PathGeometry 以使其成為可修改的,則它所包含的資料和區段也會複製並變成可修改。For example, if you clone a frozen PathGeometry to make it modifiable, the figures and segments it contains are also copied and made modifiable.

建立您自己的凍結類別Creating Your Own Freezable Class

衍生自的類別會 Freezable 取得下列功能。A class that derives from Freezable gains the following features.

  • 特殊狀態:唯讀 (凍結) 和可寫入狀態。Special states: a read-only (frozen) and a writable state.

  • 執行緒安全:凍結 Freezable 可以跨執行緒共用。Thread safety: a frozen Freezable can be shared across threads.

  • 詳細的變更通知:與其他 DependencyObject 的不同,可凍結的物件會在子屬性值變更時提供變更通知。Detailed change notification: Unlike other DependencyObjects, Freezable objects provide change notifications when sub-property values change.

  • 簡易複製:可凍結的類別已執行數個產生深層複製的方法。Easy cloning: the Freezable class has already implemented several methods that produce deep clones.

Freezable是的型別 DependencyObject ,因此會使用相依性屬性系統。A Freezable is a type of DependencyObject, and therefore uses the dependency property system. 您的類別屬性不必是相依性屬性,但使用相依性屬性將會減少您必須撰寫的程式碼數量,因為 Freezable 類別是以相依性屬性為考慮而設計的。Your class properties don't have to be dependency properties, but using dependency properties will reduce the amount of code you have to write, because the Freezable class was designed with dependency properties in mind. 如需相依性屬性系統的詳細資訊,請參閱相依性 屬性總覽For more information about the dependency property system, see the Dependency Properties Overview.

每個子 Freezable 類別都必須覆寫 CreateInstanceCore 方法。Every Freezable subclass must override the CreateInstanceCore method. 如果您的類別使用其所有資料的相依性屬性,您就會完成。If your class uses dependency properties for all its data, you're finished.

如果您的類別包含非相依性屬性資料成員,您也必須覆寫下列方法:If your class contains non-dependency property data members, you must also override the following methods:

您也必須觀察下列用來存取和寫入非相依性屬性之資料成員的規則:You must also observe the following rules for accessing and writing to data members that are not dependency properties:

  • 在任何讀取非相依性屬性資料成員的 API 開頭,呼叫 ReadPreamble 方法。At the beginning of any API that reads non-dependency property data members, call the ReadPreamble method.

  • 在任何撰寫非相依性屬性資料成員的 API 開頭,呼叫 WritePreamble 方法。At the beginning of any API that writes non-dependency property data members, call the WritePreamble method. (WritePreamble 在 API 中呼叫之後, ReadPreamble 如果您也讀取非相依性屬性資料成員,就不需要另外進行呼叫。 ) (Once you've called WritePreamble in an API, you don't need to make an additional call to ReadPreamble if you also read non-dependency property data members.)

  • 在結束 WritePostscript 寫入非相依性屬性資料成員的方法之前,請先呼叫方法。Call the WritePostscript method before exiting methods that write to non-dependency property data members.

如果您的類別包含屬於物件的非相依性屬性資料成員 DependencyObject ,則您也必須在 OnFreezablePropertyChanged 每次變更其中一個值時呼叫方法,即使您要將成員設定為 nullIf your class contains non-dependency-property data members that are DependencyObject objects, you must also call the OnFreezablePropertyChanged method each time you change one of their values, even if you're setting the member to null.

注意

Freezable使用基底執行的呼叫來開始您覆寫的每個方法,是很重要的。It's very important that you begin each Freezable method you override with a call to the base implementation.

如需自訂類別的範例 Freezable ,請參閱 自訂動畫範例For an example of a custom Freezable class, see the Custom Animation Sample.

另請參閱See also