Sdílet prostřednictvím


Přehled prostředků XAML

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 obecně přidávají do aplikace, jako je obsah, data nebo vložené soubory.

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.

<Page Name="root"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
  <Page.Resources>
    <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
    <Style TargetType="Border" x:Key="PageBackground">
      <Setter Property="Background" Value="Blue"/>
    </Style>
    <Style TargetType="TextBlock" x:Key="TitleText">
      <Setter Property="Background" Value="Blue"/>
      <Setter Property="DockPanel.Dock" Value="Top"/>
      <Setter Property="FontSize" Value="18"/>
      <Setter Property="Foreground" Value="#4E87D4"/>
      <Setter Property="FontFamily" Value="Trebuchet MS"/>
      <Setter Property="Margin" Value="0,40,10,10"/>
    </Style>
    <Style TargetType="TextBlock" x:Key="Label">
      <Setter Property="DockPanel.Dock" Value="Right"/>
      <Setter Property="FontSize" Value="8"/>
      <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>
  </Page.Resources>
  <StackPanel>
    <Border Style="{StaticResource PageBackground}">
      <DockPanel>
        <TextBlock Style="{StaticResource TitleText}">Title</TextBlock>
        <TextBlock Style="{StaticResource Label}">Label</TextBlock>
        <TextBlock DockPanel.Dock="Top" HorizontalAlignment="Left" FontSize="36" Foreground="{StaticResource MyBrush}" Text="Text" Margin="20" />
        <Button DockPanel.Dock="Top" HorizontalAlignment="Left" Height="30" Background="{StaticResource MyBrush}" Margin="40">Button</Button>
        <Ellipse DockPanel.Dock="Top" HorizontalAlignment="Left" Width="100" Height="100" Fill="{StaticResource MyBrush}" Margin="40" />
      </DockPanel>
    </Border>
  </StackPanel>
</Page>


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 Page 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 to není; jeho kolekce prostředků je prázdná), vyhledávání dále zkontroluje nadřazený prvek Button, který je Page. Pokud definujete prostředek v kořenovém Page prvku, budou k němu mít přístup všechny prvky v logickém Page stromu. 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: FillBackgroundButtona a .Rectangle

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 a poskytne 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ý bude zkompilován do knihovny DLL a zabalený jako součást aplikace nebo sdílený 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 chcete použít chování statického odkazu na prostředky, aby vyhledávání bylo předvídatelné a samostatně obsažené v motivu. S dynamickým odkazem na prostředky se dokonce i odkaz v rámci motivu ponechá nehodnocený, dokud neběží za běhu. a existuje šance, že při použití motivu některé místní prvky předefinují klíč, na který se motiv pokouší odkazovat, a místní prvek bude před motivem samotný 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 vyhodnocovat, dokud modul runtime a nepřeposílejte 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ředky 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, protože jejich hodnota je zaručena poskytovat aktualizace v reálném čase v uživatelském rozhraní. Tato funkce se může lišit v závislosti na vlastnosti a také v závislosti na typu, který vlastnost vlastní, nebo dokonce v 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íč, zatímco 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 najdete v části o stylech a šablonách.

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. Proto pokud 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 direktivu x: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">
    <Setter.Value>
      <LinearGradientBrush>
        <GradientStop Offset="0.0" Color="AliceBlue"/>
        <GradientStop Offset="1.0" Color="Salmon"/>           
      </LinearGradientBrush>
    </Setter.Value>
  </Setter>  
  <Setter Property="FontSize" Value="18"/>
</Style>

Tento styl skutečně obsahuje klíč: implicitní klíč typeof(System.Windows.Controls.Button). 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é