Información general sobre objetos FreezableFreezable Objects Overview

En este tema se describe cómo usar y crear de forma eficaz objetos Freezable, que proporcionan características especiales que pueden ayudar a mejorar el rendimiento de la aplicación.This topic describes how to effectively use and create Freezable objects, which provide special features that can help improve application performance. Los ejemplos de objetos Freezable incluyen pinceles, lápices, transformaciones, geometrías y animaciones.Examples of freezable objects include brushes, pens, transformations, geometries, and animations.

¿Qué es un elemento Freezable?What Is a Freezable?

Un Freezable es un tipo especial de objeto que tiene dos Estados: inmovilizado e inmovilizado.A Freezable is a special type of object that has two states: unfrozen and frozen. Cuando se inmoviliza, un Freezable parece comportarse como cualquier otro objeto.When unfrozen, a Freezable appears to behave like any other object. Cuando se inmoviliza, ya no se puede modificar un Freezable.When frozen, a Freezable can no longer be modified.

Un Freezable proporciona un evento Changed para notificar a los observadores de cualquier modificación del objeto.A Freezable provides a Changed event to notify observers of any modifications to the object. La inmovilización de un Freezable puede mejorar su rendimiento, ya que ya no es necesario dedicar recursos a las notificaciones de cambio.Freezing a Freezable can improve its performance, because it no longer needs to spend resources on change notifications. Un Freezable inmovilizado también puede compartirse entre subprocesos, mientras que un Freezable inmovilizado no puede.A frozen Freezable can also be shared across threads, while an unfrozen Freezable cannot.

Aunque la clase Freezable tiene muchas aplicaciones, la mayoría de los objetos Freezable de Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) están relacionados con el subsistema de gráficos.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.

La clase Freezable facilita el uso de determinados objetos del sistema de gráficos y puede ayudar a mejorar el rendimiento de la aplicación.The Freezable class makes it easier to use certain graphics system objects and can help improve application performance. Algunos ejemplos de tipos que heredan de Freezable incluyen las clases Brush, Transformy Geometry.Examples of types that inherit from Freezable include the Brush, Transform, and Geometry classes. Dado que contienen recursos no administrados, el sistema debe supervisar estos objetos para modificarlos y, a continuación, actualizar sus recursos no administrados correspondientes cuando se produce un cambio en el objeto original.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. Incluso si no modifica realmente un objeto del sistema de gráficos, el sistema debe seguir gastando algunos de sus recursos supervisando el objeto, en caso de que lo cambie.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.

Por ejemplo, supongamos que crea un pincel de SolidColorBrush y lo usa para pintar el fondo de un botón.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

Cuando se representa el botón, el subsistema de gráficos WPFWPF usa la información proporcionada para pintar un grupo de píxeles para crear el aspecto de un botón.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. Aunque se ha usado un pincel de color sólido para describir cómo se debe pintar el botón, el pincel de color sólido no realiza realmente el dibujo.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. El sistema de gráficos genera objetos de bajo nivel rápidos para el botón y el pincel, y son los objetos que realmente aparecen en la pantalla.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.

Si tuviera que modificar el pincel, se tendrían que volver a generar los objetos de bajo nivel.If you were to modify the brush, those low-level objects would have to be regenerated. La clase Freezable es lo que proporciona a un pincel la capacidad de buscar sus objetos generados de bajo nivel correspondientes y actualizarlos cuando cambia.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. Cuando esta capacidad está habilitada, se dice que el pincel está "inmovilizado".When this ability is enabled, the brush is said to be "unfrozen."

Un método Freeze de Freezable permite deshabilitar esta capacidad de auto-actualización.A freezable's Freeze method enables you to disable this self-updating ability. Puede usar este método para convertir el pincel en "inmovilizado" o no modificable.You can use this method to make the brush become "frozen," or unmodifiable.

Nota

No todos los objetos Freezable se pueden inmovilizar.Not every Freezable object can be frozen. Para evitar que se inicie una InvalidOperationException, compruebe el valor de la propiedad CanFreeze del objeto Freezable para determinar si se puede inmovilizar antes de intentar inmovilizarlo.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

Cuando ya no necesite modificar un Freezable, inmovilizarlo proporciona ventajas de rendimiento.When you no longer need to modify a freezable, freezing it provides performance benefits. Si fuera a inmovilizar el pincel en este ejemplo, el sistema de gráficos ya no necesitaría supervisarlo en busca de cambios.If you were to freeze the brush in this example, the graphics system would no longer need to monitor it for changes. El sistema de gráficos también puede crear otras optimizaciones, porque sabe que el pincel no cambiará.The graphics system can also make other optimizations, because it knows the brush won't change.

Nota

Para mayor comodidad, los objetos Freezable permanecen inmovilizados a menos que se inmovilizan explícitamente.For convenience, freezable objects remain unfrozen unless you explicitly freeze them.

Usar elementos inmovilizablesUsing Freezables

El uso de un objeto Freezable inmovilizado es como usar cualquier otro tipo de objeto.Using an unfrozen freezable is like using any other type of object. En el ejemplo siguiente, el color de un SolidColorBrush se cambia de amarillo a rojo después de utilizarse para pintar el fondo de un botón.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. El sistema de gráficos funciona en segundo plano para cambiar automáticamente el botón de amarillo a rojo la próxima vez que se actualice la pantalla.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

Inmovilizar un FreezableFreezing a Freezable

Para que un Freezable sea no modificable, llame a su método Freeze.To make a Freezable unmodifiable, you call its Freeze method. Al inmovilizar un objeto que contiene objetos Freezable, esos objetos también se inmovilizan.When you freeze an object that contains freezable objects, those objects are frozen as well. Por ejemplo, si inmoviliza un PathGeometry, las figuras y los segmentos que contiene también se bloquearán.For example, if you freeze a PathGeometry, the figures and segments it contains would be frozen too.

No se puede inmovilizar un Freezable si se cumple alguna de las siguientes condiciones:A Freezable can't be frozen if any of the following are true:

  • Tiene propiedades animadas o enlazadas a datos.It has animated or data bound properties.

  • Tiene las propiedades establecidas por un recurso dinámico.It has properties set by a dynamic resource. (Vea los recursos XAML para obtener más información acerca de los recursos dinámicos).(See the XAML Resources for more information about dynamic resources.)

  • Contiene Freezable subobjetos que no se pueden inmovilizar.It contains Freezable sub-objects that can't be frozen.

Si estas condiciones son falsas y no pretende modificar el Freezable, debe inmovilizarla para obtener las ventajas de rendimiento descritas anteriormente.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.

Una vez que se llama al método Freeze de un Freezable, ya no se puede modificar.Once you call a freezable's Freeze method, it can no longer be modified. Si se intenta modificar un objeto inmovilizado, se produce una InvalidOperationException.Attempting to modify a frozen object causes an InvalidOperationException to be thrown. En el código siguiente se produce una excepción, ya que se intenta modificar el pincel una vez que se ha inmovilizado.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

Para evitar que se produzca esta excepción, puede utilizar el método IsFrozen para determinar si un Freezable está inmovilizado.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


En el ejemplo de código anterior, se realizó una copia modificable de un objeto inmovilizado mediante el método Clone.In the preceding code example, a modifiable copy was made of a frozen object using the Clone method. En la sección siguiente se describe con más detalle la clonación.The next section discusses cloning in more detail.

Nota

Dado que no se puede animar un objeto Freezable inmovilizado, el sistema de animación creará automáticamente clones modificables de objetos Freezable inmovilizados al intentar animarlos con un Storyboard.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. Para eliminar la sobrecarga de rendimiento causada por la clonación, deje un objeto inmovilizado si tiene previsto animarlo.To eliminate the performance overhead caused by cloning, leave an object unfrozen if you intend to animate it. Para obtener más información sobre cómo animar con guiones gráficos, vea la información general sobre los guiones gráficos.For more information about animating with storyboards, see the Storyboards Overview.

Inmovilizar desde el marcadoFreezing from Markup

Para inmovilizar un objeto Freezable declarado en el marcado, se usa el atributo PresentationOptions:Freeze.To freeze a Freezable object declared in markup, you use the PresentationOptions:Freeze attribute. En el ejemplo siguiente, un SolidColorBrush se declara como un recurso de página y se inmoviliza.In the following example, a SolidColorBrush is declared as a page resource and frozen. A continuación, se usa para establecer el fondo de un botón.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>

Para usar el atributo Freeze, debe asignar al espacio de nombres opciones de presentación: 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 es el prefijo recomendado para asignar este espacio de nombres:PresentationOptions is the recommended prefix for mapping this namespace:

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

Dado que no todos los lectores de XAML reconocen este atributo, se recomienda usar el atributo MC: ignorable para marcar el atributo de Presentation:Freeze como ignorable: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"

Para obtener más información, vea la página de atributo MC: ignorable .For more information, see the mc:Ignorable Attribute page.

"Liberar" un Freezable"Unfreezing" a Freezable

Una vez inmovilizada, un Freezable nunca se puede modificar ni inmovilizar; sin embargo, puede crear un clon inmovilizado mediante el método Clone o CloneCurrentValue.Once frozen, a Freezable can never be modified or unfrozen; however, you can create an unfrozen clone using the Clone or CloneCurrentValue method.

En el ejemplo siguiente, el fondo del botón se establece con un pincel y, a continuación, se inmoviliza el pincel.In the following example, the button's background is set with a brush and that brush is then frozen. Se realiza una copia inmovilizada del pincel con el método Clone.An unfrozen copy is made of the brush using the Clone method. El clon se modifica y se usa para cambiar el fondo del botón de amarillo a rojo.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

Nota

Independientemente del método de clonación que use, las animaciones nunca se copian en la nueva Freezable.Regardless of which clone method you use, animations are never copied to the new Freezable.

Los métodos Clone y CloneCurrentValue generan copias en profundidad del Freezable.The Clone and CloneCurrentValue methods produce deep copies of the freezable. Si el objeto Freezable contiene otros objetos Freezable inmovilizados, también se clonan y se convierten en modificables.If the freezable contains other frozen freezable objects, they are also cloned and made modifiable. Por ejemplo, si clona una PathGeometry inmovilizada para convertirla en modificable, las figuras y los segmentos que contiene también se copian y se convierten en modificables.For example, if you clone a frozen PathGeometry to make it modifiable, the figures and segments it contains are also copied and made modifiable.

Crear su propia clase FreezableCreating Your Own Freezable Class

Una clase que deriva de Freezable obtiene las siguientes características.A class that derives from Freezable gains the following features.

  • Estados especiales: un estado de solo lectura (inmovilizado) y de escritura.Special states: a read-only (frozen) and a writable state.

  • Seguridad para subprocesos: un Freezable inmovilizado puede compartirse entre subprocesos.Thread safety: a frozen Freezable can be shared across threads.

  • Notificación de cambios detallada: a diferencia de otros DependencyObjects, los objetos Freezable proporcionan notificaciones de cambios cuando cambian los valores de las subpropiedades.Detailed change notification: Unlike other DependencyObjects, Freezable objects provide change notifications when sub-property values change.

  • Clonación sencilla: la clase Freezable ya ha implementado varios métodos que producen clones profundos.Easy cloning: the Freezable class has already implemented several methods that produce deep clones.

Un Freezable es un tipo de DependencyObjecty, por tanto, utiliza el sistema de propiedades de dependencia.A Freezable is a type of DependencyObject, and therefore uses the dependency property system. No es necesario que las propiedades de la clase sean propiedades de dependencia, pero el uso de propiedades de dependencia reduce la cantidad de código que se debe escribir, ya que la clase Freezable se ha diseñado teniendo en cuenta las propiedades de dependencia.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. Para obtener más información sobre el sistema de propiedades de dependencia, consulte información general sobre las propiedades de dependencia.For more information about the dependency property system, see the Dependency Properties Overview.

Cada subclase Freezable debe invalidar el método CreateInstanceCore.Every Freezable subclass must override the CreateInstanceCore method. Si la clase usa propiedades de dependencia para todos sus datos, ha terminado.If your class uses dependency properties for all its data, you're finished.

Si la clase contiene miembros de datos de propiedades que no son de dependencia, también debe invalidar los métodos siguientes:If your class contains non-dependency property data members, you must also override the following methods:

También debe observar las siguientes reglas para obtener acceso a los miembros de datos que no son propiedades de dependencia y escribir en ellos:You must also observe the following rules for accessing and writing to data members that are not dependency properties:

  • Al principio de cualquier API que lea miembros de datos de propiedades que no son de dependencia, llame al método ReadPreamble.At the beginning of any API that reads non-dependency property data members, call the ReadPreamble method.

  • Al principio de cualquier API que escriba miembros de datos de propiedades que no son de dependencia, llame al método WritePreamble.At the beginning of any API that writes non-dependency property data members, call the WritePreamble method. (Una vez que haya llamado WritePreamble en una API, no es necesario que realice una llamada adicional a ReadPreamble si también lee miembros de datos de propiedades que no son de dependencia).(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.)

  • Llame al método WritePostscript antes de salir de los métodos que escriben en los miembros de datos de propiedades que no son de dependencia.Call the WritePostscript method before exiting methods that write to non-dependency property data members.

Si la clase contiene miembros de datos que no son de dependencia que se DependencyObject objetos, también debe llamar al método OnFreezablePropertyChanged cada vez que cambie uno de sus valores, aunque esté estableciendo el miembro en null.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.

Nota

Es muy importante que comience cada Freezable método que invalide con una llamada a la implementación base.It's very important that you begin each Freezable method you override with a call to the base implementation.

Para obtener un ejemplo de una clase de Freezable personalizada, vea el ejemplo de animación personalizada.For an example of a custom Freezable class, see the Custom Animation Sample.

Vea tambiénSee also