Přehled XAML (WPF .NET)

Tento článek popisuje funkce jazyka XAML a ukazuje, jak se dá použít k zápisu aplikací WPF (Windows Presentation Foundation). Konkrétně tento článek popisuje implementaci XAML ve WPF. Jazyk XAML samotný představuje větší jazykový koncept než WPF.

Důležité

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

Co je XAML

XAML je deklarativní jazyk využívající značky. Jak je aplikováno na programovací model .NET, XAML zjednodušuje vytváření uživatelského rozhraní pro aplikaci .NET. Deklarativními značkami XAML můžete vytvářet viditelné prvky uživatelského rozhraní a pak definici uživatelského rozhraní oddělit od logiky aplikace pomocí souborů kódu na pozadí, které se se značkami propojují prostřednictvím definic částečných tříd. XAML přímo reprezentuje vytváření instancí objektů v konkrétní sadě pomocných typů definovaných v sestaveních. Tím se liší od většiny jiných jazyků využívajících značky, které jsou obvykle interpretovanými jazyky bez takovéto přímé vazby na systém pomocných typů. XAML umožňuje pracovní postup, kde samostatné týmy můžou pracovat na uživatelském rozhraní a logice aplikace, a třeba při tom můžou využívat i zcela různé nástroje.

Když se soubory XAML reprezentují jako text, jsou to soubory XML, které mívají příponu .xaml. Dají se kódovat libovolným kódováním XML, ale běžně se kódují jako UTF-8.

Následující příklad znázorňuje, jak by se dalo v rámci uživatelského rozhraní vytvořit tlačítko. Cílem tohoto příkladu je předvést, jak XAML reprezentuje běžné metafory programování uživatelských rozhraní (není to úplná ukázka).

<StackPanel>
    <Button Content="Click Me"/>
</StackPanel>

Syntaxe XAML ve stručnosti

Následující části vysvětlují základní formy syntaxe XAML a nabízejí krátkou ukázku značek. Účelem těchto částí není nabízet úplné informace o každé formě syntaxe, třeba jak jsou reprezentovány v systému pomocných typů. Další informace o specifikách syntaxe XAML najdete v části Podrobná syntaxe XAML.

Pokud už jazyk XML znáte, budete většinu informací v následujících částech považovat za úplný základ. To je důsledkem jednoho ze základních principů návrhu jazyka XAML. Jazyk XAML definuje své vlastní koncepty, ale tyto koncepty fungují v souladu s jazykem XML a formou značek.

Elementy objektů XAML

Element objektu obvykle deklaruje instanci nějakého typu. Tento typ se definuje v sestaveních, na která se odkazuje technologie, která jako jazyk používá XAML.

Syntaxe elementů objektů vždy začíná levou lomenou závorkou (<). Následuje název typu, kde chcete vytvořit instanci. (Název může obsahovat předponu, což je koncept, který vysvětlíme později.) Pak můžete volitelně v elementu objektu deklarovat atributy. Když budete chtít značku elementu objektu dokončit, ukončete jej pravou lomenou závorkou (>). Druhou možností je použít automaticky ukončovaný tvar, který nemá žádný obsah. Stačí značku zakončit lomítkem a hned za ním pravou lomenou závorkou (/>). Příklad najdete v už uvedeném fragmentu značek.

<StackPanel>
    <Button Content="Click Me"/>
</StackPanel>

Určují se v něm dva elementy objektů: <StackPanel> (s obsahem a následnou koncovou značkou) a <Button .../> (automaticky ukončovaný tvar s několika atributy). Oba elementy objektů StackPanel a Button se mapují na název třídy definované ve WPF a jsou součástí sestavení WPF. Když zadáte značku elementu objektu, vytvoříte pokyn, kterým se při zpracování XML vytvoří nová instance příslušného typu. Každá instance se vytváří zavoláním bezparametrového konstruktoru příslušného typu při parsování a načítání XAML.

Syntaxe atributů (vlastnosti)

Vlastnosti objektu se často dají vyjádřit jako atributy elementu objektu. Syntaxe atributu určuje název nastavované vlastnosti objektu, za kterou následuje operátor přiřazení (=). Hodnota atributu se vždy zadává jako řetězec uzavřený do uvozovek.

Syntaxe atributu je nejefektivnější syntaxe nastavování vlastností, která je pro vývojáře znalé jazyků využívajících značek zároveň nejintuitivnější. Například následující značky vytvářejí tlačítko, která má modré pozadí a červený text Content.

<Button Background="Blue" Foreground="Red" Content="This is a button"/>

Syntaxe elementů vlastností

Pro některé vlastnosti elementu objektů není možné syntaxi atributů použít, protože objekt nebo informace potřebné k nastavení hodnoty vlastnosti není možné vhodným způsobem vyjádřit s ohledem na omezení uvozovek a řetězců v syntaxi atributů. V takových případech je možné použít jinou syntaxi, které se říká syntaxe elementů vlastností.

Syntaxe pro počáteční značku elementu vlastností je <TypeName.PropertyName>. Obecně platí, že obsah této značky je element objektu typu, který daná vlastnost přijímá jako hodnotu. Jakmile se zadá obsah, je zapotřebí element vlastnosti ukončit koncovou značkou. Syntaxe koncové značky je </TypeName.PropertyName>.

Pokud je možné využít syntaxi atributu, je to obvykle pohodlnější a umožňuje to stručnější zápis značek, ale obvykle je to jen otázka stylu, nikoli technických omezení. Následující příklad ukazuje stejné vlastnosti nastavené v předchozí ukázce syntaxe atributů, ale tentokrát zapsané syntaxí elementu vlastností pro všechny vlastnosti objektu Button.

<Button>
    <Button.Background>
        <SolidColorBrush Color="Blue"/>
    </Button.Background>
    <Button.Foreground>
        <SolidColorBrush Color="Red"/>
    </Button.Foreground>
    <Button.Content>
        This is a button
    </Button.Content>
</Button>

Syntaxe kolekce

Jazyk XAML obsahuje určité optimalizace, které vytvářejí snadněji čitelné značky. Jednou z takových optimalizací je to, že pokud určitá vlastnost přijímá typ kolekce, položky deklarované ve značkách jako podřízené elementy v hodnotě dané vlastnosti se stanou součástí této kolekce. V takovém případě je kolekce elementů podřízených objektů hodnotou, která se nastavuje vlastnosti kolekce.

Následující příklad ukazuje syntaxi kolekce pro nastavení hodnot vlastnosti GradientStops.

<LinearGradientBrush>
    <LinearGradientBrush.GradientStops>
        <!-- no explicit new GradientStopCollection, parser knows how to find or create -->
        <GradientStop Offset="0.0" Color="Red" />
        <GradientStop Offset="1.0" Color="Blue" />
    </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

Vlastnosti obsahu XAML

Jazyk XAML obsahuje funkci, která umožňuje, aby třída označila jednu ze svých vlastností jako vlastnost obsahu XAML. Podřízené prvky tohoto elementu objektu se používají k nastavení hodnoty této vlastnosti obsahu. Jinými slovy je možné při nastavování vlastnosti ve značkách XAML vynechat element této vlastnosti a vytvořit tak zřetelnější metaforu nadřazeného a podřízeného elementu. To je pro vlastnost obsahu unikátní.

Například Border určuje vlastnost obsahuChild. Následující dva elementy Border se zpracovávají totožným způsobem. První využívá syntaxi vlastnosti obsahu a vynechává element vlastnosti Border.Child. Druhý ukazuje Border.Child explicitně.

<Border>
    <TextBox Width="300"/>
</Border>
<!--explicit equivalent-->
<Border>
    <Border.Child>
        <TextBox Width="300"/>
    </Border.Child>
</Border>

Pravidlem jazyka XAML je, že hodnota vlastnosti obsahu XAML musí být dána celá buď před jakýmkoli jiným elementem vlastnosti v daném elementu objektu, nebo za ním. Například následující značky není možné zkompilovat.

<Button>I am a
  <Button.Background>Blue</Button.Background>
  blue button</Button>

Další informace o specifikách syntaxe XAML najdete v části Podrobná syntaxe XAML.

Textový obsah

Některé elementy XAML dokáží přímo zpracovat text jako svůj obsah. Aby to bylo možné, musí nastat jeden z těchto případů:

  • Třída musí deklarovat vlastnost obsahu a tato vlastnost obsahu musí mít typ přiřaditelný řetězci (typ by mohl být Object). Například jakékoli ContentControl používá jako svou vlastnost obsahu Content a její typ Object, což podporuje následující využití v ContentControl, třeba Button: <Button>Hello</Button>.

  • Typ musí deklarovat převaděč typů. V takovém případě se textový obsah používá jako inicializační text pro daný převaděč. Například <Brush>Blue</Brush> převádí hodnotu obsahu Blue na štětec. Tento případ je v praxi méně častý.

  • Typ musí být známý primitivní typ jazyka XAML.

Kombinace vlastností obsahu a syntaxe kolekce

Podívejte se na tento příklad.

<StackPanel>
    <Button>First Button</Button>
    <Button>Second Button</Button>
</StackPanel>

Každé Button je tady podřízeným elementem StackPanel. Jsou to jednoduchý a intuitivní zápis, který vynechává dvě značky ze dvou různých důvodů:

  • Vynechaný element vlastnosti Omitted StackPanel.Children:StackPanel se odvozuje z Panel. Panel definuje Panel.Children jako svou vlastnost obsahu XAML.

  • Vynechaný element objektu UIElementCollection: Vlastnost Panel.Children přijímá typ UIElementCollection, který implementuje IList. Značka elementu kolekce se dá vynechat v souladu s pravidly XAML pro zpracovávání kolekcí, jako je IList. (V takovém případě není možné ve skutečnosti vytvořit instanci UIElementCollection, protože nezpřístupňuje bezparametrový konstruktor. Proto je element objektu UIElementCollection zakomentovaný.)

<StackPanel>
    <StackPanel.Children>
        <!--<UIElementCollection>-->
        <Button>First Button</Button>
        <Button>Second Button</Button>
        <!--</UIElementCollection>-->
    </StackPanel.Children>
</StackPanel>

Syntaxe atributu (události)

Syntaxe atributu se dá využít i pro členy, které nejsou vlastnostmi, ale událostmi. V takovém případě je názvem atributu název události. V implementaci událostí pro XAML ve WPF je hodnotou atributu název obslužné rutiny, která implementuje delegáta události. Například následující značky přiřazují obslužnou rutinu pro událost Click do Button vytvořeného značkami:

<Button Click="Button_Click" >Click Me!</Button>

Události a XAML ve WPF nabízejí více, než ukazuje tento příklad syntaxe atributu. Mohlo by vás zajímat například to, co představuje a jak je definováno ClickHandler, na které se tady odkazujeme. To bude vysvětleno v nadcházející části tohoto článku o událostech a kódu XAML na pozadí.

Velká a malá písmena a mezery v XAML

Obecně vzato jazyk XAML rozlišuje velká a malá písmena. Pro účely překladu pomocných typů rozlišuje XAML ve WPF velká a malá písmena podle stejných pravidel jako modul CLR (Common Language Runtime). Elementy objektů, elementy vlastností a názvy atributů se musí zadávat s ohledem na velká a malá písmena v názvu příslušného typu v sestavení nebo členu určitého typu. Klíčová slova a primitivní typy jazyka XAML velká a malá písmena rozlišují také. Hodnoty je však nerozlišují vždy. Rozlišování velkých a malých písmen v hodnotách bude záviset na chování převaděče typů přidruženého k vlastnosti, která danou hodnotu přijímá, nebo na typu hodnoty vlastnosti. Například vlastnosti, které přijímají typ Boolean, můžou přijímat buď true, nebo True jako ekvivalentní hodnoty, ale jen díky tomu, že už nativní převod typů řetězce na Boolean v parseru XAML ve WPF připouští tyto ekvivalenty.

Procesory a serializátory XAML ve WPF budou ignorovat veškeré nevýznamné prázdné znaky a normalizovat všechny významné. To je konzistentní s doporučeními k výchozímu chování prázdných znaků ve specifikaci XAML. Toto chování má význam jen v případě, že ve vlastnostech obsahu XAML zadáváte řetězce. Řečeno co nejjednodušeji, XAML převádí znaky mezer, konců řádků a tabulátorů na mezery a zachovává jednu mezeru, kterou případně najde na kterékoli straně nepřerušovaného řetězce. Úplné vysvětlení zpracování prázdných znaků v XAML přesahuje rámec tohoto článku. Další informace najdete v části o zpracování prázdných znaků v jazyce XAML.

Rozšíření značek

Rozšíření značek jsou koncept jazyka XAML. Když se pomocí nich zadá hodnota syntaxe atributu, složené závorky ({ a }) označí využití rozšíření značek. Toto použití dává při zpracování XAML pokyn odchýlit se od obecného zpracování hodnot atributů a považovat je buď za řetězcový literál, nebo převoditelnou řetězcovou hodnotu.

Nejběžnější rozšíření značek, která se používají při programování aplikací WPF, jsou Binding, které se používá pro výrazy datových vazeb, a odkazy na prostředky StaticResource a DynamicResource. Když budete používat rozšíření značek, budete moct pomocí syntaxe atributu zadávat hodnoty pro vlastnosti i v případě, že daná vlastnost v obecné rovině nepodporuje syntaxi atributu. Rozšíření značek často používají přechodné typy výrazů, aby zprostředkovaly funkce jako pozdržení hodnot nebo reference na jiné objekty existující pouze za běhu.

Například následující značky nastavují hodnotu vlastnosti Style pomocí syntaxe atributu. Vlastnost Style přijímá instanci třídy Style, která se standardně nedá vytvořit řetězcem syntaxe atributu. Ale v tomto případě se atribut odkazuje na konkrétní rozšíření značek StaticResource. Jakmile se toto rozšíření značek zpracuje, vrátí se odkaz na styl, pro který se dříve vytvořila instance ve tvaru prostředku s klíčem ve slovníku prostředků.

<Window x:Class="index.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="100" Width="300">
    <Window.Resources>
        <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
        <Style TargetType="Border" x:Key="PageBackground">
            <Setter Property="BorderBrush" Value="Blue"/>
            <Setter Property="BorderThickness" Value="5" />
        </Style>
    </Window.Resources>
    <Border Style="{StaticResource PageBackground}">
        <StackPanel>
            <TextBlock Text="Hello" />
        </StackPanel>
    </Border>
</Window>

Referenční seznam všech rozšíření značek pro XAML implementovaných speciálně ve WPF najdete v části o rozšíření XAML ve WPF. Referenční informace o rozšířeních značek, které jsou definovány System.Xaml a jsou široce dostupné pro implementace .NET XAML, naleznete v tématu Jazykové funkce oboru názvů XAML (x:). Další informace o konceptech rozšíření značek najdete v části o rozšířeních značek a XAML ve WPF.

Převaděče typů

V části Syntaxe XAML ve stručnosti bylo uvedeno, že hodnotu atributu musí být možné nastavit řetězcem. Základní nativní zpracování převodů řetězců na jiné typy objektů nebo primitivní hodnoty se zakládá na samotném typu String spolu s nativním zpracováním určitých typů, jako jsou DateTime nebo Uri. Ale mnoho typů WPF nebo členů těchto typů rozšiřují základní chování při zpracovávání řetězcových atributů tak, že jako řetězce a atributy je možné poskytovat instance složitějších typů objektů.

Struktura Thickness je jedním takovým typem, který má pro využití v XAML povolený převod typu. Thickness označuje rozměry ve vnořeném obdélníku a používá se jako hodnota pro vlastnosti, jako je Margin. Když se do Thickness umístí převaděč typů, všechny vlastnosti, které používají Thickness, bude snazší zadávat v XAML, protože je bude možné zadávat jako atributy. Následující příklad používá převod typu a syntaxi atributu, kterými poskytuje hodnotu pro Margin.

<Button Margin="10,20,10,30" Content="Click me"/>

Předchozí příklad syntaxe atributu je ekvivalentní k následujícímu podrobnějšímu příkladu syntaxe, kde se Margin nastavuje prostřednictvím syntaxe elementu vlastnosti obsahující element objektu Thickness. Čtyři hlavní vlastnosti Thickness se nastavují jako atributy v nové instanci:

<Button Content="Click me">
    <Button.Margin>
        <Thickness Left="10" Top="20" Right="10" Bottom="30"/>
    </Button.Margin>
</Button>

Poznámka:

Existuje i určitý počet objektů, kde je převod typů jediný veřejný způsob, jak na daný typ nastavit vlastnost, aniž by se používala podtřída, protože onen typ nemá bezparametrový konstruktor. Příklad: Cursor.

Další informace o převodu typů najdete v části o převaděčích typů a XAML.

Kořenové elementy a obory názvů

Aby byl soubor XAML platný a měl správný formát, musí mít jen jeden kořenový element. V obvyklých scénářích WPF použijete kořenový element, který má v modelu aplikace WPF největší význam (například Window nebo Page pro stránku, ResourceDictionary pro externí slovník nebo Application pro definici aplikace). Následující příklad ukazuje kořenový element typického souboru XAML pro stránku WPF, kde se jako kořenový element používá Page.

<Page x:Class="index.Page1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="Page1">

</Page>

Navíc kořenový element obsahuje atributy xmlns a xmlns:x. Tyto atributy dávají procesoru XAML informaci, které obory názvů XAML obsahují definice pomocných typů, na které se značky budou odkazovat jako na elementy. Konkrétně atribut xmlns určuje výchozí obor názvů XAML. V rámci výchozího oboru názvů XAML se elementy objektů dají ve značkách zadávat bez předpony. Pro většinu scénářů aplikací WPF a pro skoro všechny příklady uvedené v částech WPF v sadě SDK je výchozí obor názvů XAML namapovaný na obor názvů WPF http://schemas.microsoft.com/winfx/2006/xaml/presentation. Atribut xmlns:x označuje další obor názvů XAML, který mapuje obor názvů XAML http://schemas.microsoft.com/winfx/2006/xaml.

Toto využití xmlns k definici rozsahu pro použití a mapování rozsahu názvů je konzistentní se specifikací XML 1.0. Rozsahy názvů XAML se liší od rozsahů názvů XML jen v tom, že rozsah názvů XAML sám od sebe říká něco o tom, jak elementy daného rozsahu názvů používají pomocné typy při překladu typů a parsování XAML.

Atributy xmlns jsou nezbytně důležité jen v kořenovém elementu jednotlivých souborů XAML. Definice xmlns se budou vztahovat na všechny elementy podřízené kořenovému elementu (toto chování je opět konzistentní se specifikací XML 1.0 pro xmlns). Kromě toho se v ostatních elementech pod kořenem povolují i atributy xmlns, které se vztahují na všechny elementy podřízené definujícímu elementu. Časté definice a změny definic oborů názvů XAML však můžou vést ke stylu značek XAML, který se bude obtížně číst.

Implementace procesoru XAML ve WPF obsahuje infrastrukturu, která má informace o základních sestaveních WPF. O těch je známo, že obsahují typy, které podporují mapování WPF na výchozí obor názvů XAML. To je umožněno konfigurací, která je součástí souboru sestavení projektu a sestavovacích a projektových systémů WPF. Proto je deklarace výchozího oboru názvů XAML jako výchozího xmlns to jediné, co je zapotřebí, aby bylo možné se odkazovat na elementy XAML pocházející ze sestavení WPF.

Předpona x:

V předchozím příkladu kořenového elementu se použila předpona x:, pomocí které se namapoval obor názvů XAML http://schemas.microsoft.com/winfx/2006/xaml. To je vyhrazený obor názvů XAML, který podporuje jazykové konstrukce XAML. Tato předpona x: se používá pro mapování tohoto oboru názvů XAML v šablonách pro projekty, v příkladech a v dokumentaci v této sadě SDK. Obor názvů XAML pro jazyk XAML obsahuje několik programových konstrukcí, které budete ve svém kódu XAML často používat. Následuje seznam nejběžnějších programových konstrukcí předpony x:, které budete používat:

  • x:Key: Nastavuje jedinečný klíč pro každý prostředek v ResourceDictionary (nebo obdobných konceptech slovníků v jiných architekturách). x:Key bude pravděpodobně představovat 90 procent všech použití x:, se kterými se setkáte v typických značkách aplikace WPF.

  • x:Class: Určuje obor názvů modulu CLR (Common Language Runtime) a název třídy, která stránce XAML poskytuje kód na pozadí. Podle modelu programování WPF musíte takovou třídu mít, aby podporovala kód na pozadí, proto téměř vždy uvidíte x: namapované, i když se nevyužijí žádné prostředky.

  • x:Name: Určuje název objektu za běhu pro instanci, která existuje ve spuštěném kódu po zpracování elementu objektu. Obecně pro x:Name budete často používat ekvivalentní vlastnost definovanou ve WPF. Takové vlastnosti se mapují konkrétně na pomocnou vlastnost modulu CLR (Common Language Runtime), a jsou proto vhodnější pro programování aplikací, ve kterých se často pomocí spuštěného kódu hledají pojmenované elementy z inicializovaného kódu XAML. Nejběžnější takovou vlastností je FrameworkElement.Name. Pokud se v určitém typu nepodporuje ekvivalentní vlastnost Name na úrovni architektury WPF, stále můžete použít x:Name. K tomu dochází v určitých scénářích animací.

  • x:Static: Zajišťuje referenci vracející statickou hodnotu, která jinak není vlastností kompatibilní se XAML.

  • x:Type: Vytvoří referenci Type na základě názvu typu. To se používá k určování atributů, které přijímají Type, například Style.TargetType, i když daná vlastnost má často takový nativní převod řetězců na Type, že používat rozšíření značek x:Type není nezbytně nutné.

V předponě x: nebo oboru názvů XAML se nacházejí další programové konstrukce, které nejsou tak běžné. Podrobnosti najdete v části o jazykových funkcích oboru názvů jazyka XAML (x:).

Vlastní předpony a vlastní typy

Pro svá vlastní sestavení nebo pro sestavení mimo jádro WPF PresentationCore, PresentationFramework a WindowsBase můžete zadat sestavení v rámci vlastního mapování xmlns. Pak se budete moct z daného sestavení v XAML odkazovat na typy za podmínky, že daný typ má správnou implementaci a podporuje využití XAML, které chcete zavést.

Následuje základní ukázka, jak fungují vlastní předpony ve značkách XAML. Ve značce kořenového elementu je definovaná předpona custom, která je namapovaná na konkrétní sestavení zabalené a dostupné spolu s aplikací. Toto sestavení obsahuje typ NumericUpDown, který má implementovanou podporu obecného využití XAML i používání dědičnosti tříd. Ta umožňuje její vkládání na tento konkrétní bod v modelu obsahu XAML ve WPF. Instance tohoto ovládacího prvku NumericUpDown je deklarovaná jako element objektu pomocí předpony, aby parser XAML měl informace o tom, který obor názvů XAML obsahuje daný typ a kde se nachází pomocné sestavení obsahující jeho definici.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:custom="clr-namespace:NumericUpDownCustomControl;assembly=CustomLibrary"
    >
  <StackPanel Name="LayoutRoot">
    <custom:NumericUpDown Name="numericCtrl1" Width="100" Height="60"/>
...
  </StackPanel>
</Page>

Další informace o vlastních typech v XAML najdete v části o XAML a vlastních třídách pro WPF.

Další informace o tom, jak spolu souvisí obory názvů XML a obory názvů kódů v sestaveních, najdete v části o mapování oborů názvů XAML a oborů názvů pro XAML ve WPF.

Události a kód XAML na pozadí

Většina aplikací WPF sestává ze značek XAML a kódu na pozadí. V jednom projektu je kód XAML zapsaný v souboru .xaml a pomocí jazyka CLR, jako je Microsoft Visual Basic nebo C#, se zapisuje soubor kódu na pozadí. Když se značky v souboru XAML kompilují jako součást programového a aplikačního modelu WPF, umístění souboru kódu XAML na pozadí pro soubor XAML se zjišťuje určováním oboru názvů a třídy jako atributu x:Class kořenového elementu v kódu XAML.

V dosud uvedených příkladech bylo několik tlačítek, ale žádné z nich ještě nemělo přidružené žádné logické chování. Primárním mechanismem na úrovni aplikace, jak elementu objektu přidat chování, je použít stávající událost třídy elementu a pro tuto událost napsat konkrétní obslužnou rutinu, která se volá, když se za běhu vyvolá událost. Název události a název použité obslužné rutiny se zadávají ve značkách, zatímco kód, který obslužnou rutinu implementuje, se definuje v kódu na pozadí.

<Page x:Class="ExampleNamespace.ExamplePage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel>
        <Button Click="Button_Click">Click me</Button>
    </StackPanel>
</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace ExampleNamespace;

public partial class ExamplePage : Page
{
    public ExamplePage() =>
        InitializeComponent();

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var buttonControl = (Button)e.Source;
        buttonControl.Foreground = Brushes.Red;
    }
}
Class ExamplePage
    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
        Dim buttonControl = DirectCast(e.Source, Button)
        buttonControl.Foreground = Brushes.Red
    End Sub
End Class

Všimněte si, že soubor kódu používá obor názvů CLR (obor názvů ExampleNamespace není viditelný v jazyce Visual Basic) a deklaruje ExamplePage jako částečnou třídu v rámci tohoto oboru názvů. To je v souladu s hodnotou ExampleNamespace atributu x:Class.ExamplePage poskytnuté v kořenu značek. Kompilátor značek WPF vytvoří částečnou třídu pro jakýkoli zkompilovaný soubor XAML odvozením třídy z typu kořenového elementu. Když poskytnete kód na pozadí, který stejnou částečnou třídu definuje také, výsledný kód se zkombinuje ve stejném oboru názvů a třídě kompilované aplikace.

Důležité

V jazyce Visual Basic se kořenový obor názvů implikuje jak pro XAML, tak pro kód. Jsou viditelné pouze vnořené obory názvů. Tento článek ukazuje XAML projektu jazyka C#.

Další informace o požadavcích na programování kódu na pozadí ve WPF najdete v části o kódu na pozadí, obslužné rutině události a požadavků na částečné třídy ve WPF.

Pokud nechcete vytvářet samostatný soubor kódu na pozadí, můžete kód vložit i do souboru XAML. Vložený kód je však méně všestranná technika, která má významná omezení. Další informace najdete v části o kódu na pozadí a XAML ve WPF.

Směrované události

Konkrétní funkce událostí, která je pro WPF zásadní, je směrovaná událost. Směrované události umožňují elementu zpracovat událost vyvolanou jiným elementem za předpokladu, že jsou tyto elementy propojené prostřednictvím stromového vztahu. Když budete určovat zpracování události pomocí atributu XAML, je možné směrované události naslouchat a zpracovávat ji v jakémkoli elementu, včetně těch, které danou konkrétní událost neuvádějí v tabulce členů třídy. Toho se dosahuje kvalifikací atributu názvu události názvem třídy, která jej vlastní. Například nadřazený objekt StackPanel v aktuálním příkladu StackPanel / Button by mohl zaregistrovat obslužnou rutinu pro událost Click tlačítka podřízeného elementu tak, že se v elementu objektu StackPanel zadá atribut Button.Click. Hodnotou atributu by byl název obslužné rutiny. Další informace najdete v přehledu směrovaných událostí.

Pojmenované elementy

Standardně instance objektu vytvořená v grafu objektů zpracováním elementu objektu XAML nemá jedinečný identifikátor nebo odkaz na objekt. A naopak, pokud zavoláte v kódu konstruktor, téměř vždy pomocí výsledku konstruktoru nastavíte proměnnou na vytvořenou instanci, abyste se na ni mohli později v kódu odkazovat. Aby XAML poskytovalo standardizovaný přístup k objektům vytvořeným prostřednictvím definice ve značkách, definuje atribut x:Name. Hodnotu atributu x:Name můžete nastavit v jakémkoli elementu objektu. V kódu na pozadí je zvolený identifikátor ekvivalentní proměnné instance, která se odkazuje na vytvořenou instanci. Ve všech ohledech pojmenované elementy fungují, jako by to byly instance objektů (název se odkazuje na danou instanci), a váš kód na pozadí se může na pojmenované elementy odkazovat, aby za běhu aplikace zpracovávaly její interakce. Toto propojení mezi instancemi a proměnnými zajišťuje kompilátor značek XAML ve WPF. Konkrétněji se pro něj využívají funkce a vzory, jako je InitializeComponent. Tomu se ale v tomto článku podrobněji věnovat nebudeme.

Elementy XAML na úrovni architektury WPF dědí vlastnost Name, která je ekvivalentem atributu x:Name definovaného v XAML. I některé jiné třídy poskytují ekvivalenty na úrovni vlastností pro x:Name, které je také obvykle definované jako vlastnost Name. Obecně řečeno, pokud se vám nedaří najít vlastnost Name v tabulce členů pro zvolený element nebo typ, použijte místo ní x:Name. Hodnoty x:Name poskytnou elementu XAML identifikátor, který bude možné použít za běhu. Použijí k tomu buď konkrétní subsystémy, nebo pomocné metody, jako je FindName.

Následující příklad nastaví Name v elementu StackPanel. Pak se obslužná rutina v Button v daném StackPanel odkazuje na StackPanel prostřednictvím reference na instanci buttonContainer nastavené v Name.

<StackPanel Name="buttonContainer">
    <Button Click="RemoveThis_Click">Click to remove this button</Button>
</StackPanel>
private void RemoveThis_Click(object sender, RoutedEventArgs e)
{
    var element = (FrameworkElement)e.Source;
    
    if (buttonContainer.Children.Contains(element))
        buttonContainer.Children.Remove(element);
}
Private Sub RemoveThis_Click(sender As Object, e As RoutedEventArgs)
    Dim element = DirectCast(e.Source, FrameworkElement)

    If buttonContainer.Children.Contains(element) Then
        buttonContainer.Children.Remove(element)
    End If
End Sub

Stejně jako proměnná se název XAML pro instanci řídí konceptem rozsahu, aby bylo možné vynutit předvídatelnou jedinečnost názvů v určitém rozsahu. Primární značka, která definuje stránku, označuje jeden jedinečný rozsah názvů XAML. Hranicí rozsahu názvů XAML je kořenový element dané stránky. Za běhu však se stránkou můžou pracovat jiné zdroje značek, například styly nebo šablony v nich, a takové zdroje značek mají obvykle své vlastní rozsahy názvů XAML, které nemusí být nutně propojené s rozsahem názvu XAML stránky. Další informace o x:Name a rozsazích názvů XAML najdete v částech o Name, direktivě x:Name nebo rozsazích názvů XAML ve WPF.

Přidružené vlastnosti a přidružené události

XAML určuje jazykovou funkci, která umožňuje zadání určitých vlastností nebo událostí u libovolného elementu, i když vlastnost nebo událost v definicích typu pro prvek, který je nastavený, neexistuje. Verze vlastností této funkce se nazývá přidružená vlastnost, verze událostí pak přidružená událost. Přidružené vlastnosti a přidružené události si můžete představit jako globální členy, které je možné nastavit v jakémkoli elementu XAML nebo instanci objektu. Element, třída nebo nějaká větší infrastruktura však musí pro přidružené hodnoty podporovat pomocné úložiště vlastností.

Přidružené vlastnosti v XAML se obvykle používají pomocí syntaxe atributu. V syntaxi atributu zadáváte přidruženou vlastnost ve tvaru ownerType.propertyName.

Na první pohled tento zápis připomíná použití elementu vlastnosti, ale v tomto případě zadávané ownerType je vždy jiného typu než element objektu, ve kterém se přidružená vlastnost nastavuje. ownerType je typ, který poskytuje přístupové metody požadované procesorem XAML, aby mohl získávat nebo nastavovat hodnotu přidružené vlastnosti.

Nejčastěji přidružené vlastnosti slouží k tomu, aby podřízené prvky mohly oznamovat hodnotu vlastnosti nadřazeného elementu.

Následující příklad znázorňuje přidruženou vlastnost DockPanel.Dock. Třída DockPanel definuje přístupové objekty pro DockPanel.Dock a vlastní přidruženou vlastnost. Třída DockPanel obsahuje i logiku, která iteruje svými podřízenými elementy a v každém z nich kontroluje, jestli nemá nastavenou hodnotu DockPanel.Dock. Pokud se hodnota najde, použije se při nastavování rozložení k umístění podřízených elementů. Využití přidružené vlastnosti DockPanel.Dock a této funkce umísťování je hlavním účelem třídy DockPanel.

<DockPanel>
    <Button DockPanel.Dock="Left" Width="100" Height="20">I am on the left</Button>
    <Button DockPanel.Dock="Right" Width="100" Height="20">I am on the right</Button>
</DockPanel>

Ve WPF je většina přidružených vlastností implementovaná i jako vlastnosti závislostí. Další informace najdete v přehledu přidružených vlastností.

Přidružené události používají podobný tvar ownerType.eventName syntaxe atributu. Stejně jako u nepřidružené události hodnota atributu přidružené události v XAML určuje název metody obslužné rutiny, která se volá, když se v elementu zpracovává událost. Přidružené události se v XAML ve WPF nepoužívají tak často. Další informace najdete v přehledu přidružených událostí.

Základní typy

Základní XAML ve WPF a jeho obor názvů XAML jsou kolekce typů, které odpovídají objektům CLR a elementům značek pro XAML. Ne všechny třídy se však dají namapovat na elementy. Abstraktní třídy, třeba ButtonBase, a určité neabstraktní základní třídy se v modelu objektů CLR používají pro dědičnost. Základní třídy, včetně těch abstraktních, jsou při vývoji v XAML stále důležité, protože každý z konkrétních elementů XAML dědí členy z nějaké základní třídy v jeho hierarchii. Často mezi tyto členy patří vlastnosti, které se dají nastavovat jako atributy elementu, nebo události, které se dají zpracovat. FrameworkElement je konkrétní základní třída uživatelského rozhraní WPF na úrovni architektury WPF. Při navrhování uživatelského rozhraní budete používat různé třídy obrazců, panelů, dekorátorů nebo řídicích prvků, které jsou všechny odvozené z FrameworkElement. Související základní třída FrameworkContentElement podporuje elementy orientované na dokumenty, které jsou vhodné pro prezentaci rozložení toku pomocí rozhraní API, která záměrně zrcadlí rozhraní API v FrameworkElement. Kombinace atributů na úrovni elementu a modelu objektů CLR nabízí sadu běžných vlastností, které se dají nastavit v nejkonkrétnějších elementech XAML bez ohledu daný element XAML a jemu příslušný typ.

Zabezpečení

XAML je jazyk využívající značky, který přímo reprezentuje vytváření instancí objektů a jejich spouštění. Proto mají elementy vytvořené v XAML stejné možnosti interakce se systémovými prostředky (například se síťovým přístupem nebo V/V operacemi systému souborů) jako kód aplikace. K tomu má XAML stejný přístup k systémovým prostředkům jako hostující aplikace.

Zabezpečení přístupu kódu (CAS) ve WPF

Na rozdíl od rozhraní .NET Framework WPF nepodporuje CAS. Další informace najdete v části o rozdílech v zabezpečení přístupu ke kódu.

Načtení XAML z kódu

XAML se dá využít k definici celého uživatelského rozhraní, ale někdy bývá vhodné pomocí XAML definovat jen jeho část. Taková funkce může být užitečná pro:

  • umožnění částečného přizpůsobení
  • místní ukládání informací uživatelského rozhraní
  • modelování obchodního objektu

Klíčem k těmto scénářům je třída XamlReader a její metoda Load. Vstupem je soubor XAML a výstupem objekt, který představuje celý strom objektů za běhu vytvořený z daných značek. Pak můžete vložit objekt tak, aby byl vlastností jiného objektu, který v aplikaci už existuje. Dokud se vlastnost nachází v modelu obsahu a má funkce zobrazování, které spouštěcímu modulu oznámí, že se do aplikace přidal nový obsah, můžete dynamickým načítáním v XAML snadno upravovat obsah spuštěné aplikace.

Viz také