XAML a vlastní třídy pro WPF
XAML, jak je implementované v architekturách CLR (Common Language Runtime), podporuje možnost definovat vlastní třídu nebo strukturu v libovolném jazyce CLR (Common Language Runtime) a pak k této třídě přistupovat pomocí značek XAML. Můžete použít kombinaci typů definovaných ve Windows Presentation Foundation (WPF) a vlastních typů v rámci stejného souboru značek, obvykle mapováním vlastních typů na předponu oboru názvů XAML. Toto téma popisuje požadavky, které musí vlastní třída splňovat, aby byla použitelná jako element XAML.
Vlastní třídy v aplikacích nebo sestaveních
Vlastní třídy používané v xaml lze definovat dvěma různými způsoby: v kódu za kódem nebo jiným kódem, který vytváří primární aplikaci Windows Presentation Foundation (WPF) nebo jako třídu v samostatném sestavení, jako je spustitelný soubor nebo knihovna DLL použitá jako knihovna tříd. Každý z těchto přístupů má konkrétní výhody a nevýhody.
Výhodou vytvoření knihovny tříd je, že všechny takové vlastní třídy lze sdílet napříč mnoha různými možnými aplikacemi. Samostatná knihovna také usnadňuje řízení problémů s správou verzí aplikací a zjednodušuje vytváření třídy, kde zamýšlené použití třídy je jako kořenový prvek na stránce XAML.
Výhodou definování vlastních tříd v aplikaci je, že tato technika je relativně jednoduchá a minimalizuje problémy s nasazením a testováním, ke kterým došlo při zavedení samostatných sestavení nad rámec hlavního spustitelného souboru aplikace.
Bez ohledu na to, zda jsou definovány ve stejném nebo jiném sestavení, musí být vlastní třídy mapovány mezi oborem názvů CLR a oborem názvů XML, aby se používaly v XAML jako elementy. Viz jmenné prostory XAML a mapování jmenného prostoru pro WPF XAML.
Požadavky pro vlastní třídu jako element XAML
Aby bylo možné vytvořit instanci jako element objektu, musí vaše třída splňovat následující požadavky:
Vaše vlastní třída musí být veřejná a musí podporovat výchozí veřejný konstruktor (bez parametrů). (Poznámky týkající se struktur najdete v následující části.)
Vlastní třída nesmí být vnořenou třídou. Vnořené třídy a "tečka" v obecné syntaxi použití CLR interferují s jinými funkcemi WPF nebo XAML, jako jsou připojené vlastnosti.
Kromě povolení syntaxe elementu objektu umožňuje definice objektu také syntaxi elementu vlastnosti pro všechny ostatní veřejné vlastnosti, které tento objekt přebírají jako typ hodnoty. Důvodem je to, že objekt lze nyní instanciovat jako prvek objektu a může naplnit hodnotu prvku vlastnosti takové vlastnosti.
Struktury
Struktury, které definujete jako vlastní typy, se vždy dají vytvořit v XAML ve WPF . Důvodem je to, že kompilátory CLR implicitně vytvářejí konstruktor bez parametrů pro strukturu, která inicializuje všechny hodnoty vlastností na jejich výchozí hodnoty. V některých případech není žádoucí výchozí chování konstrukce a/nebo použití elementu objektu pro strukturu. Důvodem může být to, že struktura je určena k vyplnění hodnot, aby koncepčně fungovala jako unie, kde obsažené hodnoty mohou mít vzájemně se vylučující interpretace, a proto není možné nastavit žádnou z jejích vlastností. Příklad WPF takové struktury je GridLength. Obecně platí, že tyto struktury by měly implementovat převaděč typů tak, aby hodnoty lze vyjádřit ve formě atributu pomocí řetězcových konvencí, které vytvářejí různé interpretace nebo režimy hodnot struktury. Struktura by také měla vystavit podobné chování pro vytváření kódu prostřednictvím konstruktoru bez parametrů.
Požadavky na vlastnosti vlastní třídy jako atributů XAML
Vlastnosti musí odkazovat na typ podle hodnoty (například primitivní) nebo použít třídu pro typ, který má konstruktor bez parametrů nebo vyhrazený převaděč typů, ke kterému má procesor XAML přístup. V implementaci CLR XAML procesory XAML buď najdou takové převaděče prostřednictvím nativní podpory jazykových primitiv, nebo použitím TypeConverterAttribute na typ nebo člen v definicích základního typu.
Alternativně může vlastnost odkazovat na abstraktní typ třídy nebo rozhraní. U abstraktních tříd nebo rozhraní se očekává, že hodnota vlastnosti musí být naplněna konkrétními instancemi tříd, které implementují rozhraní, nebo instancemi typů odvozených z abstraktní třídy.
Vlastnosti lze deklarovat v abstraktní třídě, ale lze je nastavit pouze na konkrétní třídy, které jsou odvozeny z abstraktní třídy. Důvodem je to, že vytvoření elementu objektu pro třídu vůbec vyžaduje veřejný konstruktor bez parametrů ve třídě.
Syntaxe atributu s povolenou funkcí TypeConverter
Pokud zadáte vyhrazený převaděč typu s atributy na úrovni třídy, použitý převod typu povolí syntaxi atributů pro libovolnou vlastnost, která potřebuje vytvořit instanci daného typu. Převaděč typů nepovoluje použití elementu objektu typu; Pouze přítomnost konstruktoru bez parametrů pro tento typ umožňuje použití elementu objektu. Vlastnosti, které mají povolenou funkci převaděče typů, jsou obecně nevyužitelné v syntaxi vlastností, pokud samotný typ také nepodporuje syntaxi elementu objektu. Výjimkou je, že můžete zadat syntaxi elementu vlastnosti, ale daný element vlastnosti může obsahovat řetězec. Toto použití je ve skutečnosti v podstatě ekvivalentní použití syntaxe atributu a takové použití není běžné, pokud není potřeba robustnější zpracování prázdných znaků hodnoty atributu. Například následující je použití elementu vlastnosti, který přebírá řetězec, a odpovídající použití atributu.
<Button>Hallo!
<Button.Language>
de-DE
</Button.Language>
</Button>
<Button Language="de-DE">Hallo!</Button>
Příklady vlastností, ve kterých je povolena syntaxe atributu, ale syntaxe elementu property obsahující prvek objektu je zakázána prostřednictvím XAML jsou různé vlastnosti, které přebírají Cursor typ. Třída Cursor má vyhrazený převaděč typů CursorConverter, ale nemá konstruktor bez parametrů, takže vlastnost Cursor lze nastavit pouze prostřednictvím syntaxe atributu, i když skutečný typ Cursor je referenční typ.
Per-Property převaděče typů
Případně může samotná vlastnost deklarovat převaděč typů na úrovni vlastnosti. To umožňuje "mini language", který vytvoří instance objektů typu vložené vlastnosti zpracováním příchozích řetězcových hodnot atributu jako vstup pro operaci ConvertFrom na základě příslušného typu. Obvykle se to provádí k tomu, aby poskytlo přístupovou metodu pro zjednodušení, a ne jako jediný způsob, jak umožnit nastavení vlastnosti v XAML. Je však také možné použít převaděče typů pro atributy, u kterých chcete použít existující typy CLR, které neposkytují ani konstruktor bez parametrů, ani deklarovaný převaděč typu. Příklady z rozhraní WPF API jsou určité vlastnosti, které přebírají typ CultureInfo. V tomto případě WPF použil existující typ rozhraní Microsoft .NET Framework CultureInfo k lepšímu řešení kompatibility a migračních scénářů, které byly použity v dřívějších verzích rozhraní, ale typ CultureInfo nepodporuje nezbytné konstruktory nebo převod typu typu, aby bylo možné použít přímo jako hodnotu vlastnosti XAML.
Kdykoli zveřejníte vlastnost, která má použití XAML, zejména pokud jste autor ovládacího prvku, měli byste tuto vlastnost důrazně zvážit s vlastností závislosti. To platí zejména v případě, že používáte stávající implementaci WINDOWS Presentation Foundation (WPF) procesoru XAML, protože můžete zlepšit výkon pomocí DependencyProperty zálohování. Vlastnost závislosti zpřístupní funkce systému vlastností pro vaši vlastnost, kterou uživatelé budou očekávat pro přístupnou vlastnost XAML. To zahrnuje funkce, jako je animace, datová vazba a podpora stylu. Další informace naleznete v tématu vlastnosti vlastních závislostí a načítání XAML a vlastnosti závislostí.
Zapisování a přiřazování převaděče typů
Občas budete muset napsat vlastní TypeConverter odvozenou třídu, abyste poskytli převod typů pro váš typ vlastnosti. Pokyny k odvození a vytvoření převaděče typů, který podporuje použití XAML a jak použít TypeConverterAttribute, naleznete v tématu TypeConverters a XAML.
Požadavky na syntaxi atributu obsluhy události XAML u událostí vlastní třídy
Aby byla použitelná jako událost CLR, musí být událost vystavena jako veřejná událost ve třídě, která podporuje konstruktor bez parametrů, nebo v abstraktní třídě, kde je událost přístupná u odvozených tříd. Aby bylo možné ji pohodlně používat jako směrovanou událost, měla by událost CLR implementovat explicitní add
a remove
metody, které přidávají a odebírají obslužné rutiny pro podpis události CLR a předávat tyto obslužné rutiny AddHandler a RemoveHandler metody. Tyto metody přidávají nebo odebírají obslužné rutiny do úložiště směrovaných obslužných rutin událostí v instanci, ke které je událost připojena.
Poznámka
Je možné zaregistrovat obslužné rutiny přímo pro směrované události pomocí AddHandlera záměrně nedefinovat událost CLR, která zveřejňuje směrovanou událost. To se obecně nedoporučuje, protože událost nepovolí syntaxi atributů XAML pro připojení obslužných rutin a výsledná třída nabídne méně transparentní zobrazení XAML schopností tohoto typu.
Zápis vlastností kolekce
Vlastnosti, které přebírají typ kolekce, mají syntaxi XAML, která umožňuje zadat objekty přidané do kolekce. Tato syntaxe má dvě velmi vhodné funkce.
Objekt, který je objekt kolekce, nemusí být zadán v syntaxi elementu objektu. Přítomnost tohoto typu kolekce je implicitní při každém zadání vlastnosti v JAZYCE XAML, která přebírá typ kolekce.
Podřízené prvky vlastnosti kolekce v revizích jsou zpracovány tak, aby se staly členy kolekce. Obvykle se přístup kódu ke členům kolekce provádí prostřednictvím metod seznamu/slovníku, jako je
Add
, nebo prostřednictvím indexeru. Syntaxe XAML ale nepodporuje metody ani indexery (výjimka: XAML 2009 podporuje metody, ale použití XAML 2009 omezuje možné použití WPF; viz funkce jazyka XAML 2009). Kolekce jsou samozřejmě velmi častým požadavkem pro vytvoření stromu prvků a potřebujete nějaký způsob, jak tyto kolekce naplnit deklarativním XAML. Podřízené prvky vlastnosti kolekce jsou proto zpracovány jejich přidáním do kolekce, která je hodnota typu vlastnosti kolekce.
Implementace služeb .NET Framework XAML a tedy procesor WPF XAML používá následující definici toho, co tvoří vlastnost kolekce. Typ vlastnosti musí implementovat jednu z následujících možností:
Implementuje IList.
Implementuje IDictionary.
Odvozuje z Array (další informace o polích v XAML najdete v tématu x:Array Markup Extension.)
Implementuje IAddChild (rozhraní definované WPF).
Každý z těchto typů v CLR má Add
metodu, která je používána procesorem XAML k přidání položek do podkladové kolekce při vytváření grafu objektu.
Poznámka
Obecná rozhraní List
a Dictionary
(IList<T> a IDictionary<TKey,TValue>) nejsou podporována pro detekci kolekcí procesorem WPF XAML. Můžete však použít List<T> třídu jako základní třídu, protože implementuje IList přímo nebo Dictionary<TKey,TValue> jako základní třídu, protože implementuje IDictionary přímo.
Když deklarujete vlastnost, která přebírá kolekci, buďte opatrní ohledně toho, jak je hodnota této vlastnosti inicializována v nových instancích daného typu. Pokud vlastnost neimplementujete jako vlastnost závislosti, pak je adekvátní, aby vlastnost používala podpůrné pole, které volá konstruktor typu kolekce. Pokud je vaše vlastnost závislostí, může být nutné inicializovat vlastnost kolekce jako součást výchozího konstruktoru typu. Důvodem je to, že vlastnost závislosti přebírá výchozí hodnotu z metadat a obvykle nechcete, aby počáteční hodnota vlastnosti kolekce byla statickou sdílenou kolekcí. Pro každou obsaženou instanci typu by měla existovat odpovídající instance kolekce. Další informace naleznete v tématu vlastní závislostní vlastnosti.
Můžete implementovat vlastní typ kolekce pro vlastnost vaší kolekce. Díky implicitnímu zpracování vlastností kolekce nemusí vlastní typ kolekce poskytovat konstruktor bez parametrů, aby mohl být implicitně použit v XAML. Volitelně však můžete zadat konstruktor bez parametrů pro typ kolekce. To může být užitečný postup. Pokud nezadáte konstruktor bez parametrů, nelze kolekci explicitně deklarovat jako prvek objektu. Někteří autoři zápisu můžou preferovat explicitní kolekci jako otázku stylu zápisu. Konstruktor bez parametrů může také zjednodušit inicializační požadavky při vytváření nových objektů, které používají typ kolekce jako hodnotu vlastnosti.
Deklarace vlastností obsahu XAML
Jazyk XAML definuje koncept vlastnosti obsahu XAML. Každá třída, která je použitelná v syntaxi objektu, může mít přesně jednu vlastnost obsahu XAML. Chcete-li deklarovat vlastnost, která má být vlastností obsahu XAML pro vaši třídu, použijte ContentPropertyAttribute jako součást definice třídy. Zadejte název zamýšlené vlastnosti obsahu XAML jako Name v atributu. Vlastnost je určena jako řetězec podle názvu, nikoli jako mechanismus reflexe, například PropertyInfo.
Můžete zadat vlastnost kolekce, která má být vlastností obsahu XAML. Výsledkem je použití této vlastnosti, kdy prvek objektu může mít jeden nebo více podřízených prvků, aniž by došlo k zásahu prvků objektu kolekce nebo značek elementů vlastností. Tyto prvky se pak považují za hodnotu vlastnosti obsahu XAML a jsou přidány do instance podpůrné kolekce.
Některé existující vlastnosti obsahu XAML používají typ vlastnosti Object
. To umožňuje vlastnost obsahu XAML, která může přijímat primitivní hodnoty, jako je String, a také vzít jednu referenční hodnotu objektu. Pokud budete postupovat podle tohoto modelu, je váš typ zodpovědný za určení typu a také za zpracování možných typů. Typickým důvodem Object typu obsahu je podpora jednoduchého způsobu přidání obsahu objektu jako řetězce (který přijímá výchozí úpravu prezentace) nebo pokročilého způsobu přidání obsahu objektu, který určuje jiné než výchozí prezentace nebo další data.
Serializace XAML
V určitých scénářích, například pokud jste autor ovládacího prvku, můžete také chtít zajistit, aby jakákoli reprezentace objektu, které lze v XAML vytvořit jako instance, mohla být také serializována zpět na ekvivalentní značku XAML. Požadavky na serializaci nejsou popsány v tomto tématu. Viz Přehled tvorby ovládacích prvků a Strom elementů a serializace .
Viz také
- XAML v WPF
- vlastní vlastnosti závislosti
- Přehled vytváření ovládacích prvků
- Přehled základních elementů
- Načítání XAML a vlastnosti závislostí
.NET Desktop feedback