Rozszerzenia znacznikowania i WPF XAML

W tym temacie przedstawiono koncepcję rozszerzeń znaczników dla języka XAML, w tym ich reguły składni, przeznaczenie i model obiektów klasy, który je podsyci. Rozszerzenia znaczników to ogólna funkcja języka XAML i implementacji usług XAML platformy .NET. W tym temacie szczegółowo znaczników rozszerzenia do użycia w WPF XAML.

Procesory XAML i rozszerzenia znaczników

Ogólnie rzecz biorąc, analizator XAML może interpretować wartość atrybutu jako ciąg literału, który można przekonwertować na pierwotny, lub przekonwertować go na obiekt w jakiś sposób. Jednym z takich środków jest odwoływanie się do konwertera typów; Jest to udokumentowane w temacie TypeConverters i XAML. Istnieją jednak scenariusze, w których wymagane jest różne zachowanie. Na przykład procesor XAML może być poinstruowany, że wartość atrybutu nie powinna spowodować nowego obiektu na grafie obiektów. Zamiast tego atrybut powinien spowodować wykres obiektu, który tworzy odwołanie do już skonstruowanego obiektu w innej części grafu lub obiektu statycznego. Innym scenariuszem jest to, że procesor XAML może być poinstruowany, aby użyć składni, która dostarcza argumenty inne niż domyślne do konstruktora obiektu. Są to typy scenariuszy, w których rozszerzenie znaczników może zapewnić rozwiązanie.

Podstawowa składnia rozszerzenia znaczników

Rozszerzenie znaczników można zaimplementować w celu zapewnienia wartości właściwości w użyciu atrybutu, właściwości w użyciu elementu właściwości lub obu tych wartości.

W przypadku podania wartości atrybutu składnia wyróżniająca sekwencję rozszerzenia znaczników do procesora XAML jest obecnością nawiasów klamrowych otwierania i zamykania nawiasów klamrowych ({ i }). Typ rozszerzenia znaczników jest następnie identyfikowany przez token ciągu bezpośrednio po otwarciu nawiasu klamrowego.

W przypadku użycia w składni elementu właściwości rozszerzenie znaczników jest wizualnie takie samo jak każdy inny element używany do podania wartości elementu właściwości: deklaracja elementu XAML, która odwołuje się do klasy rozszerzenia znaczników jako elementu, ujętego w nawiasy kątowe (<>).

Rozszerzenia znaczników zdefiniowane przez język XAML

Istnieje kilka rozszerzeń znaczników, które nie są specyficzne dla implementacji XAML WPF, ale są zamiast implementacji funkcji wewnętrznych lub funkcji XAML jako języka. Te rozszerzenia znaczników są implementowane w zestawie System.Xaml w ramach ogólnych usług XAML programu .NET Framework i znajdują się w przestrzeni nazw XAML języka XAML języka XAML. Jeśli chodzi o typowe użycie znaczników, te rozszerzenia znaczników są zwykle możliwe do zidentyfikowania przez x: prefiks w użyciu. MarkupExtension Klasa bazowa (zdefiniowana również w pliku System.Xaml) udostępnia wzorzec, którego powinny używać wszystkie rozszerzenia znaczników w celu obsługi czytników XAML i składników zapisywania XAML, w tym w języku WPF XAML.

  • x:TypeType dostarcza obiekt dla nazwanego typu. Ta funkcja jest najczęściej używana w stylach i szablonach. Aby uzyskać szczegółowe informacje, zobacz x:Type Markup Extension (Rozszerzenie znaczników x:Type).

  • x:Static tworzy wartości statyczne. Wartości pochodzą z jednostek kodu typu wartości, które nie są bezpośrednio typem wartości właściwości docelowej, ale mogą być oceniane dla tego typu. Aby uzyskać szczegółowe informacje, zobacz x:Static Markup Extension (Rozszerzenie x:Static Markup).

  • x:Null określa null jako wartość właściwości i może być używany dla atrybutów lub wartości elementu właściwości. Aby uzyskać szczegółowe informacje, zobacz x:Null Markup Extension (Rozszerzenie znaczników o wartości null).

  • x:Array Zapewnia obsługę tworzenia ogólnych tablic w składni XAML, w przypadkach, gdy obsługa kolekcji zapewniana przez podstawowe elementy WPF i modele sterowania celowo nie jest używana. Aby uzyskać szczegółowe informacje, zobacz x:Array Markup Extension (Rozszerzenie znaczników x:Array).

Uwaga

Prefiks x: jest używany do typowego mapowania przestrzeni nazw XAML w elementach głównych pliku XAML lub produkcji języka XAML. Na przykład szablony programu Visual Studio dla aplikacji WPF inicjują plik XAML przy użyciu tego x: mapowania. Możesz wybrać inny token prefiksu we własnym mapowaniu przestrzeni nazw XAML, ale w tej dokumentacji przyjęto założenie domyślnego x: mapowania jako środka identyfikacji tych jednostek, które są zdefiniowaną częścią przestrzeni nazw XAML języka XAML dla języka XAML, w przeciwieństwie do domyślnej przestrzeni nazw WPF lub innych przestrzeni nazw XAML, które nie są powiązane z określoną strukturą.

Rozszerzenia znaczników specyficzne dla platformy WPF

Najbardziej typowe rozszerzenia znaczników używane w programowaniu WPF to te, które obsługują odwołania do zasobów (StaticResource i ), oraz DynamicResourcete, które obsługują powiązanie danych (Binding).

  • StaticResource element udostępnia wartość właściwości, podstawiając wartość już zdefiniowanego zasobu. Ocena StaticResource jest ostatecznie wykonana w czasie ładowania XAML i nie ma dostępu do grafu obiektów w czasie wykonywania. Aby uzyskać szczegółowe informacje, zobacz StaticResource Markup Extension (Rozszerzenie znaczników staticResource).

  • DynamicResource Element udostępnia wartość właściwości, odroczając wartość jako odwołanie w czasie wykonywania do zasobu. Dynamiczne odwołanie do zasobów wymusza nowe wyszukiwanie za każdym razem, gdy taki zasób jest uzyskiwany i ma dostęp do grafu obiektów w czasie wykonywania. Aby uzyskać ten dostęp, DynamicResource koncepcja jest obsługiwana przez właściwości zależności w systemie właściwości WPF i obliczone wyrażenia. W związku z tym można używać DynamicResource tylko dla obiektu docelowego właściwości zależności. Aby uzyskać szczegółowe informacje, zobacz DynamicResource Markup Extension (Rozszerzenie znaczników dynamicResource).

  • Binding udostępnia wartość powiązana danych dla właściwości przy użyciu kontekstu danych, który ma zastosowanie do obiektu nadrzędnego w czasie wykonywania. To rozszerzenie znaczników jest stosunkowo złożone, ponieważ umożliwia znaczącą składnię śródliniową określania powiązania danych. Aby uzyskać szczegółowe informacje, zobacz Binding Markup Extension (Powiązanie rozszerzenia znaczników).

  • RelativeSource Zawiera informacje źródłowe dla elementu Binding , które mogą nawigować po kilku możliwych relacjach w drzewie obiektów czasu wykonywania. Zapewnia to wyspecjalizowane określanie źródła powiązań utworzonych w szablonach z wieloma użyciemi lub utworzonych w kodzie bez pełnej wiedzy o otaczającym drzewie obiektów. Aby uzyskać szczegółowe informacje, zobacz RelativeSource MarkupExtension.

  • TemplateBinding Umożliwia szablonowi kontrolki używanie wartości dla właściwości szablonów pochodzących z właściwości zdefiniowanych przez model obiektów klasy, która będzie używać szablonu. Innymi słowy, właściwość w definicji szablonu może uzyskać dostęp do kontekstu, który istnieje tylko po zastosowaniu szablonu. Aby uzyskać szczegółowe informacje, zobacz TemplateBinding Markup Extension (Rozszerzenie znaczników TemplateBinding). Aby uzyskać więcej informacji na temat praktycznego użycia programu TemplateBinding, zobacz Styling with ControlTemplates Sample (Styling with ControlTemplates Sample).

  • ColorConvertedBitmap obsługuje stosunkowo zaawansowany scenariusz tworzenia obrazów. Aby uzyskać szczegółowe informacje, zobacz ColorConvertedBitmap Markup Extension (Rozszerzenie znaczników mapy ColorConvertedBitmap).

  • ComponentResourceKey i ThemeDictionary obsługują aspekty wyszukiwania zasobów, szczególnie w przypadku zasobów i motywów, które są pakowane za pomocą kontrolek niestandardowych. Aby uzyskać więcej informacji, zobacz ComponentResourceKey Markup Extension, ThemeDictionary Markup Extension lub Control Authoring Overview (Omówienie tworzenia kontrolek).

*Klasy rozszerzeń

Zarówno w przypadku ogólnego języka XAML, jak i rozszerzeń znaczników specyficznych dla platformy WPF zachowanie każdego rozszerzenia znaczników jest identyfikowane dla procesora XAML za pośrednictwem *Extension klasy pochodzącej z MarkupExtensionklasy i zapewnia implementację ProvideValue metody . Ta metoda dla każdego rozszerzenia udostępnia obiekt zwracany podczas obliczania rozszerzenia znaczników. Zwrócony obiekt jest zwykle oceniany na podstawie różnych tokenów ciągów przekazywanych do rozszerzenia znaczników.

Na przykład StaticResourceExtension klasa zapewnia implementację powierzchni rzeczywistego wyszukiwania zasobów, dzięki czemu jego ProvideValue implementacja zwraca żądany obiekt, a dane wejściowe tej konkretnej implementacji są ciągiem używanym do wyszukiwania zasobu przez element x:Key. Wiele z tych szczegółów implementacji jest nieważne, jeśli używasz istniejącego rozszerzenia znaczników.

Niektóre rozszerzenia znaczników nie używają argumentów tokenu ciągu. Jest to spowodowane tym, że zwracają wartość statyczną lub spójną albo kontekst dla zwracanej wartości jest dostępny za pośrednictwem jednej z usług przekazywanych przez serviceProvider parametr .

Wzorzec *Extension nazewnictwa jest przeznaczony dla wygody i spójności. Nie jest konieczne, aby procesor XAML zidentyfikował ten klasę jako obsługę rozszerzenia znaczników. Tak długo, jak baza kodu zawiera system.Xaml i używa implementacji usług XAML programu .NET Framework, wszystko, co jest konieczne, aby być rozpoznawane jako rozszerzenie znaczników XAML, to pochodzić z MarkupExtension i obsługiwać składnię konstrukcji. WPF definiuje klasy włączania rozszerzeń znaczników, które nie są zgodne ze wzorcem *Extension nazewnictwa, na przykład Binding. Zazwyczaj przyczyną jest to, że klasa obsługuje scenariusze poza czystą obsługą rozszerzenia znaczników. W przypadku Bindingklasy ta obsługuje dostęp w czasie wykonywania do metod i właściwości obiektu dla scenariuszy, które nie mają nic wspólnego z językiem XAML.

Interpretacja klasy rozszerzenia tekstu inicjowania

Tokeny ciągów po nazwie rozszerzenia znaczników i nadal w nawiasach klamrowych są interpretowane przez procesor XAML w jeden z następujących sposobów:

  • Przecinek zawsze reprezentuje separator lub ogranicznik poszczególnych tokenów.

  • Jeśli oddzielne tokeny nie zawierają żadnych znaków równości, każdy token jest traktowany jako argument konstruktora. Każdy parametr konstruktora musi być podany jako typ oczekiwany przez ten podpis i w odpowiedniej kolejności oczekiwanej przez ten podpis.

    Uwaga

    Procesor XAML musi wywołać konstruktor, który odpowiada liczbie argumentów liczby par. Z tego powodu, jeśli implementujesz rozszerzenie niestandardowego znaczników, nie udostępniaj wielu konstruktorów z tą samą liczbą argumentów. Zachowanie sposobu działania procesora XAML, jeśli istnieje więcej niż jedna ścieżka konstruktora rozszerzenia znaczników o tej samej liczbie parametrów, nie jest zdefiniowana, ale należy przewidzieć, że procesor XAML może zgłosić wyjątek użycia, jeśli ta sytuacja istnieje w definicjach typu rozszerzenia znaczników.

  • Jeśli poszczególne oddzielone tokeny zawierają znaki równości, procesor XAML najpierw wywołuje konstruktor bez parametrów dla rozszerzenia znaczników. Następnie każda para name=value jest interpretowana jako nazwa właściwości, która istnieje w rozszerzeniu znaczników, i wartość do przypisania do tej właściwości.

  • Jeśli istnieje równoległy wynik między zachowaniem konstruktora a zachowaniem ustawienia właściwości w rozszerzeniu znaczników, nie ma znaczenia, które zachowanie jest używane. Częściej używa się par wartości właściwości=dla rozszerzeń znaczników, które mają więcej niż jedną właściwość settable, jeśli tylko dlatego, że adiustacja jest bardziej celowa i jest mniej prawdopodobne, aby przypadkowo transponować parametry konstruktora. (Po określeniu par property=value te właściwości mogą być w dowolnej kolejności). Ponadto nie ma gwarancji, że rozszerzenie znaczników dostarcza parametr konstruktora, który ustawia każdą z jego właściwości ustawianych. Na przykład Binding jest rozszerzeniem znaczników, z wieloma właściwościami, które można ustawić za pośrednictwem rozszerzenia w formularzu wartości właściwości=, ale Binding obsługuje tylko dwa konstruktory: konstruktor bez parametrów i jeden, który ustawia początkową ścieżkę.

  • Nie można przekazać przecinka literału do rozszerzenia znaczników bez ucieczki.

Sekwencje ucieczki i rozszerzenia znaczników

Obsługa atrybutów w procesorze XAML używa nawiasów klamrowych jako wskaźników sekwencji rozszerzenia znaczników. Istnieje również możliwość utworzenia wartości atrybutu znaku nawiasu klamrowego literału w razie potrzeby, wprowadzając sekwencję ucieczki przy użyciu pustej pary nawiasów klamrowych, a następnie literału nawiasu klamrowego. Zobacz {} Sekwencja ucieczki — rozszerzenie znaczników.

Zagnieżdżanie rozszerzeń znaczników w użyciu języka XAML

Zagnieżdżanie wielu rozszerzeń znaczników jest obsługiwane, a każde rozszerzenie znaczników zostanie ocenione jako najgłębiej. Rozważmy na przykład następujące użycie:

<Setter Property="Background"  
  Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />  

W tym użyciu instrukcja jest obliczana x:Static jako pierwsza i zwraca ciąg. Ten ciąg jest następnie używany jako argument dla elementu DynamicResource.

Rozszerzenia znaczników i składnia elementu właściwości

W przypadku użycia jako elementu obiektu, który wypełnia wartość elementu właściwości, klasa rozszerzenia znaczników jest wizualnie nie do odróżnienia od typowego elementu obiektu, który może być używany w języku XAML. Praktyczna różnica między typowym elementem obiektu a rozszerzeniem znaczników polega na tym, że rozszerzenie znaczników jest oceniane na wartość typową lub odroczone jako wyrażenie. W związku z tym mechanizmy wszelkich możliwych błędów typów wartości właściwości dla rozszerzenia znaczników będą różne, podobnie jak w przypadku, gdy właściwość związana z opóźnieniem jest traktowana w innych modelach programowania. Zwykły element obiektu zostanie oceniony pod kątem dopasowania typu do właściwości docelowej, która jest ustawiana podczas analizowania kodu XAML.

Większość rozszerzeń znaczników, używanych w składni elementu obiektu do wypełniania elementu właściwości, nie ma zawartości ani żadnej dalszej składni elementu właściwości. W ten sposób można zamknąć tag elementu obiektu i zapewnić brak elementów podrzędnych. Za każdym razem, gdy dowolny element obiektu jest napotkany przez procesor XAML, konstruktor dla tej klasy jest wywoływany, który tworzy wystąpienie obiektu utworzonego na podstawie przeanalizowanego elementu. Klasa rozszerzenia znaczników nie różni się: jeśli rozszerzenie znaczników ma być używane w składni elementu obiektu, musisz podać konstruktor bez parametrów. Niektóre istniejące rozszerzenia znaczników mają co najmniej jedną wymaganą wartość właściwości, która musi zostać określona do efektywnego inicjowania. Jeśli tak, ta wartość właściwości jest zwykle podawana jako atrybut właściwości w elemecie object. W przestrzeń nazw XAML (x:) Funkcje językowe i strony referencyjne rozszerzeń XAML WPF, rozszerzenia znaczników, które mają wymagane właściwości (i nazwy wymaganych właściwości) zostaną zanotowany. Strony referencyjne będą również zwracać uwagę, jeśli składnia elementu obiektu lub składnia atrybutu jest niedozwolona dla określonych rozszerzeń znaczników. Godny uwagi przypadek to x:Array Markup Extension, które nie może obsługiwać składni atrybutów, ponieważ zawartość tej tablicy musi być określona w tagowaniu jako zawartość. Zawartość tablicy jest obsługiwana jako obiekty ogólne, dlatego nie można wykonać domyślnego konwertera typów dla atrybutu. Ponadto rozszerzenie x:Array Markup wymaga parametrutype.

Zobacz też