--- title: "Freezable Objects Overview" ms.date: "03/30/2017" ms.topic: overview dev_langs: - "csharp" - "vb" helpviewer_keywords: - "Freezable objects [WPF], description" - "unfreezing Freezable objects [WPF]" - "classes [WPF], Freezable" ms.assetid: 89c71692-4f43-4057-b611-67c6a8a863a2 --- # Freezable Objects Overview This topic describes how to effectively use and create 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? A is a special type of object that has two states: unfrozen and frozen. When unfrozen, a appears to behave like any other object. When frozen, a can no longer be modified. A provides a event to notify observers of any modifications to the object. Freezing a can improve its performance, because it no longer needs to spend resources on change notifications. A frozen can also be shared across threads, while an unfrozen cannot. Although the class has many applications, most objects in [!INCLUDE[TLA#tla_winclient](../../../includes/tlasharptla-winclient-md.md)] are related to the graphics sub-system. The class makes it easier to use certain graphics system objects and can help improve application performance. Examples of types that inherit from include the , , and 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. For example, suppose you create a brush and use it to paint the background of a button. [!code-csharp[freezablesample_procedural#FrozenExamplePart1](~/samples/snippets/csharp/VS_Snippets_Wpf/freezablesample_procedural/CSharp/freezablesample.cs#frozenexamplepart1)] [!code-vb[freezablesample_procedural#FrozenExamplePart1](~/samples/snippets/visualbasic/VS_Snippets_Wpf/freezablesample_procedural/visualbasic/freezablesample.vb#frozenexamplepart1)] When the button is rendered, the [!INCLUDE[TLA2#tla_winclient](../../../includes/tla2sharptla-winclient-md.md)] 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." A freezable's method enables you to disable this self-updating ability. You can use this method to make the brush become "frozen," or unmodifiable. > [!NOTE] > Not every Freezable object can be frozen. To avoid throwing an , check the value of the Freezable object's property to determine whether it can be frozen before attempting to freeze it. [!code-csharp[freezablesample_procedural#FrozenExamplePart2](~/samples/snippets/csharp/VS_Snippets_Wpf/freezablesample_procedural/CSharp/freezablesample.cs#frozenexamplepart2)] [!code-vb[freezablesample_procedural#FrozenExamplePart2](~/samples/snippets/visualbasic/VS_Snippets_Wpf/freezablesample_procedural/visualbasic/freezablesample.vb#frozenexamplepart2)] 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. > [!NOTE] > For convenience, freezable objects remain unfrozen unless you explicitly freeze them. ## Using Freezables Using an unfrozen freezable is like using any other type of object. In the following example, the color of a 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. [!code-csharp[freezablesample_procedural#UnFrozenExampleShort](~/samples/snippets/csharp/VS_Snippets_Wpf/freezablesample_procedural/CSharp/freezablesample.cs#unfrozenexampleshort)] [!code-vb[freezablesample_procedural#UnFrozenExampleShort](~/samples/snippets/visualbasic/VS_Snippets_Wpf/freezablesample_procedural/visualbasic/freezablesample.vb#unfrozenexampleshort)] ### Freezing a Freezable To make a unmodifiable, you call its method. When you freeze an object that contains freezable objects, those objects are frozen as well. For example, if you freeze a , 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. (See the [XAML Resources](/dotnet/desktop-wpf/fundamentals/xaml-resources-define) for more information about dynamic resources.) - It contains sub-objects that can't be frozen. If these conditions are false, and you don't intend to modify the , then you should freeze it to gain the performance benefits described earlier. Once you call a freezable's method, it can no longer be modified. Attempting to modify a frozen object causes an to be thrown. The following code throws an exception, because we attempt to modify the brush after it's been frozen. [!code-csharp[freezablesample_procedural#ExceptionExample](~/samples/snippets/csharp/VS_Snippets_Wpf/freezablesample_procedural/CSharp/freezablesample.cs#exceptionexample)] [!code-vb[freezablesample_procedural#ExceptionExample](~/samples/snippets/visualbasic/VS_Snippets_Wpf/freezablesample_procedural/visualbasic/freezablesample.vb#exceptionexample)] To avoid throwing this exception, you can use the method to determine whether a is frozen. [!code-csharp[freezablesample_procedural#CheckIsFrozenExample](~/samples/snippets/csharp/VS_Snippets_Wpf/freezablesample_procedural/CSharp/freezablesample.cs#checkisfrozenexample)] [!code-vb[freezablesample_procedural#CheckIsFrozenExample](~/samples/snippets/visualbasic/VS_Snippets_Wpf/freezablesample_procedural/visualbasic/freezablesample.vb#checkisfrozenexample)] In the preceding code example, a modifiable copy was made of a frozen object using the method. The next section discusses cloning in more detail. > [!NOTE] > Because a frozen freezable cannot be animated, the animation system will automatically create modifiable clones of frozen objects when you try to animate them with a . 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](../graphics-multimedia/storyboards-overview.md). ### Freezing from Markup To freeze a object declared in markup, you use the `PresentationOptions:Freeze` attribute. In the following example, a is declared as a page resource and frozen. It is then used to set the background of a button. [!code-xaml[FreezableSample#FreezeFromMarkupWholePage](~/samples/snippets/csharp/VS_Snippets_Wpf/FreezableSample/CS/FreezeFromMarkupExample.xaml#freezefrommarkupwholepage)] To use the `Freeze` attribute, you must map to the presentation options namespace: `http://schemas.microsoft.com/winfx/2006/xaml/presentation/options`. `PresentationOptions` is the recommended prefix for mapping this namespace: ```xaml xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" ``` Because not all XAML readers recognize this attribute, it's recommended that you use the [mc:Ignorable Attribute](mc-ignorable-attribute.md) to mark the `Presentation:Freeze` attribute as ignorable: ```xaml xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="PresentationOptions" ``` For more information, see the [mc:Ignorable Attribute](mc-ignorable-attribute.md) page. ### "Unfreezing" a Freezable Once frozen, a can never be modified or unfrozen; however, you can create an unfrozen clone using the or method. In the following example, the button's background is set with a brush and that brush is then frozen. An unfrozen copy is made of the brush using the method. The clone is modified and used to change the button's background from yellow to red. [!code-csharp[freezablesample_procedural#CloneExample](~/samples/snippets/csharp/VS_Snippets_Wpf/freezablesample_procedural/CSharp/freezablesample.cs#cloneexample)] [!code-vb[freezablesample_procedural#CloneExample](~/samples/snippets/visualbasic/VS_Snippets_Wpf/freezablesample_procedural/visualbasic/freezablesample.vb#cloneexample)] > [!NOTE] > Regardless of which clone method you use, animations are never copied to the new . The and methods produce deep copies of the freezable. If the freezable contains other frozen freezable objects, they are also cloned and made modifiable. For example, if you clone a frozen to make it modifiable, the figures and segments it contains are also copied and made modifiable. ## Creating Your Own Freezable Class A class that derives from gains the following features. - Special states: a read-only (frozen) and a writable state. - Thread safety: a frozen can be shared across threads. - Detailed change notification: Unlike other s, Freezable objects provide change notifications when sub-property values change. - Easy cloning: the Freezable class has already implemented several methods that produce deep clones. A is a type of , and therefore uses the dependency property system. 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 class was designed with dependency properties in mind. For more information about the dependency property system, see the [Dependency Properties Overview](dependency-properties-overview.md). Every subclass must override the 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: - At the beginning of any API that reads non-dependency property data members, call the method. - At the beginning of any API that writes non-dependency property data members, call the method. (Once you've called in an API, you don't need to make an additional call to if you also read non-dependency property data members.) - Call the method before exiting methods that write to non-dependency property data members. If your class contains non-dependency-property data members that are objects, you must also call the method each time you change one of their values, even if you're setting the member to `null`. > [!NOTE] > It's very important that you begin each method you override with a call to the base implementation. For an example of a custom class, see the [Custom Animation Sample](https://github.com/Microsoft/WPF-Samples/tree/master/Animation/CustomAnimation). ## See also - - [Custom Animation Sample](https://github.com/Microsoft/WPF-Samples/tree/master/Animation/CustomAnimation) - [Dependency Properties Overview](dependency-properties-overview.md) - [Custom Dependency Properties](custom-dependency-properties.md)