Vue d’ensemble des objets freezables
Cette rubrique explique comment utiliser et créer efficacement des objets Freezable, qui fournissent des fonctionnalités spéciales qui peuvent aider à améliorer les performances des applications. Des exemples d'objets gelables incluent des pinceaux, des stylos, des transformations, des géométries et des animations.
Qu’est-ce qu’un article congelable ?
Un Freezable est un type spécial d’objet qui a deux états : décongelé et figé. Lorsqu’il est décongelé, un Freezable semble se comporter comme n'importe quel autre objet. Lorsqu’elle est figée, une Freezable ne peut plus être modifiée.
Un Freezable fournit un événement de Changed pour informer 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 Freezable figé peut également être partagé entre plusieurs threads, alors qu’un Freezable non figé ne peut pas l’être.
Bien que la classe Freezable ait de nombreuses applications, la plupart des objets Freezable dans Windows Presentation Foundation (WPF) sont liés au sous-système graphique.
La classe Freezable facilite l’utilisation de certains objets système graphiques et permet d’améliorer les performances des applications. Les types qui héritent de Freezable incluent les classes Brush, Transformet Geometry. É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 pinceau SolidColorBrush 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 devraient être régénérés. La classe freezable permet à un pinceau de trouver les objets de bas niveau qu’il génère et de les mettre à jour lorsqu’il change. Lorsque cette capacité est activée, le pinceau est considéré comme « non figé ».
La méthode Freeze d’un freezable vous permet de désactiver cette capacité de mise à jour automatique. Vous pouvez utiliser cette méthode pour rendre le pinceau « figé » ou inmodifiable.
Note
Tous les objets Freezable ne peuvent pas être figés. Pour éviter de lever un InvalidOperationException, vérifiez la valeur de la propriété CanFreeze de l’objet Freezable pour déterminer s’il peut être figé avant d’essayer 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.
Note
Pour des raisons pratiques, les objets figables restent non figés, sauf si vous les figez explicitement.
Utilisation de Freezables
L'utilisation d'un objet gelable non gelé est semblable à l'utilisation de n'importe quel autre type d'objet. Dans l’exemple suivant, la couleur d’une 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 objet Freezable
Pour rendre un Freezable inmodifiable, vous appelez sa méthode Freeze. Lorsque vous figez un objet qui contient des objets congelables, 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 objet 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. (Pour plus d'informations sur les ressources dynamiques, consultez les ressources XAML .)
Il contient Freezable sous-objets qui ne peuvent pas être gelés.
Si ces conditions sont fausses et que vous n’avez pas l’intention de modifier la Freezable, vous devez la figer pour obtenir les avantages de performances décrits précédemment.
Une fois que vous appelez la méthode Freeze d'un objet freezable, il ne peut plus être modifié. La tentative de modification d’un objet figé provoque la levée d’un InvalidOperationException. Le code suivant lève une exception, car on essaie 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 méthode IsFrozen pour déterminer si une Freezable 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 méthode Clone. La section suivante décrit plus en détail le clonage.
Note
Étant donné qu’un freezable figé ne peut pas être animé, le système d’animation crée automatiquement des clones modifiables d’objets Freezable figés lorsque vous essayez de les animer avec un Storyboard. Pour éliminer la surcharge de performances causée par le clonage, laissez un objet non gelé si vous prévoyez 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 objet Freezable déclaré dans le balisage, vous utilisez l’attribut PresentationOptions:Freeze
. Dans l'exemple suivant, "SolidColorBrush" est déclarée comme 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 Freeze
, vous devez mapper à l’espace 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 Attribut mc:Ignorable.
« Défiger » un objet Freezable
Une fois figé, un Freezable ne peut jamais être modifié ou décongelé ; toutefois, vous pouvez créer un clone non figé à l’aide de la méthode Clone ou CloneCurrentValue.
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 figée du pinceau est faite à l’aide de la méthode Clone. 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 la nouvelle Freezable.
Les méthodes Clone et CloneCurrentValue produisent des copies approfondies de l’objet Freezable. Si l’objet Freezable contient d’autres objets Freezable figés, ils sont également clonés et rendus modifiables. Par exemple, si vous clonez un PathGeometry figé 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 d’objet Freezable
Une classe qui dérive de Freezable gagne les fonctionnalités suivantes.
États spéciaux : un état en lecture seule (figé) et un état accessible en écriture.
Sécurité des threads : un Freezable figé peut être partagé entre les threads.
Notification de modification détaillée : contrairement aux autres DependencyObjects, les objets freezables fournissent des notifications de modification 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.
Un Freezable est un type de DependencyObject, et utilise donc le système de proprié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 classe Freezable 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 sous-classe Freezable doit remplacer la méthode CreateInstanceCore. 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 respecter les règles suivantes pour accéder et écrire aux membres de données qui ne sont pas des propriétés de dépendance :
Au début de toute API qui lit des membres de données non liés à des propriétés de dépendance, appelez la méthode ReadPreamble.
Au début de toute API qui écrit dans des membres de données non liés à des propriétés de dépendance, appelez la méthode WritePreamble. (Une fois que vous avez appelé WritePreamble dans une API, vous n’avez pas besoin d’effectuer d’appel supplémentaire pour ReadPreamble si vous lisez également des membres de données non liés à des propriétés de dépendance.)
Appelez la méthode WritePostscript avant de quitter les méthodes qui écrivent dans des membres de données non liés à des propriétés de dépendance.
Si votre classe contient des membres de données non dépendants qui sont DependencyObject objets, vous devez également appeler la méthode OnFreezablePropertyChanged chaque fois que vous modifiez l’une de leurs valeurs, même si vous définissez le membre sur null
.
Note
Il est très important de commencer chaque méthode Freezable que vous remplacez par un appel à l’implémentation de base.
Pour obtenir un exemple de classe Freezable personnalisée, consultez l’exemple d’animation personnalisée .
Voir aussi
- Freezable
- exemple d’animation personnalisée
- Vue d’ensemble des propriétés de dépendance
- Propriétés de dépendance personnalisées
.NET Desktop feedback