Visão geral de objetos congeláveisFreezable Objects Overview

Este tópico descreve como usar e criar com eficiência Freezable objetos, que fornecem recursos especiais que podem ajudar a melhorar o desempenho do aplicativo.This topic describes how to effectively use and create Freezable objects, which provide special features that can help improve application performance. Exemplos de objetos congeláveis incluem pincéis, canetas, transformações, geometrias e animações.Examples of freezable objects include brushes, pens, transformations, geometries, and animations.

O que é um Congelável?What Is a Freezable?

Uma Freezable é um tipo especial de objeto que tem dois Estados: descongelado e congelado.A Freezable is a special type of object that has two states: unfrozen and frozen. Quando não congelado, um Freezable parece se comportar como qualquer outro objeto.When unfrozen, a Freezable appears to behave like any other object. Quando congelado, um Freezable não pode mais ser modificado.When frozen, a Freezable can no longer be modified.

Uma Freezable fornece um evento Changed para notificar os observadores de quaisquer modificações ao objeto.A Freezable provides a Changed event to notify observers of any modifications to the object. Congelar um Freezable pode melhorar seu desempenho, pois ele não precisa mais gastar recursos em notificações de alteração.Freezing a Freezable can improve its performance, because it no longer needs to spend resources on change notifications. Um Freezable congelado também pode ser compartilhado entre threads, enquanto um Freezable não congelado não pode.A frozen Freezable can also be shared across threads, while an unfrozen Freezable cannot.

Embora a classe Freezable tenha muitos aplicativos, a maioria dos objetos Freezable no Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) estão relacionados ao 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.

A classe Freezable torna mais fácil usar determinados objetos do sistema de gráficos e pode ajudar a melhorar o desempenho do aplicativo.The Freezable class makes it easier to use certain graphics system objects and can help improve application performance. Exemplos de tipos que herdam de Freezable incluem as classes Brush, Transforme Geometry.Examples of types that inherit from Freezable include the Brush, Transform, and Geometry classes. Como eles contêm recursos não gerenciados, o sistema deve monitorar as modificações a esses objetos e, em seguida, atualizar seus recursos não gerenciados correspondentes, quando houver uma alteração no 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. Mesmo se você não realmente modificar um objeto do sistema de elementos gráficos, o sistema ainda deverá gastar um pouco de seus recursos monitorando o objeto, para o caso de você alterá-lo.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 exemplo, suponha que você crie um pincel de SolidColorBrush e use-o para pintar o plano de fundo de um botão.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

Quando o botão é renderizado, o subsistema de elementos gráficos do WPFWPF usa as informações fornecidas para pintar um grupo de pixels para criar a aparência de um botão.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. Embora você tenha usado um pincel de cor sólida para descrever como o botão deveria ser pintado, seu pincel de cor sólida, na verdade, não faz a pintura.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. O sistema de elementos gráficos gera objetos rápidos e de baixo nível para o botão e o pincel e são esses objetos que realmente aparecem na tela.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.

Se você fosse modificar o pincel, esses objetos de baixo nível precisariam ser regenerados.If you were to modify the brush, those low-level objects would have to be regenerated. A classe congelável é o que proporciona a um pincel a capacidade de localizar seus objetos gerados e de nível inferior correspondentes e atualizá-los quando forem alterados.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. Quando essa capacidade é habilitada, significa que o pincel está "descongelado."When this ability is enabled, the brush is said to be "unfrozen."

O método Freeze de um Freezable permite que você desabilite essa capacidade de autoatualização.A freezable's Freeze method enables you to disable this self-updating ability. Você pode usar esse método para fazer com que o pincel se torne "congelado" ou não modificável.You can use this method to make the brush become "frozen," or unmodifiable.

Observação

Nem todo objeto Congelável pode ser congelado.Not every Freezable object can be frozen. Para evitar lançar um InvalidOperationException, verifique o valor da propriedade CanFreeze do objeto Freezable para determinar se ele pode ser congelado antes de tentar congele-lo.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

Quando você não precisa mais modificar um congelável, congelá-lo fornece benefícios de desempenho.When you no longer need to modify a freezable, freezing it provides performance benefits. Se você congelasse o pincel nesse exemplo, o sistema de elementos gráficos não precisaria mais monitorar as alterações feitas nele.If you were to freeze the brush in this example, the graphics system would no longer need to monitor it for changes. O sistema de elementos gráficos também pode fazer outras otimizações, porque sabe que o pincel não será alterado.The graphics system can also make other optimizations, because it knows the brush won't change.

Observação

Por conveniência, objetos congeláveis permanecem descongelados, a menos que você explicitamente os congele.For convenience, freezable objects remain unfrozen unless you explicitly freeze them.

Usando CongeláveisUsing Freezables

O uso de um congelável descongelado é como o uso de qualquer outro tipo de objeto.Using an unfrozen freezable is like using any other type of object. No exemplo a seguir, a cor de um SolidColorBrush é alterada de amarelo para vermelho depois de ser usada para pintar o plano de fundo de um botão.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. O sistema de elementos gráficos funciona nos bastidores para alterar automaticamente o botão de amarelo para vermelho na próxima vez que a tela for atualizada.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

Congelando uma congelávelFreezing a Freezable

Para tornar um Freezable não modificável, chame seu método Freeze.To make a Freezable unmodifiable, you call its Freeze method. Quando você congela um objeto que contém objetos congeláveis, esses objetos também são congelados.When you freeze an object that contains freezable objects, those objects are frozen as well. Por exemplo, se você congelar uma PathGeometry, as figuras e os segmentos que ela contém também ficarão congelados.For example, if you freeze a PathGeometry, the figures and segments it contains would be frozen too.

Um congelável não poderá ser congelado se alguma das seguintes condições for verdadeira:A Freezable can't be frozen if any of the following are true:

  • Ele tem propriedades animadas ou associadas a dados.It has animated or data bound properties.

  • Ele tem propriedades definidas por um recurso dinâmico.It has properties set by a dynamic resource. (Consulte os recursos XAML para obter mais informações sobre recursos dinâmicos).(See the XAML Resources for more information about dynamic resources.)

  • Ele contém Freezable subobjetos que não podem ser congelados.It contains Freezable sub-objects that can't be frozen.

Se essas condições forem falsas e você não pretender modificar o Freezable, você deverá congele-lo para obter os benefícios de desempenho descritos 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.

Depois de chamar o método Freeze de Freezable, ele não poderá mais ser modificado.Once you call a freezable's Freeze method, it can no longer be modified. A tentativa de modificar um objeto congelado faz com que um InvalidOperationException seja lançado.Attempting to modify a frozen object causes an InvalidOperationException to be thrown. O código a seguir gera uma exceção, pois tenta modificar o pincel depois de ele ter sido congelado.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 gerar essa exceção, você pode usar o método IsFrozen para determinar se um Freezable está congelado.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


No exemplo de código anterior, foi feita uma cópia modificável de um objeto congelado usando o método Clone.In the preceding code example, a modifiable copy was made of a frozen object using the Clone method. A próxima seção aborda a clonagem em mais detalhes.The next section discusses cloning in more detail.

Observação

Como um Freezable congelado não pode ser animado, o sistema de animação criará automaticamente clones modificáveis de objetos Freezable congelado quando você tentar animá-los com um 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 a sobrecarga de desempenho causada pela clonagem, deixe um objeto descongelado se você pretende animá-lo.To eliminate the performance overhead caused by cloning, leave an object unfrozen if you intend to animate it. Para obter mais informações sobre animação com storyboards, consulte a Visão geral de storyboards.For more information about animating with storyboards, see the Storyboards Overview.

Congelamento na marcaçãoFreezing from Markup

Para congelar um objeto Freezable declarado na marcação, use o atributo PresentationOptions:Freeze.To freeze a Freezable object declared in markup, you use the PresentationOptions:Freeze attribute. No exemplo a seguir, um SolidColorBrush é declarado como um recurso de página e congelado.In the following example, a SolidColorBrush is declared as a page resource and frozen. Em seguida, ele é usado para definir a tela de fundo de um botão.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 o atributo Freeze, você deve mapear para o namespace de opções de apresentação: 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. O PresentationOptions é o prefixo recomendado para mapear este namespace:PresentationOptions is the recommended prefix for mapping this namespace:

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

Como nem todos os leitores de XAML reconhecem esse atributo, é recomendável que você use o mc:Ignorable Attribute para marcar o atributo Presentation:Freeze como ignorável: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 obter mais informações, consulte a página Atributo mc:Ignorable.For more information, see the mc:Ignorable Attribute page.

"Descongelando" um Congelável"Unfreezing" a Freezable

Depois de congelado, uma Freezable nunca pode ser modificada ou descongelada; no entanto, você pode criar um clone não congelado usando o método Clone ou CloneCurrentValue.Once frozen, a Freezable can never be modified or unfrozen; however, you can create an unfrozen clone using the Clone or CloneCurrentValue method.

No exemplo a seguir, a tela de fundo do botão é definida com um pincel e, então, esse pincel é congelado.In the following example, the button's background is set with a brush and that brush is then frozen. Uma cópia não congelada é feita do pincel usando o método Clone.An unfrozen copy is made of the brush using the Clone method. O clone é modificado e usado para alterar a tela de fundo do botão de amarela para vermelha.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

Observação

Independentemente do método de clonagem usado, as animações nunca são copiadas para o novo Freezable.Regardless of which clone method you use, animations are never copied to the new Freezable.

Os métodos Clone e CloneCurrentValue produzem cópias profundas do Freezable.The Clone and CloneCurrentValue methods produce deep copies of the freezable. Se o congelável contém outros objetos congeláveis congelados, eles também são clonados e tornados modificáveis.If the freezable contains other frozen freezable objects, they are also cloned and made modifiable. Por exemplo, se você clonar um PathGeometry congelado para torná-lo modificável, as figuras e os segmentos que ele contém também serão copiados e tornados modificáveis.For example, if you clone a frozen PathGeometry to make it modifiable, the figures and segments it contains are also copied and made modifiable.

Criando sua própria classe CongelávelCreating Your Own Freezable Class

Uma classe derivada de Freezable Obtém os recursos a seguir.A class that derives from Freezable gains the following features.

  • Estados especiais: um estado somente leitura (congelada) e gravável.Special states: a read-only (frozen) and a writable state.

  • Segurança de thread: uma Freezable congelada pode ser compartilhada entre threads.Thread safety: a frozen Freezable can be shared across threads.

  • Notificação de alteração detalhada: ao contrário de outras DependencyObjects, os objetos Freezable fornecem notificações de alteração quando os valores de subpropriedades são alterados.Detailed change notification: Unlike other DependencyObjects, Freezable objects provide change notifications when sub-property values change.

  • Fácil clonagem: a classe Congelável tem vários métodos já implementados que produzem clones profundos.Easy cloning: the Freezable class has already implemented several methods that produce deep clones.

Um Freezable é um tipo de DependencyObjecte, portanto, usa o sistema de propriedades de dependência.A Freezable is a type of DependencyObject, and therefore uses the dependency property system. Suas propriedades de classe não precisam ser Propriedades de dependência, mas o uso de propriedades de dependência reduzirá a quantidade de código que você precisa escrever, pois a classe de Freezable foi projetada com propriedades de dependência em mente.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 obter mais informações sobre o sistema de propriedade de dependência, consulte o Visão geral de propriedades de dependência.For more information about the dependency property system, see the Dependency Properties Overview.

Cada subclasse de Freezable deve substituir o método CreateInstanceCore.Every Freezable subclass must override the CreateInstanceCore method. Se sua classe usa as propriedades de dependência para todos os seus dados, você terminou.If your class uses dependency properties for all its data, you're finished.

Se sua classe contém membros de dados de propriedade que não são de dependência, você também deve substituir os métodos a seguir:If your class contains non-dependency property data members, you must also override the following methods:

Você também deve observar as seguintes regras para o acesso e gravação em membros de dados que não são propriedades de dependência:You must also observe the following rules for accessing and writing to data members that are not dependency properties:

  • No início de qualquer API que leia membros de dados de propriedade não dependência, chame o método ReadPreamble.At the beginning of any API that reads non-dependency property data members, call the ReadPreamble method.

  • No início de qualquer API que grava membros de dados de propriedade de não dependência, chame o método WritePreamble.At the beginning of any API that writes non-dependency property data members, call the WritePreamble method. (Depois que você tiver chamado WritePreamble em uma API, não será necessário fazer uma chamada adicional para ReadPreamble se você também ler membros de dados de propriedade não dependentes.)(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.)

  • Chame o método WritePostscript antes de sair de métodos que gravam em membros de dados de propriedade de não dependência.Call the WritePostscript method before exiting methods that write to non-dependency property data members.

Se sua classe contiver membros de dados de propriedade não dependência que são DependencyObject objetos, você também deverá chamar o método OnFreezablePropertyChanged cada vez que alterar um de seus valores, mesmo se estiver definindo o membro como 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.

Observação

É muito importante que você comece cada método de Freezable que você substituir por uma chamada para a implementação de base.It's very important that you begin each Freezable method you override with a call to the base implementation.

Para obter um exemplo de uma classe de Freezable personalizada, consulte o exemplo animação personalizada.For an example of a custom Freezable class, see the Custom Animation Sample.

Confira tambémSee also