Přehled prostředků XAML (WPF .NET)

Prostředek je objekt, který je možné opakovaně používat na různých místech aplikace. Mezi příklady prostředků patří štětce a styly. Tento přehled popisuje, jak používat prostředky v jazyk Extensible Application Markup Language (XAML) (XAML). Můžete také vytvářet prostředky a přistupovat k prostředkům pomocí kódu.

Poznámka

Prostředky XAML popsané v tomto článku se liší od prostředků aplikace, což jsou obecně soubory přidané do aplikace, jako je obsah, data nebo vložené soubory.

Důležité

Dokumentace k desktopové příručce pro .NET 6 a .NET 5 (včetně .NET Core 3.1) je ve stávajícím prostředí.

Použití prostředků v jazyce XAML

Následující příklad definuje jako SolidColorBrush prostředek v kořenovém prvku stránky. Příklad pak odkazuje na prostředek a používá ho k nastavení vlastností několika podřízených elementů, Ellipsevčetně elementů , a TextBlock.Button

<Window x:Class="resources.ResExample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ResExample" Height="400" Width="300">
    <Window.Resources>
        <SolidColorBrush x:Key="MyBrush" Color="#05E0E9"/>
        <Style TargetType="Border">
            <Setter Property="Background" Value="#4E1A3D" />
            <Setter Property="BorderThickness" Value="5" />
            <Setter Property="BorderBrush">
                <Setter.Value>
                    <LinearGradientBrush>
                        <GradientStop Offset="0.0" Color="#4E1A3D"/>
                        <GradientStop Offset="1.0" Color="Salmon"/>
                    </LinearGradientBrush>
                </Setter.Value>
            </Setter>
        </Style>
        <Style TargetType="TextBlock" x:Key="TitleText">
            <Setter Property="FontSize" Value="18"/>
            <Setter Property="Foreground" Value="#4E87D4"/>
            <Setter Property="FontFamily" Value="Trebuchet MS"/>
            <Setter Property="Margin" Value="0,10,10,10"/>
        </Style>
        <Style TargetType="TextBlock" x:Key="Label">
            <Setter Property="HorizontalAlignment" Value="Right"/>
            <Setter Property="FontSize" Value="13"/>
            <Setter Property="Foreground" Value="{StaticResource MyBrush}"/>
            <Setter Property="FontFamily" Value="Arial"/>
            <Setter Property="FontWeight" Value="Bold"/>
            <Setter Property="Margin" Value="0,3,10,0"/>
        </Style>
    </Window.Resources>

    <Border>
        <StackPanel>
            <TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
            <TextBlock Style="{StaticResource Label}">Label</TextBlock>
            <TextBlock HorizontalAlignment="Right" FontSize="36" Foreground="{StaticResource MyBrush}" Text="Text" Margin="20" />
            <Button HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">Button</Button>
            <Ellipse HorizontalAlignment="Center" Width="100" Height="100" Fill="{StaticResource MyBrush}" Margin="10" />
        </StackPanel>
    </Border>

</Window>

Každý prvek na úrovni architektury (FrameworkElement nebo ) má Resources vlastnost , což je ResourceDictionary typ, který FrameworkContentElementobsahuje definované prostředky. Prostředky můžete definovat pro libovolný prvek, například Button. Prostředky jsou však nejčastěji definovány v kořenovém elementu, což je Window v příkladu.

Každý prostředek ve slovníku prostředků musí mít jedinečný klíč. Při definování prostředků v kódu přiřadíte jedinečný klíč prostřednictvím direktivy x:Key. Klíč je obvykle řetězec. Můžete ho ale také nastavit na jiné typy objektů pomocí příslušných rozšíření značek. Ne řetězcové klíče pro prostředky jsou používány určitými oblastmi funkcí ve WPF, zejména pro styly, prostředky komponent a styly dat.

Můžete použít definovaný prostředek se syntaxí rozšíření značek prostředků, která určuje název klíče prostředku. Prostředek můžete například použít jako hodnotu vlastnosti na jiném prvku.

<Button Background="{StaticResource MyBrush}"/>
<Ellipse Fill="{StaticResource MyBrush}"/>

Když v předchozím příkladu zavaděč XAML {StaticResource MyBrush}BackgroundButtonzpracuje hodnotu vlastnosti na , logika vyhledávání prostředků nejprve zkontroluje slovník prostředků pro Button element . Pokud Button nemá definici MyBrush klíče prostředku (v tomto příkladu ne; jeho kolekce prostředků je prázdná), vyhledávání dále zkontroluje nadřazený prvek objektu Button. Pokud prostředek není definovaný v nadřazeném objektu, bude pokračovat v kontrole logického stromu objektu směrem nahoru, dokud není nalezen.

Pokud definujete prostředky v kořenovém elementu, mají k ní přístup všechny prvky v logickém stromu, WindowPagenapříklad nebo . A můžete znovu použít stejný prostředek pro nastavení hodnoty libovolné vlastnosti, která přijímá stejný typ jako prostředek. V předchozím příkladu stejný prostředek MyBrush nastavuje dvě různé vlastnosti: Button.Background a Rectangle.Fill.

Statické a dynamické prostředky

Na prostředek lze odkazovat jako na statický nebo dynamický. Odkazy se vytvářejí pomocí rozšíření značek StaticResource nebo rozšíření značek DynamicResource. Rozšíření značek je funkce XAML, která umožňuje určit odkaz na objekt tím, že rozšíření značek zpracuje řetězec atributu a vrátí objekt do zavaděče XAML. Další informace o chování rozšíření značek najdete v tématu Rozšíření značek a WPF XAML.

Při použití rozšíření značek obvykle zadáte jeden nebo více parametrů ve formě řetězce, které jsou zpracovány tímto konkrétním rozšířením značek. Rozšíření značek StaticResource zpracovává klíč tak, že hledá hodnotu tohoto klíče ve všech dostupných slovníkech prostředků. Ke zpracování dochází během načítání, což je v případě, že proces načítání potřebuje přiřadit hodnotu vlastnosti. Rozšíření značek DynamicResource místo toho zpracuje klíč vytvořením výrazu a tento výraz zůstane neohodnocený, dokud se aplikace nes spustí. V tomto okamžiku se výraz vyhodnotí tak, aby poskytoval hodnotu.

Při odkazování na prostředek mohou následující aspekty ovlivnit, zda používáte odkaz na statické prostředky nebo dynamické odkazy na prostředky:

  • Při určování celkového návrhu způsobu vytváření prostředků pro aplikaci (na stránku, v aplikaci, ve volném XAML nebo v sestavení pouze pro prostředky) zvažte následující:

  • Funkce aplikace. Jsou aktualizace prostředků součástí požadavků vaší aplikace v reálném čase?

  • Odpovídající chování vyhledávání tohoto typu odkazu na prostředek.

  • Konkrétní vlastnost nebo typ prostředku a nativní chování těchto typů.

Statické prostředky

Odkazy na statické prostředky fungují nejlépe za následujících okolností:

  • Návrh aplikace se soustředí na většinu svých prostředků do slovníků prostředků na úrovni stránky nebo aplikace.

    Odkazy na statické prostředky se znovu nevyhodnotí na základě chování modulu runtime, jako je například opětovné načtení stránky. To může mít určité výhody z výkonu, abyste se vyhnuli velkému počtu odkazů na dynamické prostředky, když nejsou potřeba na základě návrhu vašeho prostředku a aplikace.

  • Nastavíte hodnotu vlastnosti, která není v DependencyObject objektu nebo Freezable.

  • Vytváříte slovník prostředků, který je zkompilován do knihovny DLL, která je sdílená mezi aplikacemi.

  • Vytváříte motiv pro vlastní ovládací prvek a definujete prostředky, které se v motivech používají.

    V takovém případě obvykle nechcete chování dynamického vyhledávání odkazů na prostředky. Místo toho použijte chování odkazu na statické prostředky, aby bylo vyhledávání předvídatelné a samostatné pro motiv. Při použití dynamického odkazu na prostředek se dokonce ani odkaz v rámci motivu neohodnocuje až do doby běhu. Existuje také možnost, že při použití motivu se v některém místním elementu předefinuje klíč, na který se motiv pokouší odkazovat, a místní prvek bude spadat před samotný motiv ve vyhledávání. Pokud k tomu dojde, nebude se motiv chovat podle očekávání.

  • Prostředky používáte k nastavení velkého počtu vlastností závislosti. Vlastnosti závislostí mají efektivní ukládání hodnot do mezipaměti, jak je povoleno systémem vlastností, takže pokud zadáte hodnotu vlastnosti závislosti, kterou je možné vyhodnotit při načítání, nemusí vlastnost závislosti kontrolovat přehodnocený výraz a může vrátit poslední efektivní hodnotu. Tato technika může být výkonnou výhodou.

  • Chcete změnit základní prostředek pro všechny příjemce nebo chcete udržovat samostatné zapisovatelné instance pro každého příjemce pomocí atributu x:Shared.

Chování vyhledávání statických prostředků

Následující část popisuje proces vyhledávání, který automaticky nastane, když na statický prostředek odkazuje vlastnost nebo element:

  1. Proces vyhledávání vyhledá požadovaný klíč ve slovníku prostředků definovaném elementem , který nastavuje vlastnost .

  2. Proces vyhledávání pak logickou stromovou strukturu procházející směrem nahoru k nadřazenému elementu a jeho slovníku prostředků. Tento proces pokračuje, dokud není dosaženo kořenového elementu.

  3. Kontroluje se prostředky aplikace. Prostředky aplikace jsou prostředky ve slovníku prostředků, který je definovaný objektem Application pro vaši aplikaci WPF.

Odkazy na statické prostředky ze slovníku prostředků musí odkazovat na prostředek, který již byl definován lexikálně před odkazem na prostředek. Dopředné odkazy nelze přeložit pomocí odkazu na statické prostředky. Z tohoto důvodu navrhovat strukturu slovníku prostředků tak, aby se prostředky definovali na začátku každého slovníku příslušných prostředků nebo poblíž nich.

Vyhledávání statických prostředků se může rozšířit na motivy nebo do systémových prostředků, ale toto vyhledávání se podporuje pouze proto, že zavaděč XAML odpůruje požadavek. Odložení je nezbytné, aby motiv modulu runtime v době načtení stránky správně fungoval pro aplikaci. Odkazy na statické prostředky na klíče, o kterých je známo, že existují pouze v motivech nebo jako systémové prostředky, se však nedoporučuje, protože takové odkazy se přehodnotí, pokud uživatel motiv změní v reálném čase. Dynamické odkazy na prostředky jsou spolehlivější, když si vyžádáte motiv nebo systémové prostředky. Výjimkou je, když samotný prvek motivu požaduje jiný prostředek. Tyto odkazy by měly být odkazy na statické prostředky z důvodů uvedených výše.

Chování výjimky v případě, že není nalezen odkaz na statický prostředek, se liší. Pokud byl prostředek odložen, dojde k výjimce za běhu. Pokud nebyl prostředek odložen, dojde k výjimce při načítání.

Dynamické prostředky

Dynamické prostředky fungují nejlépe v případě, že:

  • Hodnota prostředku, včetně systémových prostředků nebo prostředků, které jsou jinak uživatelem nastavitelné, závisí na podmínkách, které nejsou známé až do spuštění. Můžete například vytvořit hodnoty setter, které odkazují na systémové vlastnosti zveřejněné pomocí SystemColors, SystemFontsnebo SystemParameters. Tyto hodnoty jsou skutečně dynamické, protože nakonec pocházejí z běhového prostředí uživatele a operačního systému. Můžete mít také motivy na úrovni aplikace, které se můžou změnit, kde přístup k prostředkům na úrovni stránky také musí změnu zachytit.

  • Vytváříte styly motivu pro vlastní ovládací prvek nebo na tyto styly odkazujete.

  • Máte v úmyslu upravit obsah ResourceDictionary během životnosti aplikace.

  • Máte složitou strukturu prostředků, která má vzájemné závislosti, kde může být vyžadován dopředné odkaz. Odkazy na statické prostředky nepodporují dopředné odkazy, ale dynamické odkazy na prostředky je podporují, protože prostředek není potřeba vyhodnocovat, dokud modul runtime, a dopředné odkazy proto nejsou relevantním konceptem.

  • Odkazujete na prostředek, který je z pohledu kompilované nebo pracovní sady velký, a tento prostředek se při načtení stránky nemusí použít okamžitě. Odkazy na statické prostředky se při načtení stránky vždy načítá z XAML. Dynamický odkaz na prostředek se ale nenačte, dokud se nepouží.

  • Vytváříte styl, ve kterém hodnoty setter mohou pochovat z jiných hodnot, které jsou ovlivněny motivy nebo jinými uživatelskými nastaveními.

  • Prostředky aplikujete na prvky, které mohou být během doby života aplikace v logickém stromu znovu zachované. Změna nadřazeného objektu může také potenciálně změnit obor vyhledávání prostředků, takže pokud chcete, aby byl prostředek pro znovuhodnocený element na základě nového oboru, vždy použijte dynamický odkaz na prostředek.

Chování dynamického vyhledávání prostředků

Chování vyhledávání prostředků pro dynamické odkazy na prostředky paralelně pracuje s chováním vyhledávání v kódu, pokud zavoláte nebo FindResourceSetResourceReference:

  1. Vyhledávání vyhledá požadovaný klíč ve slovníku prostředků definovaném elementem , který nastavuje vlastnost :

  2. Vyhledávání projde logický strom směrem nahoru k nadřazenému prvku a jeho slovníku prostředků. Tento proces pokračuje, dokud není dosaženo kořenového prvku.

  3. Prostředky aplikace jsou zkontrolovány. Prostředky aplikací jsou tyto prostředky v rámci slovníku prostředků, které jsou definovány Application objektem pro vaši aplikaci WPF.

  4. Slovník prostředků motivu je kontrolován pro aktuálně aktivní motiv. Pokud se motiv změní za běhu, hodnota se znovu vyhodnotí.

  5. Jsou zaškrtnuté systémové prostředky.

Chování výjimky (pokud existuje) se liší:

  • Pokud byl prostředek vyžádán FindResource voláním a nebyl nalezen, je vyvolána výjimka.

  • Pokud byl prostředek vyžádán TryFindResource voláním a nebyl nalezen, není vyvolána žádná výjimka a vrácená hodnota je null . Pokud vlastnost nastavená nepřijímá null , je stále možné, že bude vyvolána hlubší výjimka v závislosti na nastavené individuální vlastnosti.

  • Pokud byl prostředek vyžádán odkazem dynamického prostředku v jazyce XAML a nebyl nalezen, bude chování záviset na obecném systému vlastností. Obecné chování je, jako kdyby na úrovni, kde existuje prostředek, nedošlo k žádné operaci nastavení vlastnosti. Například pokud se pokusíte nastavit pozadí na jednotlivé prvky tlačítka pomocí prostředku, který nebylo možné vyhodnotit, pak se nenastaví žádná hodnota, ale efektivní hodnota může být z jiných účastníků v rámci nastavení systému vlastností a hodnoty. Hodnota pozadí může být například stále z lokálně definovaného stylu tlačítka nebo ze stylu motivu. Pro vlastnosti, které nejsou definovány styly motivů, může platit efektivní hodnota po neúspěšném vyhodnocení prostředku z výchozí hodnoty v metadatech vlastností.

Omezení

Odkazy na dynamické prostředky mají určitá významná omezení. Alespoň jedna z následujících podmínek musí být pravdivá:

Vzhledem k tomu, že nastavená vlastnost musí být DependencyProperty vlastnost nebo Freezable , může se většina změn vlastností šířit do uživatelského rozhraní, protože Změna vlastnosti (změněná hodnota dynamického prostředku) je potvrzena systémem vlastností. Většina ovládacích prvků zahrnuje logiku, která vynutí jiné rozložení ovládacího prvku, pokud DependencyProperty změny a tato vlastnost mohou ovlivnit rozložení. Nicméně ne všechny vlastnosti, které mají rozšíření značek DynamicResource jako jejich hodnota, jsou zaručeny pro poskytování aktualizací v reálném čase v uživatelském rozhraní. Tato funkce se pořád může lišit v závislosti na vlastnosti a v závislosti na typu, který vlastní vlastnost, nebo dokonce na logické struktuře vaší aplikace.

Styly, šablony a implicitní klíče

I když všechny položky v ResourceDictionary musí mít klíč, to neznamená, že všechny prostředky musí mít explicitní x:Key . Několik typů objektů podporuje implicitní klíč, pokud je definován jako prostředek, kde hodnota klíče je svázána s hodnotou jiné vlastnosti. Tento typ klíče je známý jako implicitní klíč a x:Key atribut je explicitní klíč. Můžete přepsat libovolný implicitní klíč zadáním explicitního klíče.

Jeden z důležitých scénářů pro prostředky je při definování Style . Ve skutečnosti Style je téměř vždy definováno jako položka ve slovníku prostředků, protože styly jsou podstatně určeny k opakovanému použití. Další informace o stylech naleznete v tématu styly a šablony (WPF .NET).

Styly pro ovládací prvky mohou být vytvořeny pomocí a odkazovány pomocí implicitního klíče. Styly motivů, které definují výchozí vzhled ovládacího prvku, spoléhají na tento implicitní klíč. Z hlediska vyžádání je Type implicitní klíč samotného ovládacího prvku. Z hlediska definování prostředků je TargetType implicitní klíč ve stylu. Pokud například vytváříte motivy pro vlastní ovládací prvky nebo vytváříte styly, které pracují se stávajícími styly motivů, není pro Style ni nutné zadávat direktivu x:Key – . A pokud chcete použít styly motivů, nemusíte vůbec zadávat žádný styl. Následující definice stylu například funguje, i když se zdá, že Style prostředek nemá klíč:

<Style TargetType="Button">
    <Setter Property="Background" Value="#4E1A3D" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="BorderThickness" Value="5" />
    <Setter Property="BorderBrush">
        <Setter.Value>
            <LinearGradientBrush>
                <GradientStop Offset="0.0" Color="#4E1A3D"/>
                <GradientStop Offset="1.0" Color="Salmon"/>
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
</Style>

Styl má ve skutečnosti klíč: implicitní klíč System.Windows.Controls.Button : typ. V kódu můžete zadat TargetType přímo jako název typu (případně můžete použít {x:Type...} ) pro vrácení Type .

Pomocí výchozího mechanismu stylu motivu používaného WPF je tento styl použit jako styl Button modulu runtime na stránce, i když Button se sám o sobě nepokusí zadat jeho Style vlastnost nebo konkrétní odkaz na prostředek na styl. Váš styl definovaný na stránce se nachází dříve v sekvenci vyhledávání než styl slovníku motivu pomocí stejného klíče, který má styl slovníku motivů. Mohli byste jenom zadat <Button>Hello</Button> kamkoli na stránce a styl, který jste definovali, se ButtonTargetType použije pro toto tlačítko. Pokud chcete, můžete stále explicitně klíčovat styl se stejnou hodnotou TargetType typu, která je pro přehlednost v kódu, ale volitelná.

Implicitní klíče pro styly neplatí pro ovládací prvek, pokud OverridesDefaultStyle je true . (Všimněte si také, že OverridesDefaultStyle může být nastaveno jako součást nativního chování pro třídu ovládacího prvku, nikoli explicitně na instanci ovládacího prvku.) Aby bylo možné podporovat implicitní klíče pro odvozené třídy, ovládací prvek musí přepsat DefaultStyleKey (všechny existující ovládací prvky, které jsou součástí WPF jako součást tohoto přepsání). Další informace o stylech, motivech a návrhu ovládacích prvků naleznete v tématu pokyny pro návrh ovládacích ovládacích prvků.

DataTemplate má také implicitní klíč. Implicitní klíč pro DataTemplate je DataType hodnota vlastnosti. DataType lze také zadat jako název typu místo explicitního použití {x:Type...}. Podrobnosti najdete v tématu Přehled šablonování dat.

Viz také