Visão geral de objetos congeláveisFreezable Objects Overview

Este tópico descreve como usar e criar Freezable objetos com eficiência, 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?

Um 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 uncongelado, 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.

Um Freezable fornece um Changed evento 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 congelado Freezable também pode ser compartilhado entre threads, enquanto um não Freezable congelado não pode.A frozen Freezable can also be shared across threads, while an unfrozen Freezable cannot.

Embora a Freezable classe tenha muitos aplicativos, a Freezable maioria dos Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) objetos no está relacionada 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 Freezable classe facilita o uso de 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 Freezable de incluem Brushas Transformclasses, Geometry e.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 SolidColorBrush um pincel 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 de Freeze 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 do CanFreeze 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, você chama seu Freeze método.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 um PathGeometry, as figuras e os segmentos que ele 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á congelar 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 que você chamar o método Freeze de um 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 InvalidOperationException que um seja gerado.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 lançar essa exceção, você pode usar o IsFrozen método 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 Clone método.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 Freezable de objetos congelados quando você tentar animá- Storyboardlos com um.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 Freezable objeto declarado na marcação, use o PresentationOptions:Freeze atributo.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, Freezable um nunca pode ser modificado ou descongelado; no entanto, você pode criar um clone não Clone congelado CloneCurrentValue usando o método ou.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 Clone método.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 Freezablepara o novo.Regardless of which clone method you use, animations are never copied to the new Freezable.

Os Clone métodos CloneCurrentValue e 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 seguintes recursos.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: um Freezable congelado pode ser compartilhado entre threads.Thread safety: a frozen Freezable can be shared across threads.

  • Notificação de alteração detalhada: Ao contrário DependencyObjectde outros s, 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 Freezable escrever, pois a classe 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 Freezable subclasse deve substituir o CreateInstanceCore método.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 ReadPreamble método.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 WritePreamble o método.At the beginning of any API that writes non-dependency property data members, call the WritePreamble method. (Depois que você tiver WritePreamble chamado em uma API, não precisará fazer uma chamada adicional para ReadPreamble se você também ler membros de dados de propriedade não dependência.)(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 WritePostscript método 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 DependencyObject são objetos, você também deverá chamar OnFreezablePropertyChanged o método sempre que alterar um de seus valores, mesmo se você 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 Freezable método que substituir por uma chamada para a implementação 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 Freezable classe personalizada, consulte o exemplo animação personalizada.For an example of a custom Freezable class, see the Custom Animation Sample.

Consulte tambémSee also