Cenni preliminari sugli oggetti FreezableFreezable Objects Overview

In questo argomento viene descritto come utilizzare e creare in modo efficace oggetti Freezable, che forniscono funzionalità speciali che consentono di migliorare le prestazioni dell'applicazione.This topic describes how to effectively use and create Freezable objects, which provide special features that can help improve application performance. Esempi di oggetti Freezable includono pennelli, penne, trasformazioni, geometrie e animazioni.Examples of freezable objects include brushes, pens, transformations, geometries, and animations.

Che cos'è un oggetto Freezable?What Is a Freezable?

Un Freezable è un tipo speciale di oggetto con due stati: non bloccato e bloccato.A Freezable is a special type of object that has two states: unfrozen and frozen. Quando viene sbloccato, un Freezable sembra comportarsi come qualsiasi altro oggetto.When unfrozen, a Freezable appears to behave like any other object. Quando il blocco è bloccato, non è più possibile modificare un Freezable.When frozen, a Freezable can no longer be modified.

Un Freezable fornisce un evento Changed per notificare agli osservatori le eventuali modifiche apportate all'oggetto.A Freezable provides a Changed event to notify observers of any modifications to the object. Il blocco di un Freezable può migliorare le prestazioni, perché non è più necessario spendere risorse per le notifiche di modifica.Freezing a Freezable can improve its performance, because it no longer needs to spend resources on change notifications. Un Freezable bloccato può anche essere condiviso tra thread, mentre un Freezable non bloccato non può.A frozen Freezable can also be shared across threads, while an unfrozen Freezable cannot.

Anche se la classe Freezable dispone di molte applicazioni, la maggior parte degli oggetti Freezable in Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) sono correlati al sottosistema grafico.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 classe Freezable rende più semplice l'utilizzo di determinati oggetti di sistema grafici e consente di migliorare le prestazioni dell'applicazione.The Freezable class makes it easier to use certain graphics system objects and can help improve application performance. Esempi di tipi che ereditano da Freezable includono le classi Brush, Transforme Geometry.Examples of types that inherit from Freezable include the Brush, Transform, and Geometry classes. Poiché contengono risorse non gestite, il sistema deve monitorare tali oggetti per le modifiche e quindi aggiornare le corrispondenti risorse non gestite quando viene apportata una modifica all'oggetto originale.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. Anche se non si modifica effettivamente un oggetto di sistema grafico, il sistema deve comunque dedicare alcune risorse al monitoraggio dell'oggetto, nel caso in cui venga modificato.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.

Si supponga, ad esempio, di creare un pennello SolidColorBrush e di usarlo per disegnare lo sfondo di un pulsante.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 viene eseguito il rendering del pulsante, il sottosistema grafico WPFWPF usa le informazioni fornite per disegnare un gruppo di pixel per creare l'aspetto di un pulsante.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. Sebbene sia stato usato un pennello tinta unita per descrivere il modo in cui deve essere disegnato il pulsante, il pennello tinta unita non esegue effettivamente il disegno.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. Il sistema grafico genera oggetti veloci e di basso livello per il pulsante e il pennello e sono gli oggetti effettivamente visualizzati sullo schermo.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.

Per modificare il pennello, è necessario rigenerare tali oggetti di basso livello.If you were to modify the brush, those low-level objects would have to be regenerated. La classe Freezable fornisce a un pennello la possibilità di trovare gli oggetti di basso livello generati corrispondenti e di aggiornarli quando cambiano.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 questa funzionalità è abilitata, il pennello viene definito "non bloccato".When this ability is enabled, the brush is said to be "unfrozen."

Il metodo Freeze di un oggetto Freezable consente di disabilitare questa funzionalità di aggiornamento automatico.A freezable's Freeze method enables you to disable this self-updating ability. È possibile utilizzare questo metodo per fare in modo che il pennello diventi "bloccato" o non modificabile.You can use this method to make the brush become "frozen," or unmodifiable.

Nota

Non tutti gli oggetti Freezable possono essere bloccati.Not every Freezable object can be frozen. Per evitare di generare un InvalidOperationException, controllare il valore della proprietà CanFreeze dell'oggetto Freezable per determinare se può essere bloccato prima di tentare di bloccarlo.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 non è più necessario modificare un oggetto Freezable, il blocco offre vantaggi in merito alle prestazioni.When you no longer need to modify a freezable, freezing it provides performance benefits. Se si blocca il pennello in questo esempio, il sistema grafico non dovrà più monitorarlo per le modifiche.If you were to freeze the brush in this example, the graphics system would no longer need to monitor it for changes. Il sistema grafico può anche eseguire altre ottimizzazioni, perché sa che il pennello non cambierà.The graphics system can also make other optimizations, because it knows the brush won't change.

Nota

Per praticità, gli oggetti Freezable rimangono bloccati a meno che non vengano bloccati in modo esplicito.For convenience, freezable objects remain unfrozen unless you explicitly freeze them.

Uso di FreezableUsing Freezables

L'utilizzo di un oggetto Freezable sbloccato è analogo all'utilizzo di qualsiasi altro tipo di oggetto.Using an unfrozen freezable is like using any other type of object. Nell'esempio seguente, il colore di un SolidColorBrush viene modificato da giallo a rosso dopo che è stato usato per disegnare lo sfondo di un pulsante.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. Il sistema grafico funziona dietro le quinte per modificare automaticamente il pulsante da giallo a rosso alla successiva aggiornamento dello schermo.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

Blocco di un oggetto FreezableFreezing a Freezable

Per rendere immodificabile un Freezable, chiamare il relativo metodo Freeze.To make a Freezable unmodifiable, you call its Freeze method. Quando si blocca un oggetto che contiene oggetti Freezable, anche questi oggetti sono bloccati.When you freeze an object that contains freezable objects, those objects are frozen as well. Se, ad esempio, si blocca un PathGeometry, anche le figure e i segmenti in esso contenuti verrebbero bloccati.For example, if you freeze a PathGeometry, the figures and segments it contains would be frozen too.

Un oggetto Freezable non può essere bloccato se si verifica una delle condizioni seguenti:A Freezable can't be frozen if any of the following are true:

  • Dispone di proprietà animate o con associazione a dati.It has animated or data bound properties.

  • Dispone di proprietà impostate da una risorsa dinamica.It has properties set by a dynamic resource. Per ulteriori informazioni sulle risorse dinamiche, vedere le risorse XAML .(See the XAML Resources for more information about dynamic resources.)

  • Contiene Freezable oggetti secondari che non possono essere bloccati.It contains Freezable sub-objects that can't be frozen.

Se queste condizioni sono false e non si intende modificare il Freezable, è consigliabile bloccarlo per ottenere i vantaggi in termini di prestazioni descritti in precedenza.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 volta chiamato il metodo Freeze di un oggetto Freezable, non è più possibile modificarlo.Once you call a freezable's Freeze method, it can no longer be modified. Il tentativo di modificare un oggetto bloccato causa la generazione di un InvalidOperationException.Attempting to modify a frozen object causes an InvalidOperationException to be thrown. Il codice seguente genera un'eccezione, perché si tenta di modificare il pennello dopo che è stato bloccato.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

Per evitare di generare questa eccezione, è possibile usare il metodo IsFrozen per determinare se un Freezable è bloccato.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


Nell'esempio di codice precedente, è stata eseguita una copia modificabile di un oggetto bloccato usando il metodo Clone.In the preceding code example, a modifiable copy was made of a frozen object using the Clone method. La sezione successiva illustra la clonazione in modo più dettagliato.The next section discusses cloning in more detail.

Nota

Poiché non è possibile animare un Freezable bloccato, il sistema di animazione creerà automaticamente cloni modificabili di oggetti Freezable bloccati quando si tenta di animarli con una 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. Per eliminare l'overhead delle prestazioni causato dalla clonazione, lasciare un oggetto non bloccato se si intende animarlo.To eliminate the performance overhead caused by cloning, leave an object unfrozen if you intend to animate it. Per ulteriori informazioni sull'animazione con gli storyboard, vedere Cenni preliminari sugli storyboard.For more information about animating with storyboards, see the Storyboards Overview.

Blocco dal markupFreezing from Markup

Per bloccare un oggetto Freezable dichiarato nel markup, usare l'attributo PresentationOptions:Freeze.To freeze a Freezable object declared in markup, you use the PresentationOptions:Freeze attribute. Nell'esempio seguente una SolidColorBrush viene dichiarata come risorsa di pagina e bloccata.In the following example, a SolidColorBrush is declared as a page resource and frozen. Viene quindi usato per impostare lo sfondo di un pulsante.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>

Per utilizzare l'attributo Freeze, è necessario eseguire il mapping allo spazio dei nomi delle opzioni di presentazione: 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 è il prefisso consigliato per il mapping di questo spazio dei nomi:PresentationOptions is the recommended prefix for mapping this namespace:

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

Poiché non tutti i lettori XAML riconoscono questo attributo, è consigliabile usare l' attributo MC: Ignorable per contrassegnare l'attributo Presentation:Freeze come ignorabile: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"

Per ulteriori informazioni, vedere la pagina relativa all' attributo MC: Ignorable .For more information, see the mc:Ignorable Attribute page.

"Sblocco" di un oggetto Freezable"Unfreezing" a Freezable

Una volta bloccato, un Freezable non può mai essere modificato o sbloccato; Tuttavia, è possibile creare un clone non bloccato usando il metodo 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.

Nell'esempio seguente lo sfondo del pulsante viene impostato con un pennello e il pennello viene quindi bloccato.In the following example, the button's background is set with a brush and that brush is then frozen. Viene eseguita una copia non bloccata del pennello utilizzando il metodo Clone.An unfrozen copy is made of the brush using the Clone method. Il clone viene modificato e usato per modificare lo sfondo del pulsante da giallo a rosso.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

Indipendentemente dal metodo di clonazione usato, le animazioni non vengono mai copiate nella nuova Freezable.Regardless of which clone method you use, animations are never copied to the new Freezable.

I metodi Clone e CloneCurrentValue producono copie complete dell'oggetto Freezable.The Clone and CloneCurrentValue methods produce deep copies of the freezable. Se l'oggetto Freezable contiene altri oggetti Freezable bloccati, questi vengono anche clonati e resi modificabili.If the freezable contains other frozen freezable objects, they are also cloned and made modifiable. Se, ad esempio, si clona un PathGeometry bloccato per renderlo modificabile, anche le figure e i segmenti in esso contenuti vengono copiati e resi modificabili.For example, if you clone a frozen PathGeometry to make it modifiable, the figures and segments it contains are also copied and made modifiable.

Creazione di una classe Freezable personalizzataCreating Your Own Freezable Class

Una classe che deriva da Freezable acquisisce le funzionalità seguenti.A class that derives from Freezable gains the following features.

  • Stati speciali: uno stato di sola lettura (bloccato) e scrivibile.Special states: a read-only (frozen) and a writable state.

  • Thread safety: un Freezable bloccato può essere condiviso tra thread.Thread safety: a frozen Freezable can be shared across threads.

  • Notifica dettagliata delle modifiche: diversamente da altre DependencyObjects, gli oggetti Freezable forniscono notifiche di modifica quando i valori delle sottoproprietà cambiano.Detailed change notification: Unlike other DependencyObjects, Freezable objects provide change notifications when sub-property values change.

  • Clonazione semplice: la classe Freezable ha già implementato diversi metodi che producono cloni profondi.Easy cloning: the Freezable class has already implemented several methods that produce deep clones.

Un Freezable è un tipo di DependencyObjecte pertanto utilizza il sistema di proprietà di dipendenza.A Freezable is a type of DependencyObject, and therefore uses the dependency property system. Le proprietà della classe non devono essere proprietà di dipendenza, ma l'uso delle proprietà di dipendenza ridurrà la quantità di codice da scrivere, perché la classe Freezable è stata progettata con le proprietà di dipendenza.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. Per ulteriori informazioni sul sistema di proprietà di dipendenza, vedere Cenni preliminari sulle proprietà di dipendenza.For more information about the dependency property system, see the Dependency Properties Overview.

Ogni sottoclasse Freezable deve eseguire l'override del metodo CreateInstanceCore.Every Freezable subclass must override the CreateInstanceCore method. Se la classe USA proprietà di dipendenza per tutti i dati, l'operazione è terminata.If your class uses dependency properties for all its data, you're finished.

Se la classe contiene membri dati di proprietà non di dipendenza, è necessario anche eseguire l'override dei metodi seguenti:If your class contains non-dependency property data members, you must also override the following methods:

È inoltre necessario osservare le regole seguenti per l'accesso e la scrittura a membri dati che non sono proprietà di dipendenza:You must also observe the following rules for accessing and writing to data members that are not dependency properties:

  • All'inizio di qualsiasi API che legge i membri dati della proprietà non di dipendenza, chiamare il metodo ReadPreamble.At the beginning of any API that reads non-dependency property data members, call the ReadPreamble method.

  • All'inizio di qualsiasi API che scriva membri dati di proprietà non di dipendenza, chiamare il metodo WritePreamble.At the beginning of any API that writes non-dependency property data members, call the WritePreamble method. Dopo aver chiamato WritePreamble in un'API, non è necessario effettuare una chiamata aggiuntiva a ReadPreamble se si leggono anche i membri dati della proprietà non di dipendenza.(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.)

  • Chiamare il metodo WritePostscript prima di uscire da metodi che scrivono in membri dati di proprietà non di dipendenza.Call the WritePostscript method before exiting methods that write to non-dependency property data members.

Se la classe contiene membri dati di proprietà non dipendenza DependencyObject oggetti, è necessario chiamare anche il metodo OnFreezablePropertyChanged ogni volta che si modifica uno dei relativi valori, anche se si imposta il membro su 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

È molto importante iniziare ogni Freezable metodo di cui si esegue l'override con una chiamata all'implementazione di base.It's very important that you begin each Freezable method you override with a call to the base implementation.

Per un esempio di classe di Freezable personalizzata, vedere l' esempio di animazione personalizzata.For an example of a custom Freezable class, see the Custom Animation Sample.

Vedere ancheSee also