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. Freezable オブジェクトの例としては、ブラシ、ペン、変換、ジオメトリ、アニメーションなどがあります。Examples of freezable objects include brushes, pens, transformations, geometries, and animations.

Freezable とは何ですか。What Is a Freezable?

Freezable は、固定されていない2つの状態を持つ特殊な種類のオブジェクトです。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. 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 クラスには多くのアプリケーションがありますが、Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) 内の Freezable のオブジェクトのほとんどは、グラフィックスサブシステムに関連しています。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 から継承する型の例には、BrushTransform、および Geometry クラスが含まれます。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. Freezable クラスは、ブラシが、それに対応する生成された低レベルのオブジェクトを検索し、変更されたときにそれらを更新する機能を提供します。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."

Freezable の 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.

注意

すべての Freezable オブジェクトを固定することはできません。Not every Freezable object can be frozen. InvalidOperationExceptionがスローされないようにするには、Freezable オブジェクトの 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

Freezable を変更する必要がなくなった場合は、固定するとパフォーマンス上の利点が得られます。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.

注意

便宜上、freezable オブジェクトは、明示的に固定しない限り、凍結されたままになります。For convenience, freezable objects remain unfrozen unless you explicitly freeze them.

Freezable の使用Using Freezables

凍結されていない freezable の使用は、他の種類のオブジェクトを使用するのと似ています。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

Freezable の凍結Freezing a Freezable

Freezable 変更不可能な状態にするには、その Freeze メソッドを呼び出します。To make a Freezable unmodifiable, you call its Freeze method. Freezable オブジェクトを含むオブジェクトを固定すると、それらのオブジェクトも固定されます。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.

次のいずれかに該当する場合、Freezable をフリーズすることはできません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.

Freezable の Freeze メソッドを呼び出すと、変更できなくなります。Once you call a freezable's Freeze method, it can no longer be modified. 固定されたオブジェクトを変更しようとすると、InvalidOperationException がスローされます。Attempting 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


前のコード例では、Clone メソッドを使用して、固定されたオブジェクトで変更可能なコピーを作成しました。In 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 はアニメーション化できないため、Storyboardでアニメーション化しようとすると、固定された Freezable オブジェクトの変更可能な複製がアニメーションシステムによって自動的に作成されます。Because 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/options] にマップする必要があります。To 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: Ignorable 属性を使用して 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: Ignorable 属性」ページを参照してください。For more information, see the mc:Ignorable Attribute page.

Freezable の "固定解除""Unfreezing" a Freezable

固定された Freezable は、変更したり、凍結解除したりすることはできません。ただし、Clone または CloneCurrentValue 方法を使用して、凍結解除された複製を作成することができます。Once 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. ブラシでは、Clone メソッドを使用して、固定されていないコピーが作成されます。An 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

注意

使用する複製方法に関係なく、アニメーションは新しい Freezableにコピーされません。Regardless of which clone method you use, animations are never copied to the new Freezable.

Clone メソッドと CloneCurrentValue メソッドは、freezable のディープコピーを作成します。The Clone and CloneCurrentValue methods produce deep copies of the freezable. Freezable に他のフリーズした 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.

独自の Freezable クラスを作成する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とは異なり、Freezable オブジェクトは、サブプロパティ値が変更したときに変更通知を提供します。Detailed change notification: Unlike other DependencyObjects, Freezable objects provide change notifications when sub-property values change.

  • 簡単な複製: Freezable クラスには、ディープクローンを生成するいくつかのメソッドが既に実装されています。Easy cloning: the Freezable class has already implemented several methods that produce deep clones.

FreezableDependencyObjectの一種であるため、依存関係プロパティシステムを使用します。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. (API で WritePreamble を呼び出した後に、依存関係のないプロパティのデータメンバーも読み取る場合は、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 オブジェクトである非依存プロパティデータメンバーが含まれている場合は、メンバーを nullに設定している場合でも、値のいずれかを変更するたびに OnFreezablePropertyChanged メソッドを呼び出す必要があります。If 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