Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este tema se describe cómo usar y crear Freezable objetos de forma eficaz, que proporcionan características especiales que pueden ayudar a mejorar el rendimiento de la aplicación. Algunos ejemplos de objetos congelables incluyen pinceles, lápices, transformaciones, geometrías y animaciones.
¿Qué es congelable?
A Freezable es un tipo especial de objeto que tiene dos estados: descongelado y congelado. Cuando se descongelan, Freezable parece comportarse como cualquier otro objeto. Cuando se congela, Freezable ya no se puede modificar.
Freezable proporciona un evento Changed para notificar a los observadores cualquier modificación en el objeto. La congelación de un Freezable puede mejorar su rendimiento, ya que ya no necesita gastar recursos en las notificaciones de cambios. Un Freezable congelado también se puede compartir entre subprocesos, mientras que un Freezable descongelado no puede.
Aunque la Freezable clase tiene muchas aplicaciones, la mayoría Freezable de los objetos de Windows Presentation Foundation (WPF) están relacionados con el subsistema gráfico.
La Freezable clase facilita el uso de determinados objetos del sistema gráfico y puede ayudar a mejorar el rendimiento de la aplicación. Algunos ejemplos de tipos que heredan de Freezable incluyen las Brushclases , Transformy Geometry . Dado que contienen recursos no administrados, el sistema debe supervisar estos objetos para las modificaciones y, a continuación, actualizar sus recursos no administrados correspondientes cuando se produce un cambio en el objeto original. Incluso si realmente no modifica un objeto del sistema de gráficos, el sistema todavía debe gastar algunos de sus recursos supervisando el objeto, en caso de que lo cambie.
Por ejemplo, supongamos que crea un SolidColorBrush pincel y lo usa para pintar el fondo de un botón.
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 gráficos de WPF usa la información proporcionada para pintar un grupo de píxeles para crear la apariencia de un botón. Aunque usó un pincel de color sólido para describir cómo se debe pintar el botón, el pincel de color sólido no hace realmente la pintura. El sistema gráfico genera objetos rápidos y de bajo nivel para el botón y el pincel, y es aquellos objetos que realmente aparecen en la pantalla.
Si fuera a modificar el pincel, dichos objetos de bajo nivel tendrían que volver a generarse. La clase freezable es lo que proporciona a un pincel la capacidad de encontrar sus objetos generados y de bajo nivel correspondientes y actualizarlos cuando cambia. Cuando esta capacidad está habilitada, se dice que el pincel está "descongelado".
Un método de freezable Freeze le permite deshabilitar esta capacidad de actualización automática. Puede usar este método para hacer que el pincel se convierta en "congelado" o no modificable.
Nota:
No todos los objetos Freezable se pueden congelar. Para evitar lanzar un InvalidOperationException, compruebe el valor de la propiedad del objeto Freezable CanFreeze para determinar si se puede inmovilizar antes de intentar inmovilizarlo.
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 elemento freezable, la congelación proporciona ventajas de rendimiento. Si tuviera que inmovilizar el pincel en este ejemplo, el sistema de gráficos ya no tendría que supervisarlo para ver los cambios. El sistema gráfico también puede realizar otras optimizaciones, ya que sabe que el pincel no cambiará.
Nota:
Por comodidad, los objetos congelables permanecen no congelados a menos que los inmovilice explícitamente.
Uso de Freezables
Usar un "freezable" no congelado es como usar cualquier otro tipo de objeto. En el ejemplo siguiente, el color de un SolidColorBrush se cambia de amarillo a rojo después de que se use para pintar el fondo de un botón. El sistema gráfico funciona en segundo plano para cambiar automáticamente el botón de amarillo a rojo la próxima vez que se actualice la pantalla.
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
Congelar un congelable
Para hacer un Freezable inmodificable, llame a su método Freeze. Al inmovilizar un objeto que contiene objetos congelables, esos objetos también se congelan. Por ejemplo, si congela un PathGeometry, las figuras y los segmentos que contiene también se congelarían.
Un objeto Freezable no se puede inmovilizar si se cumple alguna de las siguientes condiciones:
Tiene propiedades animadas o enlazadas a datos.
Tiene propiedades establecidas por un recurso dinámico. (Consulta los recursos XAML para obtener más información sobre los recursos dinámicos).
Contiene Freezable sub-objetos que no se pueden congelar.
Si estas condiciones son falsas y no pretende modificar el Freezable, entonces debe congelarlo para obtener las ventajas de rendimiento descritas anteriormente.
Una vez que se llama al método freezable Freeze , ya no se puede modificar. Si se intenta modificar un objeto inmovilizado, se lanza una InvalidOperationException. El código siguiente produce una excepción porque intentamos modificar el pincel después de que se haya congelado.
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 lanzar esta excepción, puede usar el IsFrozen método para determinar si un objeto Freezable está congelado.
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 congelado mediante el método Clone. En la sección siguiente se describe la clonación con más detalle.
Nota:
Dado que un congelable congelado no se puede animar, el sistema de animación creará automáticamente clones modificables de objetos congelados Freezable cuando intente animarlos con un Storyboard. Para eliminar la sobrecarga de rendimiento causada por la clonación, deje un objeto sin congelar si tiene intención de animarlo. Para obtener más información sobre cómo animar con guiones gráficos, consulte Información general sobre guiones gráficos.
Congelación desde el marcado
Para inmovilizar un Freezable objeto declarado en el marcado, use el atributo PresentationOptions:Freeze
. En el ejemplo siguiente, SolidColorBrush se declara como un recurso de página y se congela. A continuación, se usa para establecer el fondo de un botón.
<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 mapearse al espacio de nombres de las opciones de presentación: http://schemas.microsoft.com/winfx/2006/xaml/presentation/options
.
PresentationOptions
es el prefijo recomendado para mapear este espacio de nombres.
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
Dado que no todos los lectores XAML reconocen este atributo, se recomienda usar el atributo mc:Ignorable para marcar el PresentationOptions:Freeze
atributo como ignorable:
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"
Para obtener más información, consulte la página mc:Atributo Ignorable.
"Descongelar" un Congelable
Una vez congelado, un Freezable nunca se puede modificar ni descongelar; sin embargo, puede crear un clon no congelado mediante los métodos Clone o CloneCurrentValue.
En el ejemplo siguiente, el fondo del botón se establece con un pincel y ese pincel se congela. Se realiza una copia descongelada del pincel mediante el método Clone. El clon se modifica y se usa para cambiar el fondo del botón de amarillo a rojo.
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 el nuevo Freezable.
Los métodos Clone y CloneCurrentValue producen copias profundas del objeto congelable. Si el elemento congelable contiene otros objetos congelables congelados, también se clonan y se hacen modificables. Por ejemplo, si clona un PathGeometry congelado para que sea modificable, las figuras y los segmentos que contiene también se copian y se vuelven modificables.
Creación de su propia clase Freezable
Una clase que deriva de Freezable obtiene las siguientes características.
Estados especiales: un estado de solo lectura (congelado) y un estado editable.
Seguridad de subprocesos: se puede compartir un congelado Freezable entre subprocesos.
Notificación de cambio detallada: a diferencia de otros DependencyObjectobjetos, los objetos Freezable proporcionan notificaciones de cambio cuando cambian los valores de subpropiedades.
Clonación sencilla: la clase Freezable ya ha implementado varios métodos que producen clones profundos.
A Freezable es un tipo de DependencyObjecty, por tanto, usa el sistema de propiedades de dependencia. Las propiedades de clase no tienen que ser propiedades de dependencia, pero el uso de propiedades de dependencia reducirá la cantidad de código que tiene que escribir, ya que la Freezable clase se diseñó teniendo en cuenta las propiedades de dependencia. Para obtener más información sobre el sistema de propiedades de dependencia, consulte Introducción a las propiedades de dependencia.
Cada Freezable subclase debe invalidar el CreateInstanceCore método . Si la clase usa propiedades de dependencia para todos sus datos, ha terminado.
Si la clase contiene miembros de datos que no son propiedades de dependencia, también debe anular los siguientes métodos:
También debe observar las siguientes reglas para acceder y escribir en miembros de datos que no son propiedades de dependencia:
Al principio de cualquier API que lea miembros de datos de propiedades no dependientes, llame al método ReadPreamble.
Al principio de cualquier API que escribe miembros de datos no relacionados con propiedades de dependencia, llame al método WritePreamble. (Una vez que haya llamado WritePreamble en una API, no es necesario realizar una llamada adicional a ReadPreamble si también lee miembros de datos de propiedades que no son de dependencia).
Llame al método WritePostscript antes de salir de los métodos que escriben en miembros de datos de propiedades que no son de dependencia.
Si su clase contiene miembros de datos que no son propiedades de dependencia, pero que son objetos DependencyObject, también debe llamar al método OnFreezablePropertyChanged cada vez que cambie uno de sus valores, incluso si establece el miembro en null
.
Nota:
Es muy importante que comience cada método Freezable que sobrescriba con una llamada a la implementación base.
Para obtener un ejemplo de una clase personalizada Freezable , vea el ejemplo de animación personalizada.
Consulte también
.NET Desktop feedback