Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Thema wird beschrieben, wie Sie Freezable-Objekte effektiv erstellen und verwenden, die spezielle Funktionen bereitstellen und zur Verbesserung der Anwendungsleistung beitragen können. Beispiele für einfrierbare Objekte sind Pinsel, Stifte, Transformationen, Geometrien und Animationen.
Was ist ein Freezable?
Ein Freezable ist eine besondere Art von Objekt, das zwei Zustände hat: nicht fixiert und fixiert. Wenn sie nicht eingefrozen, verhält sich ein Freezable Objekt wie jedes andere Objekt. Wenn eingefroren, kann eine Freezable nicht mehr geändert werden.
A Freezable stellt ein Changed Ereignis bereit, um Beobachter über Änderungen am Objekt zu informieren. Das Einfrieren eines Steuerelements Freezable kann seine Leistung verbessern, da er keine Ressourcen mehr für Änderungsbenachrichtigungen ausgeben muss. Ein eingefrorenes Freezable kann auch über Threads hinweg geteilt werden, während ein nicht eingefrorenes Freezable nicht geteilt werden kann.
Obwohl die Klasse viele Anwendungen aufweist, sind die Freezable meisten Freezable Objekte in Windows Presentation Foundation (WPF) mit dem Grafikuntersystem verknüpft.
Die Freezable Klasse erleichtert die Verwendung bestimmter Grafiksystemobjekte und kann die Anwendungsleistung verbessern. Beispiele für Typen, die von Freezable erben, umfassen die Klassen Brush, Transform und Geometry. Da sie nicht verwaltete Ressourcen enthalten, muss das System diese Objekte auf Änderungen überwachen und dann die entsprechenden nicht verwalteten Ressourcen aktualisieren, wenn eine Änderung am ursprünglichen Objekt vorhanden ist. Selbst wenn Sie ein Grafiksystemobjekt nicht tatsächlich ändern, muss das System dennoch einige seiner Ressourcen für die Überwachung des Objekts ausgeben, falls Sie es ändern.
Angenommen, Sie erstellen einen SolidColorBrush Pinsel und verwenden ihn zum Zeichnen des Hintergrunds einer Schaltfläche.
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
Wenn die Schaltfläche gerendert wird, verwendet das WPF-Grafikuntersystem die Informationen, die Sie zum Zeichnen einer Gruppe von Pixeln bereitgestellt haben, um die Darstellung einer Schaltfläche zu erstellen. Obwohl Sie einen Pinsel mit Volltonfarbe verwendet haben, um zu beschreiben, wie die Schaltfläche gezeichnet werden soll, führt Ihr Volltonfarbpinsel das Malen nicht aus. Das Grafiksystem generiert schnelle Objekte auf niedriger Ebene für die Schaltfläche und den Pinsel, und es handelt sich um die Objekte, die tatsächlich auf dem Bildschirm angezeigt werden.
Wenn Sie den Pinsel ändern würden, müssten diese Objekte auf niedriger Ebene neu generiert werden. Die Freezable-Klasse bietet einem Pinsel die Fähigkeit, die entsprechenden generierten Objekte auf niedrigerer Ebene zu finden und sie zu aktualisieren, wenn sie sich ändert. Wenn diese Funktion aktiviert ist, wird der Pinsel als "unfrozen" bezeichnet.
Mit der Freezable-Methode Freeze können Sie diese Selbstaktualisierungsmöglichkeit deaktivieren. Mit dieser Methode können Sie den Pinsel "eingefroren" oder unveränderlich machen.
Hinweis
Nicht jedes einfrierbare Objekt kann eingefroren werden. Um das Auslösen eines InvalidOperationExceptionObjekts zu vermeiden, überprüfen Sie den Wert der Freezable-Objekteigenschaft CanFreeze , um zu bestimmen, ob es eingefroren werden kann, bevor Sie versuchen, es zu fixieren.
if (myBrush.CanFreeze)
{
// Makes the brush unmodifiable.
myBrush.Freeze();
}
If myBrush.CanFreeze Then
' Makes the brush unmodifiable.
myBrush.Freeze()
End If
Wenn Sie ein Einfrierbar-Objekt nicht mehr ändern müssen, sorgt das Einfrieren für Leistungsvorteile. Wenn Sie den Pinsel in diesem Beispiel fixieren würden, müsste das Grafiksystem ihn nicht mehr auf Änderungen überwachen. Das Grafiksystem kann auch andere Optimierungen vornehmen, da er weiß, dass sich der Pinsel nicht ändert.
Hinweis
Zur Vereinfachung bleiben freizierbare Objekte nicht eingefroren, es sei denn, Sie frieren sie explizit ein.
Verwenden von Freezables
Die Verwendung eines unfrozen freezable-Elements ist wie bei jeder anderen Objektart. Im folgenden Beispiel wird die Farbe eines SolidColorBrush von Gelb zu Rot geändert, nachdem sie zum Anstreichen des Hintergrunds einer Schaltfläche verwendet wurde. Das Grafiksystem arbeitet hinter den Kulissen, um die Schaltfläche bei der nächsten Aktualisierung des Bildschirms automatisch von Gelb in Rot zu ändern.
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
Einfrieren eines Einfrierbaren
Um eine nicht veränderbare Freezable zu erstellen, rufen Sie dessen Freeze-Methode auf. Wenn Sie ein Objekt einfrieren, das einfrierbare Objekte enthält, werden diese Objekte ebenfalls eingefroren. Wenn Sie z. B. ein PathGeometry einfrieren, würden die darin enthaltenen Zahlen und Segmente ebenfalls eingefroren.
Eine Freezable kann nicht eingefroren werden, wenn eine der folgenden Bedingungen zutrifft:
Es verfügt über animierte oder datengebundene Eigenschaften.
Es verfügt über Eigenschaften, die von einer dynamischen Ressource festgelegt wurden. (Weitere Informationen zu dynamischen Ressourcen finden Sie in den XAML-Ressourcen .)
Es enthält Freezable Unterobjekte, die nicht eingefroren werden können.
Wenn diese Bedingungen falsch sind und Sie nicht beabsichtigen, das Freezable zu ändern, sollten Sie es einfrieren, um die zuvor beschriebenen Leistungsvorteile zu erzielen.
Nachdem Sie die Methode eines Freezable-Objekts Freeze aufgerufen haben, kann es nicht mehr geändert werden. Wenn Sie versuchen, ein eingefrorenes Objekt zu ändern, wird ein InvalidOperationException ausgelöst. Der folgende Code löst eine Ausnahme aus, weil wir versuchen, den Pinsel nach dem Einfrieren zu ändern.
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
Um das Auslösen dieser Ausnahme zu vermeiden, können Sie die Methode IsFrozen verwenden, um zu bestimmen, ob ein Freezable eingefroren ist.
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
Im vorherigen Codebeispiel wurde mithilfe der Clone Methode eine änderungsfähige Kopie eines fixierten Objekts erstellt. Im nächsten Abschnitt wird das Klonen ausführlicher erläutert.
Hinweis
Da ein eingefrorenes Freizierbares nicht animiert werden kann, erstellt das Animationssystem automatisch modifizierbare Klone von eingefrorenen Freezable Objekten, wenn Sie versuchen, sie mit einem Storyboard zu animieren. Um Leistungseinbußen durch Klonen zu verhindern, lassen Sie ein Objekt nicht einfrieren, wenn Sie es animieren möchten. Weitere Informationen zum Animieren mit Storyboards finden Sie in der Storyboards Overview.
Einfrieren von Markup
Um ein im Markup deklariertes Freezable Objekt zu fixieren, verwenden Sie das PresentationOptions:Freeze
Attribut. Im folgenden Beispiel wird eine SolidColorBrush als Seitenressource deklariert und eingefroren. Anschließend wird der Hintergrund einer Schaltfläche festgelegt.
<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>
Um das Freeze
Attribut zu verwenden, müssen Sie dem Namespace der Präsentationsoptionen zuordnen: http://schemas.microsoft.com/winfx/2006/xaml/presentation/options
.
PresentationOptions
ist das empfohlene Präfix für die Zuordnung dieses Namespaces:
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
Da nicht alle XAML-Leser dieses Attribut erkennen, wird empfohlen, das Attribut mc:Ignorable zu verwenden, um das PresentationOptions:Freeze
-Attribut als ignorierbar zu kennzeichnen.
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"
Weitere Informationen finden Sie auf der Seite mc:Ignorable Attribute.
"Auftauen eines einfrierfähigen Objekts"
Sobald eingefroren, kann eine Freezable-Datei nie geändert oder aufgetaut werden; jedoch können Sie einen nicht eingefrorenen Klon mithilfe der Clone- oder CloneCurrentValue-Methode erstellen.
Im folgenden Beispiel wird der Hintergrund der Schaltfläche mit einem Pinsel gesetzt, und dieser Pinsel wird dann eingefroren. Mit der Clone Methode wird eine unfrozen Kopie des Pinsels erstellt. Der Klon wird geändert und verwendet, um den Hintergrund der Schaltfläche von Gelb in Rot zu ändern.
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
Hinweis
Unabhängig davon, welche Klonmethode Sie verwenden, werden Animationen nie in das neue Freezablekopiert.
Die Methoden Clone und CloneCurrentValue erstellen tiefe Kopien des Freezable. Wenn die einfrierbar andere eingefrorene einfrierbare Objekte enthält, werden sie auch geklont und änderbar gemacht. Wenn Sie beispielsweise eingefrorenes PathGeometry Element klonen, um es zu ändern, werden die darin enthaltenen Abbildungen und Segmente ebenfalls kopiert und geändert.
Erstellen einer eigenen einfrierbaren Klasse
Eine Klasse, die von Freezable abgeleitet ist, erhält die folgenden Eigenschaften.
Spezielle Zustände: ein schreibgeschützter (gefrorener) und ein schreibbarer Zustand.
Threadsicherheit: Ein fixierter Freezable kann über Threads hinweg geteilt werden.
Detaillierte Änderungsbenachrichtigung: Im Gegensatz zu anderen DependencyObjectObjekten stellen Freezable-Objekte Änderungsbenachrichtigungen bereit, wenn sich Untereigenschaftswerte ändern.
Einfaches Klonen: Die Freezable-Klasse hat bereits mehrere Methoden implementiert, die tiefe Klonen erzeugen.
A Freezable ist ein Typ von DependencyObjectund verwendet daher das Abhängigkeitseigenschaftssystem. Ihre Klasseneigenschaften müssen nicht Abhängigkeitseigenschaften sein, aber die Verwendung von Abhängigkeitseigenschaften reduziert die Menge des Codes, den Sie schreiben müssen, da die Freezable Klasse unter Berücksichtigung von Abhängigkeitseigenschaften entworfen wurde. Weitere Informationen zum Abhängigkeitseigenschaftensystem finden Sie in der Übersicht über Abhängigkeitseigenschaften.
Jede Freezable Unterklasse muss die CreateInstanceCore Methode überschreiben. Wenn Ihre Klasse Abhängigkeitseigenschaften für alle Daten verwendet, sind Sie fertig.
Wenn Ihre Klasse Nicht-Abhängigkeitseigenschaftsdatenmmber enthält, müssen Sie auch die folgenden Methoden außer Kraft setzen:
Außerdem müssen Sie die folgenden Regeln für den Zugriff auf und das Schreiben von Datenmitglieder beachten, die keine Abhängigkeitseigenschaften sind:
Rufen Sie zu Beginn einer API, die Datenmitglieder mit Nicht-Abhängigkeitseigenschaften liest, die ReadPreamble Methode auf.
Rufen Sie am Anfang jeder API, die Nicht-Abhängigkeitseigenschaftsdatenmitglieder schreibt, die WritePreamble Methode auf. (Nachdem Sie WritePreamble in einer API aufgerufen haben, müssen Sie keinen zusätzlichen Aufruf zu ReadPreamble ausführen, wenn Sie auch Nicht-Abhängigkeitseigenschaftsdatenmitglieder lesen.)
Rufen Sie die WritePostscript Methode auf, bevor Sie Methoden beenden, die in Nicht-Abhängigkeitseigenschafts-Datenmitglieder schreiben.
Wenn Ihre Klasse Datenmitglieder, die keine Abhängigkeitseigenschaften sind, enthält, die DependencyObject Objekte sind, müssen Sie auch jedes Mal die OnFreezablePropertyChanged Methode aufrufen, wenn Sie einen ihrer Werte ändern, selbst wenn Sie das Element auf null
festlegen.
Hinweis
Es ist sehr wichtig, dass Sie jede Freezable Methode, die Sie überschreiben, mit einem Aufruf der Basisimplementierung beginnen.
Ein Beispiel für eine benutzerdefinierte Klasse finden Sie im Freezable Animationen.
Siehe auch
.NET Desktop feedback