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 Obory názvů XAML a mapování Namespace 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í vytvořit instanci jako prvek objektu a může vyplnit 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 a funkci koncepčně jako sjednocení, kde obsažené hodnoty mohou mít vzájemně se vylučující interpretace, a proto není nastavena žádná z jejích vlastností. Příkladem takové struktury WPF 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 pro primitiv jazyka, nebo prostřednictvím aplikace TypeConverterAttribute typu nebo člena v backing definice typu.

Alternativně může vlastnost odkazovat na abstraktní typ třídy nebo rozhraní. U abstraktních tříd nebo rozhraní očekáváme, že hodnota vlastnosti musí být vyplněna konkrétními instancemi třídy, které implementují rozhraní, nebo instance 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é jsou povoleny převaděče typů jsou obecně použitelné v syntaxi vlastnosti, pokud samotný typ také nepodporuje syntaxi elementu objektu. Výjimkou je, že můžete zadat syntaxi elementu vlastnosti, ale mít element property obsahuje ř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 ekvivalent 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ěč CursorConvertertypů , ale nezpřístupňuje konstruktor bez parametrů, takže Cursor vlastnost lze nastavit pouze prostřednictvím syntaxe atributu, i když skutečný Cursor typ je referenční typ.

Převaděče typů vlastností

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 ConvertFrom operaci na základě příslušného typu. Obvykle se to provádí tak, aby poskytovalo přístupové objekty pohodlí, a ne jako jediný způsob povolení nastavení vlastnosti v XAML. Je však také možné použít převaděče typů pro atributy, ve kterých chcete použít existující typy CLR, které nezadají konstruktor bez parametrů nebo převaděč atributů typu. Příklady z rozhraní API WPF jsou určité vlastnosti, které tento typ přebírají CultureInfo . V tomto případě WPF použil existující typ rozhraní Microsoft .NET Framework CultureInfo k lepšímu řešení scénářů kompatibility a migrace, které byly použity v dřívějších verzích rozhraní, ale CultureInfo typ nepodporuje nezbytné konstruktory nebo převod typů na úrovni typu, které by bylo možné použít jako hodnotu vlastnosti XAML přímo.

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 backingu. 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 Vlastní vlastnosti závislostí a načítání XAML a vlastnosti závislostí.

Zápis a přiřazení převaděče typů

Někdy budete muset napsat vlastní TypeConverter odvozenou třídu, která poskytuje převod typů pro váš typ vlastnosti. Pokyny k odvození a vytvoření převaděče typů, který může podporovat použití XAML a použití , naleznete v TypeConverterAttributetématu TypeConverters a XAML.

Požadavky na syntaxi atributu obslužné rutiny 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é tuto událost 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ávají tyto obslužné rutiny do AddHandler a RemoveHandler metod. 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 Addje , nebo prostřednictvím indexeru. Syntaxe XAML ale nepodporuje metody ani indexery (výjimka: XAML 2009 může podporovat metody, ale použití XAML 2009 omezuje možné použití WPF; viz jazykové funkce 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 .NET Framework XAML Services, a proto procesor WPF XAML používá následující definici pro to, co představuje vlastnost kolekce. Typ vlastnosti vlastnosti musí implementovat jednu z následujících vlastností:

Každý z těchto typů v CLR má metodu Add , která je používána procesorem XAML k přidání položek do podkladové kolekce při vytváření objektového grafu.

Poznámka:

List Obecná rozhraní (DictionaryIList<T>aIDictionary<TKey,TValue>) nejsou podporována pro detekci kolekcí procesorem WPF XAML. Třídu však můžete použít List<T> 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í o tom, jak se tato hodnota vlastnosti inicializuje v nových instancích typu. Pokud vlastnost neimimujete jako vlastnost závislosti, pak vlastnost použít backing pole, které volá konstruktor typu kolekce, je adekvátní. 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 instanci typu by měla existovat instance kolekce. Další informace naleznete v tématu Vlastní vlastnosti závislostí.

Pro vlastnost kolekce můžete implementovat vlastní typ kolekce. Vzhledem k tomu, implicitní zpracování vlastností kolekce, vlastní typ kolekce nemusí poskytovat konstruktor bez parametrů, aby bylo možné použít v XAML implicitně. 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 revizí můžou preferovat explicitní kolekci v rámci stylu revizí. 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 atribut. Vlastnost je určena jako řetězec podle názvu, nikoli jako konstruktor 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 přidají se do instance backing kolekce.

Některé existující vlastnosti obsahu XAML používají typ Objectvlastnosti . To umožňuje vlastnost obsahu XAML, která může přijímat primitivní hodnoty, jako String je například hodnota jednoho referenčního 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 typu Object 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 nestandardní prezentaci 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 vytvořit instanci v XAML, může být také serializována zpět na ekvivalentní kód XAML. Požadavky na serializaci nejsou popsány v tomto tématu. Viz Přehled vytváření ovládacích prvků a strom elementů a serializace.

Viz také