Udostępnij za pośrednictwem


Szczegółowa składnia XAML

W tym temacie zdefiniowano terminy, które są używane do opisywania elementów składni XAML. Te terminy są często używane w pozostałej części tej dokumentacji, zarówno w przypadku dokumentacji WPF, jak i dla innych struktur korzystających z języka XAML lub podstawowych pojęć XAML włączonych przez obsługę języka XAML na poziomie System.Xaml. Ten temat rozszerza podstawową terminologię wprowadzoną w temacie XAML wWPF.

Specyfikacja języka XAML

Terminologia składni XAML zdefiniowana tutaj jest również zdefiniowana lub przywoływana w specyfikacji języka XAML. XAML to język oparty na XML i przestrzega lub rozszerza zasady strukturalne XML. Część terminologii jest udostępniana lub opiera się na terminologii często używanej podczas opisywania języka XML lub modelu obiektów dokumentów XML.

Aby uzyskać więcej informacji na temat specyfikacji języka XAML, pobierz [MS-XAML] z Centrum pobierania Microsoft.

XAML i CLR

XAML to język znaczników. Środowisko uruchomieniowe języka wspólnego (CLR), jak sugeruje jego nazwa, umożliwia wykonywanie podczas działania. Język XAML nie jest sam w sobie jednym z popularnych języków, które są bezpośrednio używane przez środowisko uruchomieniowe CLR. Zamiast tego można traktować język XAML jako obsługę własnego systemu typów. Konkretny system analizy XAML używany przez WPF jest oparty na clR i systemie typów CLR. Typy XAML są mapowane na typy CLR w celu utworzenia reprezentacji w czasie wykonywania, gdy XAML dla WPF jest parsowany. Dlatego pozostała część dyskusji na temat składni w tym dokumencie będzie zawierać odniesienia do systemu typów CLR, mimo że równoważne dyskusje składni w specyfikacji języka XAML ich nie zawierają. (Na poziomie specyfikacji języka XAML typy XAML mogą być mapowane na dowolny inny system typów, który nie musi być CLR, ale wymagałoby to utworzenia i użycia innego analizatora XAML).

Członkowie typów i dziedziczenie klas

Właściwości i zdarzenia, które występują jako elementy członkowskie XAML w typach WPF, są często dziedziczone z typów podstawowych. Rozważmy na przykład następujący przykład: <Button Background="Blue" .../>. Właściwość Background nie jest natychmiast zadeklarowaną właściwością klasy Button, jeśli chodzi o definicję klasy, wyniki odbicia lub dokumentację. Zamiast tego Background jest dziedziczony po klasie bazowej Control.

Zachowanie dziedziczenia klas elementów XAML WPF jest znaczącym odejściem od wymuszanej przez schemat interpretacji znaczników XML. Dziedziczenie klas może stać się złożone, szczególnie gdy pośrednie klasy bazowe są abstrakcyjne lub gdy są zaangażowane interfejsy. Jest to jeden z powodów, dla których zestaw elementów XAML i ich dopuszczalne atrybuty są trudne do reprezentowania dokładnie i całkowicie przy użyciu typów schematów, które są zwykle używane do programowania XML, takiego jak format DTD lub XSD. Innym powodem jest to, że rozszerzalność i cechy mapowania typów samego języka XAML uniemożliwiają kompletność dowolnej stałej reprezentacji dopuszczalnych typów i elementów członkowskich.

Składnia elementu object

Składnia elementu obiektu to składnia znaczników XAML, która tworzy instancję klasy CLR lub struktury poprzez zadeklarowanie elementu XML. Ta składnia przypomina składnię elementów innych języków znaczników, takich jak HTML. Składnia elementu obiektu rozpoczyna się od lewego nawiasu kątowego (<), po którym następuje natychmiast nazwa typu tworzonej klasy lub struktury. Może występować zero lub więcej spacji po nazwie typu, a także może być zadeklarowanych zero lub więcej atrybutów w elemencie obiektu, z co najmniej jedną spacją oddzielającą każdą parę nazwa atrybutu="wartość". Na koniec jedna z następujących wartości musi być prawdziwa:

  • Element i tag muszą być zamknięte ukośnikiem do przodu (/), a następnie bezpośrednio nawiasem kątowym (>).

  • Tag otwierający musi zostać zakończony nawiasem ostrym (>). Inne elementy obiektu, elementy właściwości lub tekst wewnętrzny mogą być zgodne z tagiem otwierającym. Dokładnie zawartość, która może być zawarta w tym miejscu, jest zwykle ograniczona przez model obiektów elementu. Równoważny tag zamykający dla elementu obiektu musi również istnieć, zachowując odpowiednie zagnieżdżenie i równowagę z innymi parami tagów otwierających i zamykających.

Język XAML implementowany przez platformę .NET zawiera zestaw reguł mapujących elementy obiektów na typy, atrybuty w właściwości lub zdarzenia oraz przestrzenie nazw XAML na przestrzenie nazw CLR oraz zestaw. W przypadku elementów obiektów WPF i .NET elementy obiektów XAML są mapowane na typy platformy .NET zgodnie z definicją w zestawach, a atrybuty są mapowane na elementy członkowskie tych typów. W przypadku odwołania się do typu CLR w XAML, masz również dostęp do odziedziczonych składników tego typu.

Na przykład poniższy przykład to składnia elementu obiektu, która tworzy wystąpienie nowego wystąpienia klasy Button, a także określa atrybut Name i wartość dla tego atrybutu:

<Button Name="CheckoutButton"/>

Poniższy przykład to składnia elementu obiektu, która zawiera również składnię właściwości zawartości XAML. Tekst wewnętrzny będzie wykorzystany do ustawienia właściwości zawartości XAML TextBoxText.

<TextBox>This is a Text Box</TextBox>

Modele zawartości

Klasa może obsługiwać użycie jako element obiektu XAML pod względem składni, ale ten element będzie działać prawidłowo tylko w aplikacji lub na stronie, gdy zostanie umieszczony w oczekiwanej pozycji ogólnego modelu zawartości lub drzewa elementów. Na przykład MenuItem zazwyczaj należy umieścić tylko jako element podrzędny klasy pochodnej MenuBase, takiej jak Menu. Modele treści dla specyficznych elementów są udokumentowane w ramach uwag na stronach klas dotyczących kontrolek i innych klas WPF, które mogą być używane jako elementy XAML w ramach WPF.

Właściwości elementów obiektu

Właściwości w języku XAML są ustawiane przez różne możliwe składnie. Składnia, która może być używana dla określonej właściwości, będzie się różnić w zależności od właściwości systemu typu bazowego ustawianej właściwości.

Ustawiając wartości właściwości, dodajesz funkcje lub cechy do obiektów, ponieważ istnieją one na wykresie obiektu czasu wykonywania. Początkowy stan utworzonego obiektu na podstawie elementu obiektu jest oparty na zachowaniu konstruktora bez parametrów. Zazwyczaj aplikacja będzie używać czegoś innego niż całkowicie domyślne wystąpienie dowolnego obiektu.

Składnia atrybutu (właściwości)

Składnia atrybutu to składnia znaczników XAML, która ustawia wartość dla właściwości, deklarując atrybut dla istniejącego elementu obiektu. Nazwa atrybutu musi być zgodna z nazwą składowej CLR właściwości klasy, która obsługuje odpowiedni element obiektu. Po nazwie atrybutu następuje operator przypisania (=). Wartość atrybutu musi być ciągiem ujętym w cudzysłów.

Notatka

Możesz użyć naprzemiennych cudzysłowów, aby wstawić znak cudzysłowu dosłownego w atrybucie. Na przykład można użyć pojedynczych cudzysłowów jako sposobu na zadeklarowanie ciągu, który zawiera znak podwójnego cudzysłowu. Niezależnie od tego, czy używasz cudzysłowów pojedynczych, czy podwójnych, należy użyć pary pasującej do otwierania i zamykania ciągu wartości atrybutu. Istnieją również sekwencje ucieczki lub inne techniki dostępne do pracy z ograniczeniami znaków narzuconymi przez dowolną konkretną składnię XAML. Zobacz encje znakowe XML i XAML.

Aby można było ustawić za pomocą składni atrybutu, właściwość musi być publiczna i musi być zapisywalna. Wartość właściwości w systemie typów pomocniczych musi być typem wartości albo typem referencyjnym, dla którego można utworzyć wystąpienie lub który może być przywołany przez procesor XAML podczas uzyskiwania dostępu do odpowiedniego typu pomocniczego.

W przypadku zdarzeń XAML WPF zdarzenie, do którego odwołuje się nazwa atrybutu, musi być publiczne i mieć delegata publicznego.

Właściwość lub zdarzenie musi być elementem członkowskim klasy lub struktury tworzonej przez element zawierający obiekt.

Przetwarzanie wartości atrybutów

Wartość ciągu zawarta w cudzysłowie otwierającym i zamykającym jest przetwarzana przez procesor XAML. W przypadku właściwości domyślne zachowanie przetwarzania jest określane przez typ podstawowej właściwości CLR.

Wartość atrybutu jest wypełniana przez jedną z następujących wartości przy użyciu tego zamówienia przetwarzania:

  1. Jeśli procesor XAML napotka nawias klamrowy lub element obiektu wywodzący się z MarkupExtension, to zamiast przetwarzać wartość jako ciąg znaków, najpierw ocenia przywoływane rozszerzenie znaczników, a obiekt zwracany przez to rozszerzenie jest używany jako wartość. W wielu przypadkach obiekt zwracany przez ekstensję znaczników będzie odwołaniem do istniejącego obiektu lub wyrażeniem, które opóźnia ocenę do czasu uruchomienia, i nie jest nowo utworzonym obiektem.

  2. Jeśli właściwość jest zadeklarowana za pomocą atrybutu TypeConverter, lub typ wartości tej właściwości jest zadeklarowany z atrybutem TypeConverter, wartość ciągu atrybutu jest przesyłana do konwertera typów jako dane wejściowe konwersji, a konwerter zwróci nowe wystąpienie obiektu.

  3. Jeśli nie ma TypeConverter, zostanie podjęta próba bezpośredniej konwersji na typ właściwości. Ten ostatni poziom jest bezpośrednią konwersją na wartość natywną analizatora składni dla typów pierwotnych języka XAML lub i sprawdzaniem nazw nazwanych stałych w wyliczeniu (analizator uzyskuje wtedy dostęp do pasujących wartości).

Wartości atrybutów enumeracji

Wyliczenia w języku XAML są przetwarzane wewnętrznie przez analizatory XAML, a elementy członkowskie wyliczenia należy określić, określając nazwę ciągu jednego z nazwanych stałych wyliczenia.

W przypadku wartości wyliczeń nie będących flagami, zachowanie natywne polega na przetwarzaniu ciągu wartości atrybutu i rozpoznawaniu jej jako jednej z wartości wyliczeniowych. Nie określasz wyliczenia w formacie Wyliczenie.Wartość, jak w kodzie. Zamiast tego należy określić tylko wartość, a Wyliczenie jest wnioskowane przez typ ustawianej właściwości. Jeśli określisz atrybut w formie Wyliczenie.wartość, nie zostanie on poprawnie rozpoznany.

W przypadku wyliczeń flagowych zachowanie jest oparte na metodzie Enum.Parse. Dla wyliczenia flagowego można określić wiele wartości, oddzielając każdą wartość przecinkami. Nie można jednak połączyć wartości wyliczenia, które nie są flagowe. Na przykład nie można użyć składni przecinka, aby utworzyć Trigger, które działa na wielu warunkach wyliczenia nienaznaczonego.

<!--This will not compile, because Visibility is not a flagwise enumeration.-->  
...  
<Trigger Property="Visibility" Value="Collapsed,Hidden">  
  <Setter ... />  
</Trigger>  
...  

Flagowe wyliczenia, które obsługują atrybuty, które są ustawiane w języku XAML, są rzadkie w WPF. Jednak jedną z takich wyliczeń jest StyleSimulations. Można na przykład użyć składni atrybutu rozdzielanego przecinkami, aby zmodyfikować przykład podany w uwagach dla klasy Glyphs; StyleSimulations = "BoldSimulation" może stać się StyleSimulations = "BoldSimulation,ItalicSimulation". KeyBinding.Modifiers jest inną właściwością, w której można określić więcej niż jedną wartość wyliczenia. Jednak ta właściwość jest wyjątkowym przypadkiem, ponieważ wyliczenie ModifierKeys obsługuje swój własny konwerter typów. Konwerter typów modyfikatorów używa znaku plus (+) jako ogranicznika, a nie przecinka (,). Ta konwersja obsługuje bardziej tradycyjną składnię do reprezentowania kombinacji w programowaniu systemu Microsoft Windows, takich jak "Ctrl+Alt".

Właściwości i odwołania do nazw członków zdarzenia

Podczas określania atrybutu można odwołać się do dowolnej właściwości lub zdarzenia, które istnieje jako element członkowski typu CLR utworzonego dla elementu zawierającego obiekt.

Można też odwołać się do dołączonej właściwości lub dołączonego zdarzenia niezależnie od elementu zawierającego obiekt. (Dołączone właściwości zostaną omówione w jednej z nadchodzących sekcji).

Można również nazwać dowolne zdarzenie z dowolnego obiektu, który jest dostępny za pośrednictwem domyślnej przestrzeni nazw przy użyciu typeName. częściowo kwalifikowaną nazwą; ta składnia obsługuje dołączanie programów obsługi dla zdarzeń kierowanych, w których program obsługi ma na celu obsługę routingu zdarzeń z elementów podrzędnych, ale element nadrzędny nie ma tego zdarzenia w swojej tabeli elementów członkowskich. Ta składnia przypomina dołączoną składnię zdarzenia, ale to zdarzenie nie jest prawdziwym dołączonym zdarzeniem. Zamiast tego odwołujesz się do zdarzenia o kwalifikowanej nazwie. Aby uzyskać więcej informacji, zobacz Routed Events Overview.

W niektórych scenariuszach nazwy właściwości są czasami podawane jako wartość atrybutu, a nie nazwa atrybutu. Ta nazwa właściwości może również zawierać kwalifikatory, takie jak ta określona w postaci ownerType.dependencyPropertyName. Ten scenariusz jest typowy podczas pisania stylów lub szablonów w języku XAML. Reguły przetwarzania nazw właściwości podane jako wartość atrybutu są różne i podlegają typowi ustawianej właściwości lub zachowaniom określonych podsystemów WPF. Aby uzyskać szczegółowe informacje, zobacz Styleing and Templating.

Innym użyciem nazw właściwości jest to, gdy wartość atrybutu opisuje relację właściwości-właściwość. Funkcja ta jest używana do wiązania danych oraz dla docelowych elementów scenorysu i jest aktywowana przez klasę PropertyPath oraz jej konwerter typów. Aby uzyskać bardziej szczegółowy opis semantyki przeszukiwania, zobacz PropertyPath XAML Syntax.

Składnia elementu właściwości

Składnia elementu właściwości jest składnią, która nieco odbiega od podstawowych reguł składni XML dla elementów. W formacie XML wartość atrybutu jest de facto ciągiem, a jedyną możliwą odmianą jest używany format kodowania ciągów. W języku XAML można przypisać inne elementy obiektu jako wartość właściwości. Ta funkcja jest umożliwiana przez składnię elementu właściwości. Zamiast właściwości określonej jako atrybut w tagu elementu, właściwość jest określana przy użyciu otwierającego tagu elementu w formacie elementTypeName.propertyName, wartość właściwości jest określona wewnątrz elementu, a następnie element właściwości jest zamknięty.

W szczególności składnia zaczyna się od lewego nawiasu kątowego (<), po którym następuje natychmiast nazwa typu klasy lub struktury, w której znajduje się składnia elementu właściwości. Następuje to natychmiast po pojedynczej kropce (.), następnie nazwą właściwości, a na końcu prawym nawiasem kątowym (>). Podobnie jak w przypadku składni atrybutu, ta właściwość musi istnieć w zadeklarowanych członkach publicznych określonego typu. Wartość, która ma zostać przypisana do właściwości, jest zawarta w elemecie właściwości. Zazwyczaj wartość jest podawana jako co najmniej jeden element obiektu, ponieważ określenie obiektów jako wartości jest scenariuszem, w jakim składnia elementu właściwości ma na celu rozwiązanie problemu. Na koniec, należy podać równoważny tag zamykający, określający kombinację tego samego elementTypeName.propertyName , przy zachowaniu odpowiedniego zagnieżdżania i równowagi z innymi tagami elementów.

Na przykład, poniżej znajduje się składnia elementu własności dla własności ContextMenu obiektu Button.

<Button>
  <Button.ContextMenu>
    <ContextMenu>
      <MenuItem Header="1">First item</MenuItem>
      <MenuItem Header="2">Second item</MenuItem>
    </ContextMenu>
  </Button.ContextMenu>
  Right-click me!</Button>

Wartość elementu właściwości może być również podana jako tekst wewnętrzny, w przypadkach, gdy określony typ właściwości jest typem wartości pierwotnej, takim jak String, lub wyliczenie, w którym określono nazwę. Te dwa zastosowania są nieco nietypowe, ponieważ każdy z tych przypadków może również używać prostszej składni atrybutów. Jednym ze scenariuszy wypełniania elementu właściwości ciągiem jest zastosowanie właściwości, które nie są właściwością zawartości XAML, ale nadal są używane do reprezentacji tekstu interfejsu użytkownika, a konkretne elementy odstępu, takie jak kanały wiersza, są wymagane do wyświetlenia w tym tekście interfejsu użytkownika. Składnia atrybutów nie może zachować znaków nowej linii, ale składnia elementu właściwości może, pod warunkiem że aktywne jest zachowanie znaczących białych znaków (aby uzyskać szczegółowe informacje, zobacz Przetwarzanie białych znaków w języku XAML). Innym scenariuszem jest to, że x:Uid Dyrektywy można zastosować do elementu właściwości, a tym samym oznaczyć wartość w postaci wartości, która powinna być zlokalizowana w danych wyjściowych WPF BAML lub innych technik.

Element właściwości nie jest reprezentowany w drzewie logicznym WPF. Element właściwości to tylko określona składnia ustawiania właściwości i nie jest elementem, który zawiera wystąpienie lub obiekt, który go wspiera. (Aby uzyskać szczegółowe informacje na temat koncepcji drzewa logicznego, zobacz Trees in WPF.)

W przypadku właściwości, w których obsługiwana jest składnia atrybutu i elementu właściwości, dwie składnie zazwyczaj mają ten sam wynik, chociaż subtelności, takie jak obsługa białych znaków, mogą się nieznacznie różnić w zależności od składni.

Składnia kolekcji

Specyfikacja XAML wymaga implementacji procesora XAML w celu zidentyfikowania właściwości, w których typ wartości jest kolekcją. Ogólna implementacja procesora XAML na platformie .NET jest oparta na kodzie zarządzanym i środowisku CLR oraz identyfikuje typy kolekcji za pomocą jednej z następujących metod:

Jeśli typ właściwości jest kolekcją, wywnioskowany typ kolekcji nie musi być określony w znaczniku jako element obiektu. Zamiast tego elementy, które mają stać się pozycjami w kolekcji, są określane jako jeden lub więcej elementów podrzędnych elementu właściwości. Każdy taki element jest przekształcany w obiekt podczas ładowania i dodawany do kolekcji przez wywołanie metody Add kolekcji wynikającej z kontekstu. Na przykład właściwość Triggers obiektu Style przyjmuje specjalizowany typ kolekcji TriggerCollection, który implementuje IList. Nie jest konieczne tworzenie instancji elementu obiektu TriggerCollection w znacznikach. Zamiast tego należy określić jeden lub więcej elementów Trigger jako elementy wewnątrz elementu właściwości Style.Triggers, gdzie Trigger (lub klasa pochodna) jest oczekiwanym typem elementu dla silnie typizowanego i niejawnego TriggerCollection.

<Style x:Key="SpecialButton" TargetType="{x:Type Button}">
  <Style.Triggers>
    <Trigger Property="Button.IsMouseOver" Value="true">
      <Setter Property = "Background" Value="Red"/>
    </Trigger>
    <Trigger Property="Button.IsPressed" Value="true">
      <Setter Property = "Foreground" Value="Green"/>
    </Trigger>
  </Style.Triggers>
</Style>

Właściwość może być zarówno typem kolekcji, jak i właściwością zawartości XAML dla tego typu i typów pochodnych, które zostały omówione w następnej sekcji tego tematu.

Niejawny element kolekcji tworzy element członkowski w reprezentacji drzewa logicznego, mimo że nie jest wyświetlany w znaczniku jako element. Zwykle konstruktor typu nadrzędnego inicjuje kolekcję, która jest jedną z jego właściwości, a początkowo pusta kolekcja staje się częścią hierarchii obiektów.

Notatka

Ogólne interfejsy listy i słownika (IList<T> i IDictionary<TKey,TValue>) nie są obsługiwane w przypadku wykrywania kolekcji. Można jednak użyć klasy List<T> jako klasy bazowej, ponieważ implementuje IList bezpośrednio lub Dictionary<TKey,TValue> jako klasę bazową, ponieważ implementuje IDictionary bezpośrednio.

Na stronach referencyjnych platformy .NET dla typów kolekcji ta składnia z celowym pominięciem elementu obiektu dla kolekcji jest od czasu do czasu zanotowana w sekcjach składni XAML jako Składnia niejawnej kolekcji.

Z wyjątkiem elementu głównego każdy element obiektu w pliku XAML, który jest zagnieżdżony jako element podrzędny innego elementu, jest naprawdę elementem, który jest jednym lub oba z następujących przypadków: elementem niejawnym właściwości kolekcji elementu nadrzędnego lub elementem określającym wartość właściwości zawartości XAML dla elementu nadrzędnego (właściwości zawartości XAML zostaną omówione w nadchodzącej sekcji). Innymi słowy, relacja elementów nadrzędnych i elementów podrzędnych w stronie znaczników jest w rzeczywistości pojedynczym obiektem w korzeniu, a każdy element obiektu pod korzeniem jest albo pojedynczym wystąpieniem, które zapewnia wartość właściwości elementu nadrzędnego, albo jednym z elementów w kolekcji, która jest również wartością właściwości typu kolekcji elementu nadrzędnego. Koncepcja jednego korzenia jest powszechna dla XML i jest często wzmacniana w zachowaniu API wczytujących XAML, takich jak Load.

Poniższy przykład przedstawia składnię z elementem object kolekcji (GradientStopCollection) określonym jawnie.

<LinearGradientBrush>  
  <LinearGradientBrush.GradientStops>  
    <GradientStopCollection>  
      <GradientStop Offset="0.0" Color="Red" />  
      <GradientStop Offset="1.0" Color="Blue" />  
    </GradientStopCollection>  
  </LinearGradientBrush.GradientStops>  
</LinearGradientBrush>  

Należy pamiętać, że nie zawsze można jawnie zadeklarować kolekcję. Na przykład próba zadeklarowania TriggerCollection jawnie w przedstawionym wcześniej przykładzie Triggers zakończy się niepowodzeniem. Jawne deklarowanie kolekcji wymaga, aby klasa kolekcji obsługiwała konstruktor bez parametrów, a TriggerCollection nie ma konstruktora bez parametrów.

Właściwości zawartości XAML

Składnia zawartości XAML jest składnią, która jest włączona tylko w klasach, które określają ContentPropertyAttribute w ramach deklaracji klasy. ContentPropertyAttribute odwołuje się do nazwy właściwości, która jest właściwością zawartości dla tego typu elementu (w tym klas pochodnych). Podczas przetwarzania przez procesor XAML wszystkie elementy podrzędne lub tekst wewnętrzny znalezione między tagami otwierania i zamykania elementu obiektu zostaną przypisane jako wartość właściwości zawartości XAML dla tego obiektu. Można określić jawne elementy właściwości dla właściwości zawartości, ale to użycie nie jest ogólnie wyświetlane w sekcjach składni XAML w dokumentacji platformy .NET. Jawna/szczegółowa technika ma czasami wartość dla jasności znaczników lub jako kwestia stylu znacznikowego, ale zazwyczaj celem właściwości zawartości jest uproszczenie struktury znaczników, tak aby elementy intuicyjnie powiązane jako rodzic-dziecko mogły być zagnieżdżane bezpośrednio. Tagi elementów właściwości dla innych właściwości elementu nie są przypisywane jako "zawartość" dla ścisłej definicji języka XAML; są one przetwarzane wcześniej w kolejności przetwarzania analizatora XAML i nie są uważane za "zawartość".

Wartości właściwości zawartości XAML muszą być ciągłe

Wartość właściwości zawartości XAML musi być podana całkowicie przed lub całkowicie po innych elementach właściwości w tym elemecie obiektu. Jest to prawda, czy wartość właściwości zawartości XAML jest określona jako ciąg, czy jako co najmniej jeden obiekt. Na przykład następujące znaczniki nie mogą być parsowane:

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

Jest to nielegalne, zasadniczo dlatego, że jeśli ta składnia byłaby wyraźnie określona poprzez zastosowanie składni elementu dla właściwości zawartości, wtedy właściwość ta zostałaby ustawiona dwukrotnie.

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

Podobnie nielegalny przykład polega na tym, że właściwość zawartości jest kolekcją, a elementy podrzędne są przeplatane elementami właściwości:

<StackPanel>  
  <Button>This example</Button>  
  <StackPanel.Resources>  
    <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>  
  </StackPanel.Resources>  
  <Button>... is illegal XAML</Button>  
</StackPanel>  

Właściwości zawartości i łączenie składni kolekcji

Aby zaakceptować więcej niż jeden element obiektu jako zawartość, typ właściwości zawartości musi być w szczególności typem kolekcji. Podobnie jak składnia elementu właściwości dla typów kolekcji, procesor XAML musi identyfikować typy, które są typami kolekcji. Jeśli element ma właściwość zawartości XAML, a typ właściwości zawartości XAML jest kolekcją, typ kolekcji implikowanej nie musi być określony w znaczniku jako element obiektu, a właściwość zawartości XAML nie musi być określona jako element właściwości. Dlatego widoczny model zawartości w adiustacji może teraz mieć więcej niż jeden element podrzędny przypisany jako zawartość. Poniżej znajduje się składnia zawartości dla klasy pochodnej Panel. Wszystkie klasy pochodne Panel ustalają właściwość zawartości XAML na Children, która wymaga wartości typu UIElementCollection.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
  <StackPanel>
    <Button>Button 1</Button>
    <Button>Button 2</Button>
    <Button>Button 3</Button>
  </StackPanel>
</Page>

Należy pamiętać, że ani element właściwości dla Children, ani element UIElementCollection nie jest wymagany w adiustacji. Jest to funkcja projektowania języka XAML, dzięki czemu rekurencyjnie zawarte elementy, które definiują interfejs użytkownika, są bardziej intuicyjnie reprezentowane jako drzewo zagnieżdżonych elementów z bezpośrednimi relacjami elementów nadrzędny-podrzędny bez pośrednictwa tagów elementów właściwości lub obiektów kolekcji. W rzeczywistości UIElementCollection nie można jawnie określić w znaczniku jako element obiektu z założenia. Ponieważ jej jedynym zamierzonym zastosowaniem jest kolekcja domyślna, UIElementCollection nie posiada publicznego konstruktora bez parametrów, w związku z czym nie można utworzyć jej instancji jako elementu obiektu.

Mieszanie elementów właściwości i elementów obiektu w obiekcie z właściwością zawartości

Specyfikacja XAML deklaruje, że procesor XAML może wymusić, że elementy obiektów używane do wypełnienia właściwości zawartości XAML w elemmencie obiektu muszą być ciągłe i nie mogą być mieszane. To ograniczenie dotyczące mieszania elementów właściwości i zawartości jest egzekwowane przez procesory XAML WPF.

Element obiektu podrzędnego może być pierwszym bezpośrednim znacznikiem w elemecie object. Następnie można wprowadzić elementy właściwości. Możesz też określić co najmniej jeden element właściwości, a następnie zawartość, a następnie więcej elementów właściwości. Ale gdy element właściwości następuje po zawartości, nie można już dodawać dalszej zawartości, można jedynie dodać elementy właściwości.

To wymaganie kolejności elementów zawartości/właściwości nie ma zastosowania do tekstu wewnętrznego używanego jako zawartość. Jednak nadal jest to dobry styl znaczników, aby zachować ciągły tekst wewnętrzny, ponieważ znaczące białe znaki będą trudne do wykrycia wizualnego w znaczniku, jeśli elementy właściwości są przeplatane tekstem wewnętrznym.

Przestrzenie nazw XAML

Żaden z powyższych przykładów składni nie określił przestrzeni nazw XAML innej niż domyślna przestrzeń nazw XAML. W typowych aplikacjach WPF domyślna przestrzeń nazw XAML jest określona jako przestrzeń nazw WPF. Możesz określić przestrzenie nazw XAML inne niż domyślna przestrzeń nazw XAML i nadal używać podobnej składni. Jednak w dowolnym miejscu, gdzie klasa jest nazwana, a nie jest dostępna w domyślnej przestrzeni nazw XAML, ta nazwa klasy musi być poprzedzona prefiksem przestrzeni nazw XAML przyporządkowanego odpowiadającej jej przestrzeni nazw CLR. Na przykład <custom:Example/> jest składnią elementu obiektu używaną do utworzenia wystąpienia klasy Example, gdzie przestrzeń nazw CLR zawierająca tę klasę (i ewentualnie informacje o zewnętrznym zestawie zawierającym typy podstawowe) została wcześniej przypisana do przedrostka custom.

Aby uzyskać więcej informacji na temat przestrzeni nazw XAML, zobacz przestrzenie nazw XAML i mapowanie przestrzeni nazw dla języka WPF XAML.

Rozszerzenia znaczników

Język XAML definiuje entytet programistyczny rozszerzenia znaczników, który umożliwia obejście standardowego przetwarzania przez procesor XAML dla wartości atrybutów tekstowych lub elementów obiektu, przenosząc przetwarzanie do klasy wspierającej. Znak, który identyfikuje rozszerzenie znaczników dla procesora XAML podczas używania składni atrybutu, to otwierający nawias klamrowy ({), po którym następuje dowolny znak inny niż zamykający nawias klamrowy (}). Pierwszy ciąg po otwierającym nawiasie klamrowym musi odwoływać się do klasy, która zapewnia określone zachowanie rozszerzenia, gdzie odwołanie może pominąć podciąg "Rozszerzenie", jeśli podciąg jest częścią prawdziwej nazwy klasy. Następnie może pojawić się pojedyncza spacja, a potem każdy kolejny znak jest używany jako dane wejściowe przez implementację rozszerzenia, aż do napotkania zamykającego nawiasu klamrowego.

Implementacja XAML platformy .NET używa klasy abstrakcyjnej MarkupExtension jako podstawy dla wszystkich rozszerzeń znaczników obsługiwanych przez WPF, a także innych struktur lub technologii. Rozszerzenia znaczników, które są specjalnie implementowane przez WPF, często mają na celu umożliwienie odwoływania się do innych istniejących obiektów lub tworzenia odroczonych odniesień do obiektów, które zostaną ocenione podczas wykonywania programu. Na przykład proste powiązanie danych WPF jest realizowane przez określenie rozszerzenia znaczników {Binding} zamiast wartości, którą zwykle będzie przyjmować określona właściwość. Wiele rozszerzeń znaczników WPF umożliwia składnię atrybutu dla właściwości, w których składnia atrybutu nie byłaby w przeciwnym razie możliwa. Na przykład obiekt Style jest stosunkowo złożonym typem zawierającym zagnieżdżoną serię obiektów i właściwości. Style w WPF są zwykle definiowane jako zasób w ResourceDictionary, a następnie są przywoływane za pomocą jednego z dwóch rozszerzeń znaczników WPF, które żądają zasobu. Rozszerzenie znaczników odwraca ocenę wartości właściwości do wyszukiwania zasobów i umożliwia podanie wartości właściwości Style, biorąc typ Style, w składni atrybutu, jak w poniższym przykładzie:

<Button Style="{StaticResource MyStyle}">My button</Button>

W tym miejscu StaticResource identyfikuje klasę StaticResourceExtension zapewniającą implementację rozszerzenia znaczników. Następny ciąg MyStyle jest używany jako dane wejściowe dla konstruktora StaticResourceExtension innego niż domyślny, gdzie parametr pobrany z ciągu rozszerzenia deklaruje żądany ResourceKey. Oczekuje się, że MyStyle będzie wartością x:Key zasobu Style. StaticResource Markup Extension określa użycie, że zasób ma być użyty do dostarczenia wartości właściwości Style za pomocą logiki wyszukiwania zasobów statycznych w czasie ładowania.

Aby uzyskać więcej informacji na temat rozszerzeń znaczników, zobacz sekcje Rozszerzenia znaczników iWPF XAML. Aby zapoznać się z dokumentacją rozszerzeń znaczników i innymi funkcjami programowania XAML włączonymi w ogólnej implementacji języka XAML platformy .NET, zobacz Przestrzeń nazw XAML (x:) Funkcje języka. Aby zapoznać się z rozszerzeniami znaczników specyficznych dla platformy WPF, zobacz rozszerzenia XAML WPF.

Dołączone właściwości

Dołączone właściwości to koncepcja programowania wprowadzona w języku XAML, w której właściwości mogą być własnością i definiowane przez określony typ, ale ustawiane jako atrybuty lub elementy właściwości na dowolnym elemenie. Podstawowym scenariuszem, w którym dołączone właściwości są przeznaczone, jest umożliwienie elementom podrzędnym w strukturze znaczników raportowania informacji do elementu nadrzędnego bez konieczności stosowania szeroko współdzielonego modelu obiektowego we wszystkich elementach. Z drugiej strony dołączone właściwości mogą być używane przez elementy nadrzędne do zgłaszania informacji do elementów podrzędnych. Aby uzyskać więcej informacji na temat przeznaczenia dołączonych właściwości i sposobu tworzenia własnych dołączonych właściwości, zobacz Dołączone właściwości — omówienie.

Dołączone właściwości używają składni, która powierzchownie przypomina składnię elementu właściwości, ponieważ również określasz kombinację typeName.propertyName. Istnieją dwie ważne różnice:

  • Możesz użyć typeName.propertyName kombinacji nawet podczas ustawiania dołączonej właściwości za pomocą składni atrybutu. Dołączone właściwości są jedynym przypadkiem, w którym kwalifikowanie nazwy właściwości jest wymaganiem w składni atrybutu.

  • Można również użyć składni elementów właściwości dla przypisanych właściwości. Jednak w przypadku typowej składni dla elementów właściwości, określony typeName jest elementem objektu, który zawiera element właściwości. Jeśli odwołujesz się do dołączonej właściwości, typeName jest klasą, która definiuje dołączoną właściwość, a nie element obiektu zawierającego.

Dołączone zdarzenia

Dołączone zdarzenia to kolejna koncepcja programowania wprowadzona w języku XAML, w której zdarzenia mogą być definiowane przez określony typ, ale programy obsługi mogą być dołączone do dowolnego elementu obiektu. W implementacji WOF często typ definiujący dołączone zdarzenie jest statycznym typem definiującym usługę, a czasami te dołączone zdarzenia są ujawniane przez alias zdarzenia routowanego w typach, które udostępniają usługę. Obsługiwacze dołączonych zdarzeń są określane za pomocą składni atrybutów. Podobnie jak w przypadku dołączonych zdarzeń, składnia atrybutów jest rozszerzana dla dołączonych zdarzeń, aby umożliwić użycie typeName.eventName, gdzie typeName to klasa udostępniająca Add i Remove akcesory obsługi zdarzeń dla infrastruktury dołączonych zdarzeń, a eventName jest nazwą zdarzenia.

Anatomia elementu głównego XAML

W poniższej tabeli przedstawiono typowy element główny XAML podzielony na poszczególne atrybuty elementu głównego:

Atrybut Opis
<Page Otwieranie elementu obiektowego elementu głównego
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Domyślna przestrzeń nazw XAML (WPF)
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Przestrzeń nazw XAML języka XAML
x:Class="ExampleNamespace.ExampleCode" Deklaracja klasy częściowej, która łączy znaczniki z dowolnym kodem-behind zdefiniowanym dla klasy częściowej
> Koniec elementu obiektu dla korzenia. Obiekt nie został jeszcze zamknięty, ponieważ element zawiera elementy podrzędne

Opcjonalne i niezalecane użycie XAML

W poniższych sekcjach opisano użycie XAML, które są technicznie obsługiwane przez procesory XAML, ale generują rozwlekłość lub inne problemy estetyczne, które zakłócają czytelność plików XAML, przy tworzeniu aplikacji zawierających kod XAML.

Opcjonalne użycie elementu właściwości

Opcjonalne użycie elementu właściwości obejmuje jawne zapisywanie właściwości zawartości elementu, które procesor XAML uznaje za niejawne. Na przykład, przy deklarowaniu zawartości Menu, można jawnie określić kolekcję Items dla Menu jako tag elementu właściwości <Menu.Items> i umieścić każdy MenuItem w <Menu.Items>. Zamiast tego, można skorzystać z niejawnego zachowania procesora XAML, który zakłada, że wszystkie elementy podrzędne Menu muszą być MenuItem i są umieszczane w kolekcji Items. Czasami opcjonalne użycia mogą pomóc wizualnie rozjaśnić strukturę obiektów reprezentowaną w znacznikach. Czasami jawne użycie elementu właściwości może zapobiec stosowaniu znaczników, które są technicznie funkcjonalne, ale wizualnie mylące, na przykład zagnieżdżonych rozszerzeń znaczników w ramach wartości atrybutu.

Pełne atrybuty kwalifikowane typu typeName.memberName

typeName.memberName w formie przypisanej do atrybutu działa bardziej uniwersalnie niż tylko w przypadku zdarzenia kierowanego. Ale w innych sytuacjach forma jest zbędna i należy jej unikać, choćby ze względu na styl znaczników i czytelność. W poniższym przykładzie każde z trzech odwołań do atrybutu Background jest całkowicie równoważne:

<Button Background="Blue">Background</Button>
<Button Button.Background="Blue">Button.Background</Button>
<Button Control.Background="Blue">Control.Background</Button>

Button.Background działa, ponieważ kwalifikowane wyszukiwanie tej właściwości w Button kończy się pomyślnie (Background zostało odziedziczone z klasy Control), a Button jest klasą elementu obiektu lub klasą bazową. Control.Background działa, ponieważ klasa Control faktycznie definiuje Background, a Control jest klasą bazową Button.

Jednak następujący typeName.memberName przykład kodu formularza nie działa, a więc jest pokazany w formie skomentowanej.

<!--<Button Label.Background="Blue">Does not work</Button> -->

Label jest inną klasą pochodną Control, a jeśli określono Label.Background w elemecie obiektu Label, to użycie zadziałałoby. Jednak ponieważ Label nie jest klasą ani klasą bazową Button, określone zachowanie procesora XAML polega na przetwarzaniu Label.Background jako dołączonej właściwości. Label.Background nie jest właściwością dołączaną i to użycie kończy się niepowodzeniem.

baseTypeName.memberName — elementy właściwości

Analogicznie do tego, jak składnia typeName.memberName działa dla atrybutów, składnia baseTypeName.memberName działa dla elementów właściwości. Na przykład działa następująca składnia:

<Button>Control.Background PE
  <Control.Background>
    <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
      <GradientStop Color="Yellow" Offset="0.0" />
      <GradientStop Color="LimeGreen" Offset="1.0" />
    </LinearGradientBrush>
    </Control.Background>
</Button>

W tym miejscu element właściwości został podany jako Control.Background, mimo że element właściwości był zawarty w Button.

Ale podobnie jak typeName.memberName w przypadku atrybutów, baseTypeName.memberName to zły styl w oznaczeniu i należy go unikać.

Zobacz też