Delen via


Overzicht van bevriesbare Objecten

In dit onderwerp wordt beschreven hoe u effectief Freezable objecten kunt gebruiken en maken, die speciale functies bieden waarmee de prestaties van toepassingen kunnen worden verbeterd. Voorbeelden van bevriesbare objecten zijn borstels, pennen, transformaties, geometrieën en animaties.

Wat is een invriesbaar object?

Een Freezable is een speciaal type object met twee statussen: ontrozen en bevroren. Wanneer u de Freezable niet hebt ingevroren, lijkt het alsof het zich gedraagt als elk ander object. Wanneer een Freezable is bevroren, kan het niet meer worden gewijzigd.

Een Freezable biedt een Changed-gebeurtenis om waarnemers te informeren over eventuele wijzigingen in het object. Het blokkeren van een Freezable kan de prestaties verbeteren, omdat het geen resources meer hoeft te besteden aan wijzigingsmeldingen. Een bevroren Freezable kan ook worden gedeeld tussen threads, terwijl een niet-bevroren Freezable dat niet kan.

Hoewel de Freezable klasse veel toepassingen heeft, zijn de meeste Freezable objecten in Windows Presentation Foundation (WPF) gerelateerd aan het grafische subsysteem.

De Freezable-klasse maakt het eenvoudiger om bepaalde grafische systeemobjecten te gebruiken en kan de prestaties van toepassingen verbeteren. Voorbeelden van typen die overnemen van Freezable zijn de Brush, Transformen Geometry klassen. Omdat ze onbeheerde resources bevatten, moet het systeem deze objecten controleren op wijzigingen en vervolgens de bijbehorende onbeheerde resources bijwerken wanneer het oorspronkelijke object wordt gewijzigd. Zelfs als u een grafisch systeemobject niet daadwerkelijk wijzigt, moet het systeem nog steeds enkele van de resources besteden aan het bewaken van het object, voor het geval u dit wijzigt.

Stel dat u een SolidColorBrush penseel maakt en deze gebruikt om de achtergrond van een knop te schilderen.

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

Wanneer de knop wordt weergegeven, gebruikt het WPF-grafische subsysteem de informatie die u hebt opgegeven om een groep pixels te schilderen en zo het uiterlijk van een knop te vormen. Hoewel u een effen kleur penseel hebt gebruikt om te beschrijven hoe de knop moet worden geschilderd, brengt uw effen kleur penseel niet daadwerkelijk verf aan. Het grafische systeem genereert snelle laag-niveau objecten voor de knop en de kwast, en deze objecten verschijnen daadwerkelijk op het scherm.

Als u de kwast zou wijzigen, moeten deze objecten op laag niveau opnieuw worden gegenereerd. De bevriesbare klasse geeft een penseel de mogelijkheid om zijn overeenkomstige gegenereerde objecten op laag niveau te vinden en deze bij te werken wanneer deze veranderen. Wanneer deze mogelijkheid is ingeschakeld, wordt gezegd dat de borstel 'unfrozen' is.

Met de Freeze methode van een freezable kunt u deze mogelijkheid voor zelfupdates uitschakelen. U kunt deze methode gebruiken om de borstel "bevroren," of niet aanpasbaar, te maken.

Opmerking

Niet elk Freezable-object kan worden bevroren. Om te voorkomen dat u een InvalidOperationExceptiongenereert, controleert u de waarde van de eigenschap CanFreeze van het Freezable-object om te bepalen of het kan worden bevroren voordat u probeert het te bevriezen.

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

Wanneer u een freezable niet meer hoeft te wijzigen, biedt het blokkeren prestatievoordelen. Als u het penseel in dit voorbeeld zou bevriezen, zou het grafische systeem het niet meer hoeven controleren op wijzigingen. Het grafische systeem kan ook andere optimalisaties uitvoeren, omdat het weet dat de kwast niet verandert.

Opmerking

Voor het gemak blijven invrisbare objecten onbevroren, tenzij u ze expliciet bevriest.

Freezables gebruiken

Het gebruik van een unfrozen freezable is zoals het gebruik van elk ander type object. In het volgende voorbeeld wordt de kleur van een SolidColorBrush gewijzigd van geel in rood nadat deze is gebruikt om de achtergrond van een knop te schilderen. Het grafische systeem werkt achter de schermen om de knop automatisch te wijzigen van geel in rood wanneer het scherm de volgende keer wordt vernieuwd.

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

Een freezable bevriezen

Om een Freezable onveranderlijk te maken, roept u de Freeze methode aan. Wanneer je een object bevriest dat bevriesbare objecten bevat, worden deze objecten ook bevroren. Als u bijvoorbeeld een PathGeometryblokkeert, worden de cijfers en segmenten die deze bevat ook geblokkeerd.

Een bevriesbare kan niet worden bevroren als een van de volgende waar is:

  • Het heeft geanimeerde of gegevensgebonden eigenschappen.

  • Het heeft eigenschappen ingesteld door een dynamische resource. (Zie de XAML-resources voor meer informatie over dynamische resources.)

  • Het bevat Freezable subobjecten die niet kunnen worden bevroren.

Als deze voorwaarden onwaar zijn en u niet van plan bent de Freezablete wijzigen, moet u deze blokkeren om de prestatievoordelen te verkrijgen die eerder zijn beschreven.

Zodra u de Freeze methode van een freezable aanroept, kan deze niet meer worden gewijzigd. Als u probeert een bevroren object te wijzigen, wordt er een InvalidOperationException opgeworpen. Met de volgende code wordt er een uitzondering opgeworpen, omdat we proberen de brush te wijzigen nadat deze bevroren is.


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

Om te voorkomen dat deze uitzondering wordt gegenereerd, kunt u de methode IsFrozen gebruiken om te bepalen of een Freezable is geblokkeerd.


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


In het voorgaande codevoorbeeld is een wijzigbare kopie gemaakt van een bevroren object met behulp van de methode Clone. In de volgende sectie wordt het klonen in meer detail besproken.

Opmerking

Omdat een bevroren freezable niet kan worden geanimeerd, maakt het animatiesysteem automatisch aanpasbare klonen van bevroren Freezable-objecten wanneer u ze probeert te animeren met een Storyboard. Als u de prestatieoverhead wilt elimineren die wordt veroorzaakt door klonen, laat u een object onrozen als u deze wilt animeren. Zie de Overviewvoor meer informatie over animaties met storyboards.

Blokkeren vanuit markeringen

Als u een Freezable-object wilt blokkeren dat in markeringen is gedeclareerd, gebruikt u het kenmerk PresentationOptions:Freeze. In het volgende voorbeeld wordt een SolidColorBrush gedeclareerd als een paginaresource en bevroren. Deze wordt vervolgens gebruikt om de achtergrond van een knop in te stellen.

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

Om het kenmerk Freeze te gebruiken, moet u dit koppelen aan de naamruimte voor presentatieopties: http://schemas.microsoft.com/winfx/2006/xaml/presentation/options. PresentationOptions is het aanbevolen voorvoegsel voor het in kaart brengen van deze naamruimte.

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

Omdat niet alle XAML-lezers dit kenmerk herkennen, is het raadzaam om de mc:Ignorable Attribute te gebruiken om het kenmerk PresentationOptions:Freeze als negeerbaar te markeren:

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

Zie de pagina mc:Ignorable Attribute voor meer informatie.

"Ontdooiing" van een "Freezable"

Eenmaal bevroren, kan een Freezable nooit worden gewijzigd of ontrozen; U kunt echter een niet-berozen kloon maken met behulp van de methode Clone of CloneCurrentValue.

In het volgende voorbeeld wordt de achtergrond van de knop ingesteld met een penseel en dat penseel wordt vervolgens bevroren. Een ontdooide kopie wordt gemaakt van de borstel met de Clone-methode. De kloon wordt gewijzigd en gebruikt om de achtergrond van de knop te wijzigen van geel in rood.

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

Opmerking

Ongeacht welke kloonmethode u gebruikt, worden animaties nooit gekopieerd naar de nieuwe Freezable.

De Clone- en CloneCurrentValue methodes produceren diepe kopieën van de bevriesbare. Als de freezable andere bevroren freezable-objecten bevat, worden deze ook gekloond en aanpasbaar gemaakt. Als u bijvoorbeeld een bevroren PathGeometry kloont om deze te wijzigen, worden ook de afbeeldingen en segmenten die deze bevat gekopieerd en gewijzigd.

Uw eigen freezable-klasse maken

Een klasse die is afgeleid van Freezable krijgt de volgende functies.

  • Speciale toestanden: een alleen-lezen (bevroren) toestand en een beschrijfbare toestand.

  • Threadveiligheid: een bevroren Freezable kan worden gedeeld tussen threads.

  • Gedetailleerde wijzigingsmelding: In tegenstelling tot andere DependencyObjectbieden freezable-objecten wijzigingsmeldingen wanneer de waarden van subeigenschappen worden gewijzigd.

  • Eenvoudig klonen: de Freezable-klasse heeft al verschillende methoden geïmplementeerd die diepe klonen produceren.

Een Freezable is een type DependencyObjecten maakt daarom gebruik van het afhankelijkheidseigenschapssysteem. Uw klasse-eigenschappen hoeven geen afhankelijkheidseigenschappen te zijn, maar het gebruik van afhankelijkheidseigenschappen vermindert de hoeveelheid code die u moet schrijven, omdat de Freezable klasse is ontworpen met afhankelijkheidseigenschappen in gedachten. Zie het overzicht Eigenschappen van afhankelijkheden voor meer informatie over het eigenschappensysteem voor afhankelijkheden.

Elke Freezable subklasse moet de methode CreateInstanceCore overschrijven. Als uw klasse afhankelijkheidseigenschappen gebruikt voor alle bijbehorende gegevens, bent u klaar.

Als uw klasse niet-afhankelijke eigenschapsgegevensleden bevat, moet u ook de volgende methoden overschrijven:

U moet ook de volgende regels observeren voor toegang tot en schrijven naar gegevensleden die geen afhankelijkheidseigenschappen zijn:

  • Aan het begin van een API die leden van niet-afhankelijke eigenschapsgegevens leest, roept u de ReadPreamble-methode aan.

  • Aan het begin van een API die leden van niet-afhankelijke eigenschapsgegevens schrijft, roept u de methode WritePreamble aan. Nadat u WritePreamble hebt aangeroepen in een API, hoeft u geen extra aanroep uit te voeren naar ReadPreamble als u ook gegevensleden van niet-afhankelijke eigenschappen leest.

  • Roep de methode WritePostscript aan voordat u methoden afsluit die naar gegevensleden van niet-afhankelijke eigenschappen schrijven.

Als uw klasse niet-afhankelijke gegevensleden bevat die DependencyObject objecten zijn, moet u ook de OnFreezablePropertyChanged methode aanroepen telkens wanneer u een van de waarden wijzigt, zelfs als u het lid instelt op null.

Opmerking

Het is erg belangrijk dat u bij elke Freezable-methode die u overschrijft, begint met een aanroep van de basisimplementatie.

Zie het Freezablevoor een voorbeeld van een aangepaste klasse.

Zie ook