Přehled zamrznutelných objektů
Toto téma popisuje, jak efektivně používat a vytvářet Freezable objekty, které poskytují speciální funkce, které pomáhají zlepšit výkon aplikace. Mezi příklady zamrznutelných objektů patří štětce, pera, transformace, geometrie a animace.
Co je to zamrazitelné?
Freezable je speciální typ objektu se dvěma stavy: rozmrazený a zmrazený. Když Freezable rozmrazíte, zdá se, že se chová jako jakýkoli jiný objekt. Když je Freezable zmrazený, už ho nelze upravovat.
Freezable poskytuje událost Changed, která oznámí pozorovatelům veškeré úpravy objektu. Zmrazení Freezable může zlepšit jeho výkon, protože už nemusí trávit prostředky na oznámení o změnách. Zmrazený Freezable lze také sdílet napříč vlákny, zatímco nezmrazený Freezable nelze.
I když Freezable třída má mnoho aplikací, většina Freezable objektů v systému Windows Presentation Foundation (WPF) souvisí s grafickým podsystémem.
Třída Freezable usnadňuje používání určitých grafických systémových objektů a pomáhá zlepšit výkon aplikace. Příklady typů, které dědí z Freezable, zahrnují třídy Brush, Transforma Geometry. Vzhledem k tomu, že obsahují nespravované prostředky, musí systém tyto objekty monitorovat a aktualizovat odpovídající nespravované prostředky, pokud dojde ke změně původního objektu. I když ve skutečnosti neupravíte objekt grafického systému, musí systém stále trávit některé jeho prostředky monitorováním objektu, pokud ho změníte.
Předpokládejme například, že vytvoříte SolidColorBrush štětec a použijete ho k vykreslení pozadí tlačítka.
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
Když se tlačítko vykreslí, použije dílčí systém grafiky WPF informace, které jste zadali k vykreslení skupiny pixelů k vytvoření vzhledu tlačítka. I když jste použili plný barevný štětec k popisu způsobu malování tlačítka, plný barevný štětec ve skutečnosti neprovádí malování. Grafický systém generuje pro tlačítko a štětec rychlé objekty nízké úrovně a jedná se o objekty, které se skutečně zobrazují na obrazovce.
Pokud byste chtěli upravit štětec, tyto předměty nižší úrovně by se musely znovu vygenerovat. Třída Freezable dává štětci schopnost najít odpovídající vygenerované nízkoúrovňové objekty a aktualizovat je při změně. Když je tato schopnost povolená, štětec se říká, že je "nefrozen".
Zamrznutelná metoda Freeze umožňuje zakázat tuto možnost samoobslužné aktualizace. Tuto metodu můžete použít k tomu, aby se kartáč stal "ukotveným" nebo neupravitelným.
Poznámka
Ne každý zmrazený objekt lze zamrznout. Aby se předešlo vyvolání výjimky InvalidOperationException, zkontrolujte hodnotu vlastnosti CanFreeze objektu Freezable, abyste zjistili, zda může být zmrazen před pokusem o jeho zmrazení.
if (myBrush.CanFreeze)
{
// Makes the brush unmodifiable.
myBrush.Freeze();
}
If myBrush.CanFreeze Then
' Makes the brush unmodifiable.
myBrush.Freeze()
End If
Pokud již nepotřebujete měnit nezmrazený objekt, jeho zmrazení poskytne výhody výkonu. Kdybyste v tomto příkladu zamrzli štětec, grafický systém by už ho nemusel sledovat kvůli změnám. Grafický systém může také provádět další optimalizace, protože ví, že se štětec nezmění.
Poznámka
Pro usnadnění zůstanou zmrazitelné objekty nezmrazeny, pokud je explicitně nezmrazíte.
Použití zmrazitelných objektů
Použití rozmrazeného zmrazitelného objektu je podobné použití jakéhokoli jiného typu objektu. V následujícím příkladu se barva SolidColorBrush po použití k malování pozadí tlačítka změní ze žluté na červenou. Grafický systém funguje na pozadí a automaticky změní tlačítko ze žluté na červenou při příští aktualizaci obrazovky.
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
Zmrazení něčeho, co lze zmrazit
Chcete-li, aby Freezable bylo nemodifikovatelné, zavoláte jeho metodu Freeze. Když zmrazíš objekt, který obsahuje zmrazitelné objekty, jsou tyto objekty také zmrazeny. Pokud například zmrazíte PathGeometry, údaje a segmenty, které obsahuje, by se také zablokovaly.
Zamrznutá nemůže být zmrazena, pokud platí některá z následujících možností:
Obsahuje animované vlastnosti nebo vlastnosti vázané na data.
Vlastnosti jsou nastaveny dynamickým prostředkem. (Další informace o dynamických prostředcích najdete v prostředcích XAML.)
Obsahuje Freezable dílčí objekty, které nelze zmrazit.
Pokud jsou tyto podmínky nepravdivé a nemáte v úmyslu upravit Freezable, měli byste ho ukotvit, abyste získali výhody výkonu popsané výše.
Jakmile zavoláte metodu Freeze z objektu Freezable, nelze ji již upravovat. Pokus o úpravu zmrazeného objektu způsobí vyvolání výjimky InvalidOperationException. Následující kód vyvolá výjimku, protože se pokusíme upravit štětec po jeho zmrazení.
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
Chcete-li se vyhnout vyvolání této výjimky, můžete pomocí metody IsFrozen určit, zda je Freezable zablokovaný.
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
V předchozím příkladu kódu byla vytvořena modifikovatelná kopie zmrazeného objektu pomocí metody Clone. Další část popisuje klonování podrobněji.
Poznámka
Vzhledem k tomu, že zamrzlý zamrzající objekt nelze animovat, animační systém automaticky vytvoří modifikovatelné klony zamrzlých Freezable objektů, když se pokusíte animovat je pomocí Storyboard. Chcete-li eliminovat režii na výkon způsobenou klonováním, ponechte objekt nezmražený, pokud ho chcete animovat. Další informace o animaci pomocí scénářů naleznete v tématu Storyboards Přehled.
Zastavení z označení
Pokud chcete ukotvit objekt Freezable deklarovaný v kódu, použijte atribut PresentationOptions:Freeze
. V následujícím příkladu je SolidColorBrush deklarován jako prostředek stránky a zmrazený. Pak se použije k nastavení pozadí tlačítka.
<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>
Chcete-li použít atribut Freeze
, musíte jej přiřadit k oboru názvů možností prezentace: http://schemas.microsoft.com/winfx/2006/xaml/presentation/options
. Doporučená předpona pro mapování tohoto jmenného prostoru je PresentationOptions
.
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
Vzhledem k tomu, že tento atribut nerozpozná všichni čtenáři XAML, doporučujeme použít mc:Ignorable Atribut k označení atributu PresentationOptions:Freeze
jako ignorable:
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"
Další informace najdete na stránce mc:Ignorable Attribute.
Rozmrazení zamražitelného
Jakmile je Freezable zmrazen, nelze jej nikdy změnit ani rozmrazit; můžete však vytvořit nezmrazený klon pomocí metody Clone nebo CloneCurrentValue.
V následujícím příkladu je pozadí tlačítka nastaveno štětcem a ten je pak zmrazený. Rozmražená kopie je vyrobena ze štětce pomocí metody Clone. Klon se upraví a použije se ke změně pozadí tlačítka ze žluté na červenou.
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
Poznámka
Bez ohledu na to, kterou metodu klonování použijete, se animace nikdy nekopírují do nového Freezable.
Metody Clone a CloneCurrentValue vytvářejí hluboké kopie zmrazitelných objektů. Pokud zmrzlinovatelné objekty obsahují další zmrazené zmrzlinovatelné objekty, jsou také klonovány a stávají se upravitelnými. Pokud například naklonujete zmrazenou PathGeometry, aby bylo možné ho upravit, budou údaje a segmenty, které obsahuje, zkopírovány a upraveny.
Vytvoření vlastní třídy s možností zamčení změn
Třída odvozená z Freezable získá následující funkce.
Zvláštní stavy: jen pro čtení (zmrazené) a zapisovatelný stav.
Bezpečnost vláken: zmrazené Freezable lze sdílet napříč vlákny.
Podrobné oznámení: Na rozdíl od jiných DependencyObjectposkytují zmrazitelné objekty oznámení o změnách hodnot dílčích vlastností.
Snadné klonování: Třída Freezable již obsahuje několik metod, které vytvářejí hluboké kopie.
Freezable je typ DependencyObject, a proto používá systém vlastností závislostí. Vlastnosti třídy nemusí být vlastnosti závislostí, ale použitím vlastností závislosti se sníží množství kódu, který musíte napsat, protože třída Freezable byla navržena s ohledem na vlastnosti závislostí. Další informace o systému vlastností závislostí naleznete v přehledu vlastností závislostí.
Každá podtřída Freezable musí překonat metodu CreateInstanceCore. Pokud vaše třída používá vlastnosti závislostí pro všechna její data, jste hotovi.
Pokud vaše třída obsahuje datové členy vlastností, které nejsou závislé, musíte také přepsat následující metody:
Musíte také dodržovat následující pravidla pro přístup k datovým členům, kteří nejsou vlastnostmi závislosti a zápis do nich:
Na začátku jakéhokoli rozhraní API, které čte datové členy nesouvisející s vlastnostmi závislosti, zavolejte metodu ReadPreamble.
Na začátku každého API, které zapisuje datové členy vlastností nezávislých na závislostech, zavolejte metodu WritePreamble. (Po volání WritePreamble v rozhraní API nemusíte provádět další volání ReadPreamble, pokud také čtete datové členy vlastností, které nejsou závislé.)
Před ukončením metod, které zapisují do datových členů vlastností, které nejsou závislé, volejte metodu WritePostscript.
Pokud vaše třída obsahuje datové členy bez závislostí, které jsou DependencyObject objekty, musíte také volat metodu OnFreezablePropertyChanged pokaždé, když změníte jednu z jejich hodnot, i když nastavujete člena na null
.
Poznámka
Je velmi důležité, abyste zahájili každou metodu Freezable, kterou přepíšete voláním základní implementace.
Příklad vlastní třídy Freezable najdete v ukázce vlastní animace.
Viz také
- Freezable
- ukázka vlastní animace
- Přehled vlastností závislosti
- Vlastní vlastnosti závislostí
.NET Desktop feedback