Názvové oblasti WPF XAML
Názvové rozsahy XAML jsou koncept, který identifikuje objekty definované v jazyce XAML. Názvy v názvovém oboru XAML lze použít k navázání relací mezi názvy objektů definovanými XAML a jejich ekvivalenty instance ve stromu objektů. Jmenné obory XAML se ve spravovaném kódu WPF obvykle vytvářejí při načítání jednotlivých kořenů stránek XAML pro aplikaci XAML. Názvové rozsahy XAML jako programovací objekt jsou definovány rozhraním INameScope a jsou také implementovány praktickou třídou NameScope.
Názvové rozsahy v načtených aplikacích XAML
V širším kontextu programování nebo počítačové vědy často zahrnují koncepty programování princip jedinečného identifikátoru nebo názvu, který lze použít pro přístup k objektu. Pro systémy, které používají identifikátory nebo názvy, názvový obor definuje hranice, ve kterých bude proces nebo technika prohledávat, pokud je požadován objekt tohoto názvu, nebo hranice, ve kterých se vynucuje jedinečnost identifikace názvů. Tyto obecné principy platí pro názvové rozsahy XAML. Ve WPF jsou názvové skopy XAML vytvořeny v kořenovém elementu pro stránku XAML při načtení stránky. Každý název zadaný na stránce XAML počínaje kořenem stránky se přidá do příslušného oboru názvů XAML.
Ve WPF XAML prvky, které jsou běžnými kořenovými prvky (například Pagea Window), vždy řídí názvový prostor XAML. Pokud je element, například FrameworkElement nebo FrameworkContentElement, kořenovým prvkem stránky v kódu, přidá procesor XAML Page kořen implicitně, aby Page mohl poskytnout funkční názvový rozsah XAML.
Poznámka
Akce sestavení WPF vytvoří názvový prostor XAML pro XAML dokument, i když nejsou definovány žádné atributy Name
nebo x:Name
na žádných prvcích v kódu XAML.
Pokud se pokusíte použít stejný název dvakrát v libovolném názvovém oboru XAML, vyvolá se výjimka. Pro WPF XAML, který má kód v pozadí a je součástí kompilované aplikace, je výjimka vyvolána při sestavování sestavovacími akcemi WPF při vytváření vygenerované třídy pro stránku během počáteční kompilace XAML značek. U XAML, který není kompilován žádnou akcí sestavení, mohou být při načtení XAML vyvolány výjimky související s problémy s názvovým rozsahem XAML. Návrháři XAML mohou také očekávat problémy s oborem názvů XAML během návrhu.
Přidání objektů do stromů objektů modulu runtime
Okamžik, kdy se XAML analyzuje, je okamžikem v čase, kdy je vytvořen a definován názvový rozsah WPF XAML. Pokud přidáte objekt do stromu objektů v okamžiku po tom, co byl kód XAML, který tento strom vytvořil, analyzován, hodnota Name
nebo x:Name
na novém objektu automaticky neaktualizuje informace v názvovém oboru XAML. Chcete-li přidat název objektu do jmenného prostoru WPF XAML po načtení XAML, je nutné volat odpovídající implementaci RegisterName na objektu, který definuje tento jmenný prostor, což je obvykle kořen stránky XAML. Pokud název není zaregistrovaný, přidaný objekt nelze odkazovat pomocí metod, jako je FindName, a tento název nelze použít pro cílení na animace.
Nejběžnějším scénářem pro vývojáře aplikací je, že použijete RegisterName k registraci názvů do názvového oboru XAML v aktuálním kořenovém adresáři stránky. RegisterName je součástí důležitého scénáře pro scénáře, které cílí na objekty pro animace. Další informace najdete v tématu Přehled scénářů.
Pokud voláte RegisterName u objektu jiného než objektu, který definuje názvový rozsah XAML, je název stále zaregistrován do oboru názvů XAML, který je uložen v volajícím objektu, jako kdybyste volali RegisterName v definičním objektu XAML namescope.
Názvové skopy XAML v kódu
V kódu můžete vytvořit a pak použít názvové názvové skopy XAML. Rozhraní API a koncepty zahrnuté do vytváření názvového oboru XAML jsou stejné i pro použití čistého kódu, protože procesor XAML pro WPF používá tato rozhraní API a koncepty při zpracování samotného XAML. Koncepty a rozhraní API existují hlavně pro účely schopnosti najít objekty podle názvu v rámci stromu objektů, který je obvykle definován částečně nebo zcela v XAML.
Pro aplikace vytvořené programově, a ne z načteného XAML, musí objekt, který definuje názvový obor XAML, implementovat INameScope, nebo být třídou odvozenou z FrameworkElement nebo FrameworkContentElement, aby podporoval vytvoření názvového oboru XAML ve svých instancích.
Také pro každý prvek, který není načten a zpracován procesorem XAML, se namescope XAML pro daný objekt ve výchozím nastavení nevytváří ani neinizializuje. Musíte explicitně vytvořit nový názvový rozsah XAML pro jakýkoli objekt, do kterého chcete následně zaregistrovat názvy. Pokud chcete vytvořit názvový rozsah XAML, zavoláte statickou metodu SetNameScope. Zadejte objekt, který ho bude vlastnit jako parametr dependencyObject
, a jako parametr value
zavolá nový konstruktor NameScope.
Pokud objekt zadaný jako dependencyObject
pro SetNameScope není implementace INameScope, FrameworkElement nebo FrameworkContentElement, volání RegisterName na všechny podřízené prvky nebude mít žádný vliv. Pokud se vám nepodaří vytvořit nový názvový rozsah XAML explicitně, volání RegisterName vyvolá výjimku.
Příklad použití rozhraní XAML namescope API v kódu najdete v tématu Definování oboru názvů.
Názvové rozsahy XAML ve stylech a šablonách
Styly a šablony ve WPF poskytují možnost opakovaně používat a znovu používat obsah jednoduchým způsobem. Styly a šablony ale můžou obsahovat i prvky s názvy XAML definovanými na úrovni šablony. Stejná šablona se může na stránce používat vícekrát. Z tohoto důvodu styly a šablony definují vlastní názvové rozsahy XAML nezávisle na libovolném umístění ve stromu objektů, ve kterém je použit styl nebo šablona.
Podívejte se na následující příklad:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Page.Resources>
<ControlTemplate x:Key="MyButtonTemplate" TargetType="{x:Type Button}">
<Border BorderBrush="Red" Name="TheBorder" BorderThickness="2">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Page.Resources>
<StackPanel>
<Button Template="{StaticResource MyButtonTemplate}">My first button</Button>
<Button Template="{StaticResource MyButtonTemplate}">My second button</Button>
</StackPanel>
</Page>
V této části se stejná šablona použije na dvě různá tlačítka. Pokud by šablony neměly oddělené názvové obory XAML, název TheBorder
použitý v šabloně by způsobil konflikt názvů v názvovém oboru XAML. Každá instance šablony má svůj vlastní názvový prostor XAML, takže v tomto příkladu by názvový prostor XAML každé instance šablony obsahoval přesně jedno jméno.
Styly také definují vlastní názvový rozsah XAML, většinou tak, aby části scénářů mohly mít přiřazené konkrétní názvy. Tyto názvy umožňují řídit specifické chování, které bude cílit na prvky tohoto názvu, i když byla šablona znovu definována jako součást přizpůsobení ovládacího prvku.
Vzhledem k samostatným oborům názvů XAML je nalezení pojmenovaných prvků v šabloně náročnější než nalezení nešablonovaného pojmenovaného prvku na stránce. Nejdřív je potřeba určit použitou šablonu získáním hodnoty vlastnosti Template ovládacího prvku, ve kterém je šablona použita. Potom zavoláte verzi šablony FindNamea předáte ovládací prvek, ve kterém byla šablona použita jako druhý parametr.
Pokud jste autor ovládacího prvku a generujete konvenci, kde konkrétní pojmenovaný prvek v použité šabloně je cílem chování, které je definováno samotným ovládacím prvkem, můžete použít GetTemplateChild metodu z kódu implementace ovládacího prvku. Metoda GetTemplateChild je chráněná, takže k ní má přístup pouze autor ovládacího prvku.
Pokud pracujete v rámci šablony a potřebujete se dostat do oboru názvů XAML, kde je šablona použita, získejte hodnotu TemplatedParenta potom tam zavolejte FindName. Příkladem práce v rámci šablony by bylo, kdybyste psali implementaci obslužné rutiny události, kde bude událost vyvolána z elementu v použité šabloně.
Názvové rozsahy XAML a rozhraní API související s názvy
FrameworkElement má metody FindName, RegisterName a UnregisterName. Pokud objekt, na který voláte tyto metody, vlastní názvový obor XAML, tyto metody volají přímo metody příslušného názvového oboru XAML. V opačném případě se nadřazený prvek zkontroluje, jestli vlastní názvový rozsah XAML, a tento proces pokračuje rekurzivně, dokud se nenajde názvový rozsah XAML (kvůli chování procesoru XAML je zaručeno, že v kořenovém adresáři je názvový rozsah XAML). FrameworkContentElement má podobné chování, s výjimkou, že žádný FrameworkContentElement nebude nikdy vlastnit názvový rozsah XAML. Metody existují u FrameworkContentElement, aby bylo možné volání nakonec přesměrovat na FrameworkElement nadřazený prvek.
SetNameScope slouží k mapování nového oboru názvů XAML na existující objekt. Pokud chcete resetovat nebo vymazat názvový rozsah XAML, můžete volat SetNameScope více než jednou, ale to není běžné použití. GetNameScope se také obvykle nepoužívá v kódu.
Implementace názvového oboru XAML
Následující třídy implementují INameScope přímo:
ResourceDictionary nepoužívá názvy XAML ani názvové prostory, místo toho používá klíče, protože je to implementace slovníku. Jediným důvodem, proč ResourceDictionary implementuje INameScope je, aby mohl vyvolat výjimky uživatelského kódu, které pomáhají objasnit rozdíl mezi skutečným názvovým rozsahem XAML a tím, jak ResourceDictionary zpracovává klíče, a také zajistit, aby se názvové rozsahy XAML nepouužijí na ResourceDictionary nadřazenými prvky.
FrameworkTemplate a Style implementují INameScope prostřednictvím explicitních definic rozhraní. Explicitní implementace umožňují, aby se tyto názvové skopy XAML chovaly konvenčně, když jsou přístupné prostřednictvím INameScope rozhraní, což je způsob, jakým jsou názvové skopy XAML komunikovány interními procesy WPF. Explicitní definice rozhraní však nejsou součástí tradiční plochy rozhraní API FrameworkTemplate a Style, protože zřídka potřebujete volat metody INameScope přímo na FrameworkTemplate a Style, a místo toho byste používali jiné rozhraní API, jako je GetTemplateChild.
Následující třídy definují vlastní názvový rozsah XAML pomocí pomocné třídy System.Windows.NameScope a připojují se k jeho implementaci názvového rozsahu XAML prostřednictvím připojené vlastnosti NameScope.NameScope:
Viz také
.NET Desktop feedback