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

Prostředek je objekt, který lze opakovaně použít 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 xaml (Extensible Application Markup Language). Prostředky můžete také vytvářet a přistupovat k němu pomocí kódu.

Poznámka:

Prostředky XAML popsané v tomto článku se liší od prostředků aplikace, které se obvykle přidávají do aplikace, jako je obsah, data nebo vložené soubory.

Důležité

Dokumentace k desktopové příručce pro .NET 7 a .NET 6 se právě připravuje.

Použití prostředků v XAML

Následující příklad definuje SolidColorBrush jako prostředek na 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 prvků, včetně , Ellipsea TextBlocka a 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 FrameworkContentElement) má Resources vlastnost, což je ResourceDictionary typ, který obsahuje 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 prvku, který 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 používají určité oblasti funkcí 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. Například použijte prostředek jako hodnotu vlastnosti na jiném prvku.

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

Když zavaděč XAML v předchozím příkladu zpracuje hodnotu {StaticResource MyBrush} vlastnosti BackgroundButton, vyhledávací logika prostředku nejprve zkontroluje slovník prostředků pro Button prvek. Pokud Button nemá definici klíče MyBrush prostředku (v tomto příkladu není, jeho kolekce prostředků je prázdná), vyhledávání v dalším kroku zkontroluje nadřazený prvek Button. Pokud prostředek není definovaný u nadřazeného objektu, bude pokračovat v kontrole logického stromu objektu vzhůru, dokud se nenajde.

Pokud definujete prostředky v kořenovém prvku, budou k němu mít přístup všechny prvky v logickém stromu, jako Window je například nebo Page. Stejný prostředek můžete znovu použít k nastavení hodnoty jakékoli vlastnosti, která přijímá stejný typ, který prostředek představuje. V předchozím příkladu stejný MyBrush prostředek nastaví dvě různé vlastnosti: Button.Background a Ellipse.Fill.

Statické a dynamické prostředky

Prostředek lze odkazovat buď jako 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 naleznete 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ů v řetězcové podobě, které jsou zpracovány tímto konkrétním rozšířením značek. Rozšíření značek StaticResource zpracovává klíč vyhledáním hodnoty pro tento klíč ve všech dostupných slovníkech prostředků. Zpracování probíhá během načítání, což je situace, kdy proces načítání potřebuje přiřadit hodnotu vlastnosti. Rozšíření značek DynamicResource místo toho zpracovává klíč vytvořením výrazu a tento výraz zůstane nehodnocený, dokud se aplikace nespustí, a vyhodnocuje se výraz tak, aby poskytoval hodnotu.

Při odkazování na prostředek můžou mít následující aspekty vliv na to, jestli používáte statický odkaz na prostředek nebo dynamický odkaz na prostředky:

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

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

  • 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

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

  • Návrh aplikace se soustředí na většinu prostředků na stránku nebo slovníky prostředků na úrovni aplikace.

    Statické odkazy na prostředky se znovu nevyhodnocují na základě chování modulu runtime, jako je opětovné načtení stránky. Proto může být nějaký přínos pro výkon, abyste se vyhnuli velkému počtu dynamických odkazů na prostředky, pokud nejsou nezbytné na základě návrhu vašeho prostředku a aplikace.

  • Nastavujete hodnotu vlastnosti, která není na objektu nebo v objektu DependencyObjectFreezable.

  • Vytváříte slovník prostředků, který je zkompilovaný do knihovny DLL, která se sdílí mezi aplikacemi.

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

    V tomto případě obvykle nechcete chování dynamického vyhledávání odkazů na prostředky. Místo toho použijte chování statického odkazu na prostředky, aby vyhledávání bylo předvídatelné a samostatné pro motiv. S dynamickým odkazem na prostředky se dokonce i odkaz v rámci motivu ponechá nehodnocený, dokud neběží za běhu. A je možné, že když se použije motiv, nějaký místní prvek předefinuje klíč, na který se váš motiv snaží odkazovat, a místní prvek spadne před samotným motivem ve vyhledávání. Pokud k tomu dojde, motiv se nebude chovat podle očekávání.

  • K nastavení velkého počtu vlastností závislostí používáte prostředky. Vlastnosti závislostí mají efektivní ukládání hodnot do mezipaměti, jak je povoleno systémem vlastností vlastností, takže pokud zadáte hodnotu vlastnosti závislosti, která se dá vyhodnotit v době načtení, vlastnost závislosti nemusí kontrolovat znovuhodnocený výraz a může vrátit poslední efektivní hodnotu. Tato technika může být výhodou výkonu.

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

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

Následující popis popisuje proces vyhledávání, který se automaticky provede, když na statický prostředek odkazuje vlastnost nebo prvek:

  1. Proces vyhledávání vyhledá požadovaný klíč v rámci slovníku prostředků definovaného elementem, který nastaví vlastnost.

  2. Proces vyhledávání pak prochází logický strom směrem nahoru k nadřazeného prvku a jeho slovníku prostředků. Tento proces pokračuje, dokud nebude dosaženo kořenového prvku.

  3. Zkontrolují se prostředky aplikace. Prostředky aplikace jsou prostředky v rámci slovníku prostředků, který je definován objektem Application pro vaši aplikaci WPF.

Statické odkazy na prostředky ze slovníku prostředků musí odkazovat na prostředek, který již byl definován lexicky před odkazem na prostředek. Odkazy na předávání nelze přeložit statickým odkazem na prostředky. Z tohoto důvodu navrhněte strukturu slovníku prostředků tak, aby prostředky byly definovány na začátku nebo blízko začátku každého příslušného slovníku prostředků.

Statické vyhledávání prostředků může rozšířit do motivů nebo systémových prostředků, ale toto vyhledávání je podporováno pouze proto, že zavaděč XAML požadavek deferuje. Odložení je nezbytné, aby se motiv modulu runtime v době, kdy se stránka načte správně, použila pro aplikaci. Statické odkazy na 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čují, protože tyto odkazy se znovu nevyhodnotují, pokud je motiv změněn uživatelem v reálném čase. Dynamické odkazy na prostředky jsou spolehlivější, když požadujete 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 statické odkazy na prostředky, a to z důvodů uvedených výše.

Chování výjimky, pokud se nenajde odkaz na statický prostředek, se liší. Pokud byl prostředek odložen, dojde k výjimce za běhu. Pokud prostředek nebyl odložen, dojde k výjimce v době načtení.

Dynamické prostředky

Dynamické prostředky fungují nejlépe v případech, kdy:

  • Hodnota prostředku, včetně systémových prostředků nebo prostředků, které jsou jinak nastaveny uživatelem, závisí na podmínkách, které nejsou známé, dokud modul runtime. Můžete například vytvořit hodnoty setter, které odkazují na systémové vlastnosti, které jsou vystaveny pomocí SystemColors, SystemFontsnebo SystemParameters. Tyto hodnoty jsou skutečně dynamické, protože nakonec pocházejí z prostředí runtime 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 musí také zaznamenat změnu.

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

  • 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 se může vyžadovat předávací odkaz. Statické odkazy na prostředky nepodporují předávané odkazy, ale dynamické odkazy prostředků je podporují, protože prostředek není potřeba vyhodnotit, dokud modul runtime a nepředávejte odkazy, nejsou proto relevantním konceptem.

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

  • Vytváříte styl, ve kterém hodnoty setter můžou pocházet z jiných hodnot, které jsou ovlivněné motivy nebo jiným uživatelským nastavením.

  • Používáte prostředky na prvky, které se můžou v logickém stromu znovu načíst během životnosti aplikace. Změna nadřazeného objektu také potenciálně změní obor vyhledávání prostředků, takže pokud chcete, aby byl prostředek pro přehodnocený prvek znovu vyhodnocován na základě nového oboru, vždy použijte dynamický odkaz na prostředky.

Dynamické chování vyhledávání prostředků

Chování vyhledávání prostředků pro dynamické odkazy na prostředky paralelně chování vyhledávání ve vašem kódu, pokud voláte FindResource nebo SetResourceReference:

  1. Vyhledávání vyhledá požadovaný klíč v rámci slovníku prostředků definovaného elementem, který nastaví vlastnost:

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

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

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

  5. Systémové prostředky jsou kontrolovány.

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

  • Pokud byl prostředek požadován voláním FindResource a nebyl nalezen, vyvolá se výjimka.

  • Pokud byl prostředek požadován voláním TryFindResource a nebyl nalezen, není vyvolána žádná výjimka a vrácená hodnota je null. Pokud nastavení vlastnosti nepřijme null, je stále možné, že se v závislosti na nastavení jednotlivé vlastnosti vyvolá hlubší výjimka.

  • Pokud byl prostředek požadován dynamickým odkazem na prostředek v XAML a nebyl nalezen, chování závisí na obecném systému vlastností. Obecné chování je, jako kdyby na úrovni, ve které existuje prostředek, nedošlo k žádné operaci nastavení vlastnosti. Pokud se například pokusíte nastavit pozadí jednotlivého prvku tlačítka pomocí prostředku, který nelze vyhodnotit, pak žádné výsledky sady hodnot, ale efektivní hodnota může stále pocházet od ostatních účastníků v systému vlastností a prioritě hodnot. Například hodnota pozadí může stále pocházet z místně definovaného stylu tlačítka nebo ze stylu motivu. U vlastností, které nejsou definovány styly motivu, může efektivní hodnota po neúspěšném vyhodnocení prostředku pocházet z výchozí hodnoty v metadatech vlastnosti.

Omezení

Dynamické odkazy na prostředky mají některá možná omezení. Musí být splněna alespoň jedna z následujících podmínek:

Vzhledem k tomu, že nastavená vlastnost musí být DependencyProperty vlastnost nebo Freezable vlastnost, může se většina změn vlastností rozšířit do uživatelského rozhraní, protože změna vlastnosti (změněná dynamická hodnota 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 se změní a tato vlastnost může ovlivnit rozložení. Ne všechny vlastnosti, které mají rozšíření značek DynamicResource jako jejich hodnotu, jsou však zaručeny, že poskytují aktualizace v reálném čase v uživatelském rozhraní. Tato funkce se může lišit v závislosti na vlastnosti a v závislosti na typu, který vlastnost vlastní, nebo dokonce logické struktuře vaší aplikace.

Styly, objekty DataTemplates a implicitní klíče

I když všechny položky v objektu ResourceDictionary musí mít klíč, neznamená to, ž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 je hodnota klíče svázaná s hodnotou jiné vlastnosti. Tento typ klíče se označuje jako implicitní klíč a x:Key atribut je explicitní klíč. Implicitní klíč můžete přepsat zadáním explicitního klíče.

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

Styly ovládacích prvků lze vytvořit pomocí implicitního klíče i odkazovat na ho. Styly motivu, které definují výchozí vzhled ovládacího prvku, závisí na tomto implicitní klíči. Z hlediska žádosti o něj implicitní klíč je Type samotný ovládací prvek. Z hlediska definování prostředků je TargetType implicitní klíč stylem. Pokud například vytváříte motivy pro vlastní ovládací prvky nebo vytváříte styly, které pracují s existujícími styly motivu, nemusíte pro to Stylezadávat direktivux:Key . A pokud chcete použít styly motivů, nemusíte vůbec zadávat žádný styl. Například následující definice stylu funguje, i když Style se zdá, že 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>

Tento styl má skutečně klíč: implicitní klíč: System.Windows.Controls.Button typ. V kódu můžete zadat TargetType přímo jako název typu (nebo můžete k vrácení znaku Typepoužít {x:Type...}).

Prostřednictvím výchozích mechanismů stylu motivu používaných WPF se tento styl použije jako styl Button modulu runtime na stránce, i když Button se sám nepokouší určit jeho Style vlastnost nebo konkrétní odkaz na prostředek stylu. Váš styl definovaný na stránce se nachází dříve ve vyhledávací sekvenci než styl slovníku motivu pomocí stejného klíče, který má styl slovníku motivu. Stačí zadat <Button>Hello</Button> libovolné místo na stránce a styl, se TargetTypeButton kterým jste definovali, se použije u tohoto tlačítka. Pokud chcete, můžete styl i nadále explicitně zadávat se stejnou hodnotou typu, jako TargetType je srozumitelnost v kódu, ale to je volitelné.

Implicitní klávesy pro styly se u ovládacího prvku nevztahují, pokud OverridesDefaultStyle je true. (Všimněte si také, že OverridesDefaultStyle je možné nastavit jako součást nativního chování pro třídu ovládacího prvku, nikoli explicitně u instance ovládacího prvku.) Aby bylo možné podporovat implicitní klíče pro scénáře odvozené třídy, musí ovládací prvek přepsat DefaultStyleKey (všechny existující ovládací prvky poskytované jako součást WPF zahrnují toto 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 prvků stylovatelných.

DataTemplate má také implicitní klíč. Implicitní klíč pro hodnotu DataTemplateDataType vlastnosti. DataType lze také zadat jako název typu, nikoli explicitně použít { x:Type...}. Podrobnosti najdete v tématu Přehled šablon dat.

Viz také