Jazyk XAML

3. díl - Jazyk XAML

Tomáš Jecha, MVP, MCSD       02.02.2012       WPF, .NET       20202 zobrazení

Co to vlastně je XAML? Proč je tak důležitý pro Windows Presentation Foundation? Jakým způsobem se zapisuje a co reprezentuje? Proč je tento způsob zápisu mezi vývojáři tak oblíbený? Tento článek je úvod do jazyka XAML.

Co to je XAML a co má společného s WPF?

XAML (vyslovujeme “zaml”) je zkratka pro Extensible Application Markup Language. Je to deklarativní jazyk založený na XML. Je určený primárně k návrhu uživatelského prostředí pro technologie WPF a Silverlight. Často se však můžeme setkat s jeho alternativním způsobem využití, jako je definice konfigurace aplikace nebo popisu procesů (viz technologie Workflow Foundation). Můžeme jej tedy použít na cokoliv chceme a není vázán pouze na WPF, ačkoliv je v této formě asi nejpoužívanější.

Jazyk XAML slouží k usnadnění zápisu. Vše, co lze udělat pomocí něj, tak můžeme zapsat i v jazycích C# nebo Visual Basic .NET. Když to zjednoduším, tak XAMLem říkáme, jaké objekty se mají vytvořit a jaké vlastnosti se jim mají nastavit. Tedy například ve WPF slouží primárně k sestavení objektového stromu elementů uživatelského prostředí. XAML totiž pracuje s objektovým modelem .NET – buď s komponenty, které jsou dodávané s .NET Frameworkem nebo s jakoukoliv podstrčenou knihovnou, na kterou se ze XAML souboru odkážeme pomocí XML namespace.

Zápis jazyka XAML

Než se vrhnu do popisu samotného XAML jazyka, připomenu některé opomíjené základy formátu XML.

XML Namespaces

XML namespacy jsou jedním ze základních principů jazyka XML (není to výmysl XAMLu). Pokud jejich význam neznáte, nebo vám není úplně jasný, jsou vám určeny následující řádky.

Namespacy (jmenné prostory) znáte z programování v jazycích .NET. Zde se využívají k jednoznačnému rozlišení tříd a dalších typů. Pokud by namespacy neexistovaly, musely bychom zajistit, že každá třída má svůj unikátní název v rámci celého projektu. Což by navíc při používání externích knihoven nebylo nikterak snadné – museli bychom zajistit, aby nenastal konflikt ani s typy uvnitř těchto knihoven. A proto rozdělujeme jednotlivé typy do různých jmenných prostorů. K jejich jednoznačné identifikaci pak nepoužijeme pouze jejich jméno, ale zároveň i jejich namespace. A nemusí nás vůbec zajímat, zda náhodou neexistuje v jiném namespacu stejně pojmenovaná třída. A velmi podobně je tomu u jazyka XML.

Namespacy v XML se definují, stejně jako v .NET, textovým názvem. Navíc jim však přiřazujeme zkratku, kterou specifický namespace zastupuje v rámci konkrétního XML souboru. Jak se bude zkratka jmenovat nijak neovlivňuje význam výsledného dokumentu. Důležité je, aby odkazovala na správný namespace a využívali jí správné elementy.

Jak definovat odkaz XML namespace?

Podívejte se na následující zápis:

<x:Window xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml” />

Zde zápisem “x:Window” říkáme, že chceme použít element “Window z namespacu se zkratkou “x”.

Zároveň rovnou na tomto elementu definujeme, že zkratka “x” se odkazuje na namespace:
http://schemas.microsoft.com/winfx/2006/xaml”. Výraz “xmlns” je klíčové slovo jazyka XML a znamená “XML namespace”. Za ním následuje dvojtečka a zkratka, kterou chceme definovat a na konec v uvozovkách plné jméno namespacu.

Takto definovanou zkratku můžete používat jak elementem, nad kterým jste ji definovali a všech vnitřních elementech do libovolné úrovně (pokud její registraci zase nezrušíte nebo nepřepíšete jinou se stejnou zkratkou). Počet registrovaných namespaců není omezen.

Poznámka: Častým postupem je registrace všech potřebných namespaců na kořenovém elementu XML dokumentu, aby byly zkratky dostupné v rámci celého dokumentu.

Poznámka: V příkladu jsem uvedl namespace “http://schemas.microsoft.com/winfx/2006/xaml” (hlavní WPF namespace obsahující základní sadu komponent). XML namespacy totiž musí být ve formátu URI. Slouží ale pouze jako identifikátor, nikoliv webová adresa! Ačkoliv občas firmy volí XML namespacy, které korespondují s webovou adresou, která může obsahovat například XSD schématem definující povolené ementy uvnitř XML namespacu, není to pravidlem. Většinou se nejedná o platnou URL adresu.

Důležitý je fakt, že XML samo o sobě nekontroluje, zda používáme platné namespacy a elementy, které v daném namespacu existují. Fyzicky je namespace jen textová hodnota. O případné validaci musí rozhodnout až aplikace, která bude výsledné XML používat.

Ukázka použití elementů a namespaců

Zvažte toto XML:

<a:Trida1 xmlns:a=”http://sample/namespace1” xmlns:b=”http://sample/namespace2”>
	<b: Trida1 />
</a:Trida1>

Tento příklad ukazuje definici dvou namespaců (“a”, “b”) a jejich použití. Kořenový element je “Trida1 z namespacu “http://sample/namespace1”. Uvnitř tohoto elementu je element, který je pojmenovaný stejně (“Trida1”), je však jiný, protože je odkázán do namespacu “http://sample/namespace2”.

Defaultní XML namespacy

Pokud jste někde pracovali s XML, určitě víte, že se často jeho elementy používají i bez namespaců. Ve skutečnosti má ale svůj namespace každý element. Jen pokud není uvedena jeho zkratka, použije se takzvaný defaultní namespace. Jeho výhoda je, že defaultní nemaspace není nutné registrovat. Možné to však je:

<Trida1 xmlns=”http://sample/namespace1” />

V zápisu se pouze vynechá dvojtečka a přiřazená zkratka. Tím říkáme, že se tento namespace bere jako defaultní a používá se pokaždé, když se u elementů nezadá zkratka namespacu.

Defaultní namespace je možné samozřejmě kombinovat s pojmenovanými namespacy (ty, které mají zkratku). Například:

<Trida1 xmlns=”http://sample/namespace1” xmlns:b=”http://sample/namespace2”>
	<b: Trida1 />
</Trida1>

V tomto příkladu máme kořenový element definovaný v rámci defaultního namespacu a jeden vnořený element v rámci pojmenovaného namespacu “b”.

Syntaxe jazyka XAML

Důvodem, proč jsem se rozepsal o XML namespacech byl ten, že v jazyku XAML hrají velmi významnou roli. Definujeme skrze ně jaké datové typy budeme v zápisu XAML používat. Každý definovaný namespace v XAML souboru odkazu na konkrétní namespace v .NET assembly. Jako jména elementů, které využijí tyto namespacy dosadíme jména datových typů, jenž se v příslušném jmenném prostoru v DLL souboru nacházejí.

Nejlepší bude vše ukázat na jednoduchém příkladu. Zde je kód “Hello World” z předchozího dílu:

<Window x:Class="HelloWorldWpf.MainWindow" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
        <Label FontSize="25"  Content="Hello WPF world!" HorizontalAlignment="Center" VerticalAlignment="Center" /> 
    </Grid> 
</Window> 

Nejprve rozeberu element Window. Ten má sobě řadu atributů. Začnu s atributy definující namespacy – tedy xmlns (defaultní namespace) a xmlns:x (namespace se zkratkou “x”).

Defaultní namespace “http://schemas.microsoft.com/winfx/2006/xaml/presentation” obsahuje základní grafické elementy technologie WPF. Vzhledem k tomu, že použité elementy Window, Grid i Label nemají u sebe namespace uvedený, využívají tento defaultní.

Druhý namespace "http://schemas.microsoft.com/winfx/2006/xaml" je pojmenovaný jako “x” a obsahuje některé obecné doplňující parametry. Z tohoto namespacu je ale využitá pouze jediná vlastnost – x:Class definující třídu, která představuje k tomuto XAMLu funkční kód.

Pokud budete chtít využít vlastní XML namespace odkazující se do některé jiné assembly, jde to udělat velmi snadno. Využijeme toho při psaní vlastních komponent. Identifikátor namespacu zapíšeme v tomto formátu:

xmlns:zkratka="clr-namespace:MojeAssembly.MujNamespace;assembly=MojeAssembly"

O vlastních komponentách budu psát v některém z dalších dílů.

Vše ostatní v ukázkovém XAML kódu je už běžný zápis XML. Vše používá jeden defaultní namespace (tedy namespace “http://schemas.microsoft.com/winfx/2006/xaml/presentation”). Nad elementem Window je definována hodnota některých vlastností:

  • Title – nadpis okna
  • Width – šířka okna
  • Height – výška okna

Tyto vlastnosti jsou shodné s vlastnostmi, které fyzicky existují přímo nad objektem Window.

Uvnitř tohoto objekt Window se nachází objekt Grid. A uvnitř něj dále Label. Ten také přijímá nastavení některých jeho vlastností (FontSize, Content atp.).

Content property

Jak jsem již psal, při vložení atributu k elementu nastavujete vlastnosti daného objektu (například Title="MainWindow"). Třída si ale navíc může zvolit jednu vlastnost, která bude představovat tzv. content property. Fyzicky toto určuje atribut ContentPropertyAttribute umístěný nad celou třídou. Jako parametr předáme jméno vlastnosti, kterou pasujeme na content property. Tím určujeme, že vše co vepíšeme dovnitř elementu nastaví XAML parser právě jako hodnotu takto zvolené vlastnosti.

Příkladem může být objekt Label. Jeho content property je vlastnost Content. Díky tomu jsou tyto dva zápisy identické:

<Label Content="Hello!" />
<Label>Hello!</Label>

Pokud nastavíte tuto vlastnost oběma způsoby, zobrazí se chyba upozorňující, že nelze tutéž vlastnost nastavit dvěma způsoby: “The property 'Content' is set more than once.

<Label Content="Hello!">Hello!</Label>

Řada tříd (dědící z typu Panel) tímto způsobem dovoluje vkládat objekty do sebe. Například vložení dvou textových popisků do StackPanel (skládá komponenty pod sebe podle jejich výšky):

<StackPanel> 
    <Label Content="Text 1" /> 
    <Label Content="Text 2" /> 
</StackPanel>

Tato komponenta StackPanel (stejně jako všechny komponenty dědící z třídy Panel) má jako content property nastavenou vlastnost Children, která je typu UIElementCollection dovolující nést kolekci elementů uživatelského prostředí. Díky tomu lze do ní vložit více jak jeden objekt.

Nastavování vlastností

Může se stát, že budeme chtít nastavit do nějaké vlastnosti objekt, který nepůjde snadno zapsat do atributu. Řešením je využít explicitní přístup do vlastností pomocí elementu který se skládá ze jména třídy, jejíž vlastnost nastavujeme + jméno nastavované vlastnosti (v následujícím příkladu StackPanel.Children). Narozdíl od content property můžeme takto nastavit vlastností více a to i ty, které nejsou jako content property označené.

<StackPanel> 
    <StackPanel.Children> 
        <Label Content="Text 1" /> 
        <Label Content="Text 2" /> 
    </StackPanel.Children> 
</StackPanel>

Jazyk XAML nabízí ještě celou řadu dalších užitečných funkcí jako například Markup Extensions nebo Type Converters. Těm se ale budu věnovat v pozdějších dílech, kdy již budou probrány základy WPF.

Update 2012-02-03 – kód vložení vlastních komponent

K článku dodatečně přidávám XAML kód pro použití vlastní komponenty. Ačkoliv toto téma proberu jindy.

Dejme tomu, že máme assembly “MojeAssembly”. Ta obsahuje v namespacu “MojeAssembly.Komponenty” naše WPF komponenty, jenž v XAMLu chceme inicializovat.

Následuje příklad inicializace komponenty “MojeKomponenta”:

<Window x:Class="HelloWorldWpf.MainWindow" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:moje="clr-namespace:MojeAssembly.Komponenty;assembly=MojeAssembly"
        Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
        <moje:MojeKomponenta />
    </Grid> 
</Window> 

Nejprve jsem definoval odkaz na konkrétní namespace “MojeAssembly.Komponenty” do vlastní assembly “MojeAssembly” pojmenovaný jako “moje”:

xmlns:moje="clr-namespace:MojeAssembly.Komponenty;assembly=MojeAssembly"

Komponentu jsem pak snadno použil pomocí:

<moje:MojeKomponenta />

Závěr

Používání jazyka XAML je pro práci s WPF naprosto stěžejní. Vzhledem k tomu, že v něm pracujete se stejnými objekty, jako při psaní C# kódu, se celý vývoj značně ulehčuje.

Navíc vidím jako obrovskou výhodu práce s libovolnými objekty – nejen těmi z WPF. Získáváme tak možnost použít XAML k inicializaci objektů z externího XML souboru bez nutnosti vytvářet konfigurační sekce či vlastní parser. Načtení objektu, který XAML reprezentuje je totiž otázka jednoho řádku kódu pomocí: XamlReader.Load(zdroj)

Další díl se podívá na zoubek objektové architektuře Windows Presentation Foundation.

bell5_thumbDalší díl vychází příští čtvrtek (9. 2. 2012).

 

hodnocení článku

3 bodů / 3 hlasů       Hodnotit mohou jen registrované uživatelé.

 

 

 

Nový příspěvek

 

Diskuse: XAML a objektový model WPF

Dobrý večer,

Nie je mi z Vášho článku jasné, akým spôsobom vznikol názov http://schemas.microsoft.com/winfx/2006/... , ktorý je uvedený ako defaultný namespace. Myslel som si, že je to nejaká webová adresa, ale ak nie, tak ako potom ten názov vznikol?

A ako by som sa mal v XML a teda aj v XAML odkazovať napríklad na namespace System.Collections.Generic ? Pozn. toto je len príklad, neuvažoval som nad tým, aký by to malo v praxi význam, len je to prvý namespace v .net frameworku, ktorý ma napadol.

[Update] Odpověď na tento dotaz byla vložena do článku.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

http://schemas.microsoft.com/winfx/2006/...

Tento název vznikl jednoduše, je to soubor, který obsahuje definice(schéma) základního markupu, pokud jste již někdy pracoval v HTML, tak by se to dalo přirovnat k například:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-t...">

To co jsem vyznačil výrazně je něco na ten způsob, jenom MS tam asi takázal přístup z prohlížeče.

Takže pokuď zadáte například <Menu>, tak definice toho xaml kódu se někde musí vzít, je to z toho souboru.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Microsoft nezakázal přístup z prohlížeče. Ta adresa prostě neexistuje.

Jak píšu ve článku, jedná se o XML namespace, nikoliv webovou adresu. Je to prostě řetězec a o to, jakým způsobem se s ním naloží, je čistě na parseru XML. Nikde není dáno, že namespace musí být HTTP odkaz na nějaké schéma. Je to pouze unikátní identifikátor, nikoliv internetová adresa, ačkoliv to tak vypadá a někdy (ne nutně vždy) může na této adrese být informace o daném namespacu.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Jedná se rezervovaný název. Je to schéma pevně dodávané s WPF.

Pokud chcete použít vlastní, využijete syntaxi:clr-namespace:MojeAssembly.MujNamespace;assembly=MojeAssembly

Budu o tom psát v další dílech věnovaných vlastním komponentám.

Ale právě tuto informaci jsem do článku ještě doplnil.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Diskuse: XAML a objektový model WPF

Pěkné, už se těším na další díl... :-)

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback