Vue d'ensemble des objets Freezable

Cette rubrique explique comment utiliser et créer Freezable efficacement des objets, qui fournissent des fonctionnalités spéciales qui peuvent aider à améliorer les performances des applications. Des exemples d’objets libres incluent des pinceaux, des stylos, des transformations, des géométries et des animations.

Qu’est-ce qu’un freezable ?

Il Freezable s’agit d’un type spécial d’objet qui a deux états : unfrozen et figé. Lorsqu’il n’est pas configuré, il Freezable semble se comporter comme n’importe quel autre objet. Lorsqu’il est figé, une Freezable personne ne peut plus être modifiée.

Un Freezable événement fournit un Changed événement pour avertir les observateurs des modifications apportées à l’objet. Geler un Freezable peut améliorer ses performances, car il n’a plus besoin de dépenser des ressources sur les notifications de modification. Un figé Freezable peut également être partagé entre les threads, tandis qu’un dégel ne peut pas être supprimé Freezable .

Bien que la classe ait de nombreuses applications, la Freezable plupart des Freezable objets dans Windows Presentation Foundation (WPF) sont liés au sous-système graphique.

La Freezable classe facilite l’utilisation de certains objets système graphiques et permet d’améliorer les performances des applications. Exemples de types qui héritent d’inclure Freezable les classes et TransformGeometry les Brushclasses. Étant donné qu’ils contiennent des ressources non managées, le système doit surveiller ces objets pour les modifications, puis mettre à jour leurs ressources non managées correspondantes en cas de modification de l’objet d’origine. Même si vous ne modifiez pas réellement un objet de système graphique, le système doit toujours dépenser certaines de ses ressources pour surveiller l’objet, au cas où vous le modifiez.

Par exemple, supposons que vous créez un SolidColorBrush pinceau et que vous l’utilisez pour peindre l’arrière-plan d’un bouton.

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

Lorsque le bouton est rendu, le sous-système graphique WPF utilise les informations que vous avez fournies pour peindre un groupe de pixels pour créer l’apparence d’un bouton. Bien que vous utilisiez un pinceau de couleur unie pour décrire comment le bouton doit être peint, votre pinceau de couleur unie ne fait pas réellement la peinture. Le système graphique génère des objets rapides et de bas niveau pour le bouton et le pinceau, et il s’agit de ces objets qui apparaissent réellement sur l’écran.

Si vous deviez modifier le pinceau, ces objets de bas niveau doivent être régénérés. La classe freezable est ce qui donne à un pinceau la possibilité de trouver ses objets générés et de bas niveau correspondants et de les mettre à jour lorsqu’il change. Lorsque cette capacité est activée, le pinceau est dit « sans connexion ».

Une méthode freezable Freeze vous permet de désactiver cette capacité de mise à jour automatique. Vous pouvez utiliser cette méthode pour rendre le pinceau « figé » ou inmodifiable.

Remarque

Tous les objets Freezable ne peuvent pas être figés. Pour éviter de lever un InvalidOperationException, case activée la valeur de la propriété de l’objet Freezable pour déterminer s’il CanFreeze peut être figé avant de tenter de le figer.

if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}
If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If

Lorsque vous n’avez plus besoin de modifier un freezable, le gel offre des avantages en matière de performances. Si vous deviez figer le pinceau dans cet exemple, le système graphique n’aurait plus besoin de le surveiller pour les modifications. Le système graphique peut également effectuer d’autres optimisations, car il sait que le pinceau ne changera pas.

Remarque

Pour des raisons pratiques, les objets gratuits restent sans assistance, sauf si vous les figez explicitement.

Utilisation de Freezables

L’utilisation d’un freezable sans nom est semblable à l’utilisation de n’importe quel autre type d’objet. Dans l’exemple suivant, la couleur d’un élément SolidColorBrush est passée du jaune au rouge après son utilisation pour peindre l’arrière-plan d’un bouton. Le système graphique fonctionne en arrière-plan pour changer automatiquement le bouton de jaune à rouge la prochaine fois que l’écran est actualisé.

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

Geler un freezable

Pour rendre inmodifiable Freezable , vous appelez sa Freeze méthode. Lorsque vous figez un objet qui contient des objets libres, ces objets sont également figés. Par exemple, si vous figez un PathGeometry, les chiffres et les segments qu’il contient sont également figés.

Un Freezable ne peut pas être figé si l’un des éléments suivants est vrai :

  • Il a des propriétés animées ou liées aux données.

  • Elle a des propriétés définies par une ressource dynamique. (Voir le Ressources XAML pour plus d’informations sur les ressources dynamiques.)

  • Il contient Freezable des sous-objets qui ne peuvent pas être figés.

Si ces conditions sont fausses et que vous n’avez pas l’intention de modifier, Freezablevous devez la figer pour obtenir les avantages de performances décrits précédemment.

Une fois que vous appelez la méthode freezable Freeze , elle ne peut plus être modifiée. La tentative de modification d’un objet figé entraîne la levée d’un InvalidOperationException objet. Le code suivant lève une exception, car nous essayons de modifier le pinceau une fois qu’il a été figé.


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

Pour éviter de lever cette exception, vous pouvez utiliser la IsFrozen méthode pour déterminer si une Freezable exception est figée.


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


Dans l’exemple de code précédent, une copie modifiable a été faite d’un objet figé à l’aide de la Clone méthode. La section suivante décrit plus en détail le clonage.

Remarque

Comme un freezable figé ne peut pas être animé, le système d’animation crée automatiquement des clones modifiables d’objets figés Freezable lorsque vous essayez de les animer avec un Storyboard. Pour éliminer la surcharge de performances causée par le clonage, laissez un objet non configuré si vous envisagez de l’animer. Pour plus d’informations sur l’animation avec des storyboards, consultez la vue d’ensemble des storyboards.

Gel du balisage

Pour figer un Freezable objet déclaré dans le balisage, vous utilisez l’attribut PresentationOptions:Freeze . Dans l’exemple suivant, une SolidColorBrush ressource de page est déclarée comme une ressource de page et figée. Il est ensuite utilisé pour définir l’arrière-plan d’un bouton.

<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>

Pour utiliser l’attribut, vous devez mapper à l’espace Freeze de noms des options de présentation : http://schemas.microsoft.com/winfx/2006/xaml/presentation/options. PresentationOptions est le préfixe recommandé pour le mappage de cet espace de noms :

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

Étant donné que tous les lecteurs XAML ne reconnaissent pas cet attribut, il est recommandé d’utiliser l’attribut mc :Ignorable pour marquer l’attribut PresentationOptions:Freeze comme étant ignoré :

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"

Pour plus d’informations, consultez la page mc :Ignorable Attribute .

« Unfrezing » un Freezable

Une fois figé, un Freezable fichier ne peut jamais être modifié ou non modifié ; toutefois, vous pouvez créer un clone non configuré à l’aide de la méthode ou CloneCurrentValue de la Clone méthode.

Dans l’exemple suivant, l’arrière-plan du bouton est défini avec un pinceau et ce pinceau est ensuite figé. Une copie non chiffrée est faite du pinceau à l’aide de la Clone méthode. Le clone est modifié et utilisé pour changer l’arrière-plan du bouton de jaune en rouge.

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

Remarque

Quelle que soit la méthode clone que vous utilisez, les animations ne sont jamais copiées dans le nouveau Freezable.

Les Clone méthodes et CloneCurrentValue les méthodes produisent des copies profondes du freezable. Si le freezable contient d’autres objets freezable figés, ils sont également clonés et rendus modifiables. Par exemple, si vous clonez un figé PathGeometry pour le rendre modifiable, les figures et les segments qu’il contient sont également copiés et rendus modifiables.

Création de votre propre classe freezable

Classe qui dérive des Freezable gains des fonctionnalités suivantes.

  • États spéciaux : un état en lecture seule (figé) et un état accessible en écriture.

  • Sécurité des threads : un figé Freezable peut être partagé entre les threads.

  • Notification de modification détaillée : Contrairement à d’autres DependencyObjectobjets freezables, les notifications de modification sont envoyées lorsque les valeurs de sous-propriété changent.

  • Clonage facile : la classe Freezable a déjà implémenté plusieurs méthodes qui produisent des clones profonds.

Il Freezable s’agit d’un type de , et utilise donc le système de DependencyObjectpropriétés de dépendance. Vos propriétés de classe n’ont pas besoin d’être des propriétés de dépendance, mais l’utilisation des propriétés de dépendance réduit la quantité de code que vous devez écrire, car la Freezable classe a été conçue avec des propriétés de dépendance à l’esprit. Pour plus d’informations sur le système de propriétés de dépendance, consultez la vue d’ensemble des propriétés de dépendance.

Chaque Freezable sous-classe doit remplacer la CreateInstanceCore méthode. Si votre classe utilise des propriétés de dépendance pour toutes ses données, vous avez terminé.

Si votre classe contient des membres de données de propriété non dépendants, vous devez également remplacer les méthodes suivantes :

Vous devez également observer les règles suivantes pour l’accès et l’écriture aux membres de données qui ne sont pas des propriétés de dépendance :

  • Au début de n’importe quelle API qui lit les membres de données de propriété non dépendants, appelez la ReadPreamble méthode.

  • Au début de toute API qui écrit des membres de données de propriété non dépendants, appelez la WritePreamble méthode. (Une fois que vous avez appelé WritePreamble dans une API, vous n’avez pas besoin d’effectuer un appel supplémentaire si ReadPreamble vous lisez également des membres de données de propriété non dépendants.)

  • Appelez la WritePostscript méthode avant de quitter les méthodes qui écrivent dans des membres de données de propriété non dépendants.

Si votre classe contient des membres de données de propriété non dépendants qui sont DependencyObject des objets, vous devez également appeler la OnFreezablePropertyChanged méthode chaque fois que vous modifiez l’une de leurs valeurs, même si vous définissez le membre nullsur .

Remarque

Il est très important de commencer chaque Freezable méthode que vous remplacez par un appel à l’implémentation de base.

Pour obtenir un exemple de classe personnalisée, consultez l’exemple d’animation personnaliséeFreezable.

Voir aussi