Rozszerzenia znacznikowania i WPF XAML

W tym temacie wprowadzono koncepcję rozszerzeń znaczników dla języka XAML, w tym reguły składni, przeznaczenie i model obiektu klasy, który je ułoni. Rozszerzenia znaczników są ogólną funkcją języka XAML i implementacji usług XAML na platformie .NET. W tym temacie szczegółowo o szczegółowe informacje o rozszerzeniach znaczników do użycia w WPF XAML.

Procesory XAML i rozszerzenia znaczników

Ogólnie rzecz biorąc, parser XAML może albo zinterpretować wartość atrybutu jako ciąg literału, który można przekonwertować na typ pierwotny, albo przekonwertować ją na obiekt w jakiś sposób. Jednym z takich sposobów jest odwołanie się do konwertera typu; Jest to udokumentowane w temacie TypeConverters i XAML. Istnieją jednak scenariusze, w których wymagane jest inne zachowanie. Na przykład procesor XAML może zostać poinstruowany, że wartość atrybutu nie powinna powodować nowego obiektu w grafie obiektów. Zamiast tego atrybut powinien spowodować powstanie wykresu obiektu, który tworzy odwołanie do już skonstruowanego obiektu w innej części grafu lub obiektu statycznego. Innym scenariuszem jest to, że procesora XAML można poinstruować, aby użyć składni, która dostarcza argumenty inne niż domyślne konstruktora obiektu. Są to typy scenariuszy, w których rozszerzenie znaczników może udostępnić 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 elementów.

W przypadku podania wartości atrybutu składnią odróżniającą sekwencję rozszerzenia znaczników od procesora XAML jest obecność otwierających i zamykających nawiasów klamrowych ({ i }). Typ rozszerzenia znaczników jest następnie identyfikowany przez token ciągu bezpośrednio po otwierającym nawiasie klamrowym.

Gdy jest używane w składni elementu właściwości, rozszerzenie znaczników jest wizualnie takie samo jak każdy inny element używany do zapewnienia 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 (<>).

XAML-Defined rozszerzenia znaczników

Istnieje kilka rozszerzeń znaczników, które nie są specyficzne dla implementacji języka XAML WPF, ale zamiast tego są implementacjami funkcji wewnętrznych lub funkcji XAML jako języka. Te rozszerzenia znaczników są implementowane w zestawie System.Xaml jako część ogólnej .NET Framework XAML i znajdują się w przestrzeni nazw XAML języka XAML. Jeśli chodzi o typowe użycie znaczników, te rozszerzenia znaczników są zwykle identyfikowane przez x: prefiks w użyciu. Klasa bazowa (zdefiniowana również w Pliku System.Xaml) zawiera wzorzec, który powinien być obsługiwany przez wszystkie rozszerzenia znaczników, aby można było go używać w czytnikach XAML i na autorzy kodu XAML, w tym w MarkupExtension języku WPF XAML.

Uwaga

Prefiks jest używany do typowego mapowania przestrzeni nazw XAML wewnętrznych języka XAML w elemencie głównym pliku x: XAML lub produkcji. Na przykład szablony Visual Studio 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, że mapowanie domyślne jest sposobem identyfikowania jednostek, które są zdefiniowaną częścią przestrzeni nazw 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ą x: platformą.

WPF-Specific rozszerzenia znaczników

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

  • StaticResource Dostarcza wartość właściwości przez podsieć wartość już zdefiniowanego zasobu. Ocena jest ostatecznie oceniana w czasie ładowania kodu XAML i nie ma dostępu do StaticResource grafu obiektów w czasie działania. Aby uzyskać szczegółowe informacje, zobacz StaticResource Markup Extension (Rozszerzenie znaczników StaticResource).

  • DynamicResource Dostarcza wartość właściwości przez odroczenie tej wartości jako odwołania w czasie uruchamiania do zasobu. Dynamiczne odwołanie do zasobu wymusza nowe odnośniki za każdym razem, gdy taki zasób jest dostępny i ma dostęp do grafu obiektów w czasie działania. Aby uzyskać ten dostęp, koncepcja jest obsługiwana przez właściwości zależności w systemie właściwości DynamicResource WPF i wyrażenia oceniane. W związku z tym można używać tylko DynamicResource dla obiektu docelowego właściwości zależności. Aby uzyskać szczegółowe informacje, zobacz DynamicResource Markup Extension (Rozszerzenie znaczników DynamicResource).

  • Binding dostarcza wartość powiązaną z danymi dla właściwości przy użyciu kontekstu danych, który ma zastosowanie do obiektu nadrzędnego w czasie uruchamiania. To rozszerzenie znaczników jest stosunkowo złożone, ponieważ umożliwia znaczącą składnię w tekście umożliwiającą określenie powiązania danych. Aby uzyskać szczegółowe informacje, zobacz Binding Markup Extension (Rozszerzenie znaczników powiązania).

  • RelativeSource Zawiera informacje o źródle dla obiektu , które Binding mogą nawigować po kilku możliwych relacjach w drzewie obiektów czasu uruchomienia. Zapewnia to wyspecjalizowane źródło powiązań, które są tworzone w szablonach wielokrotnego użytku lub tworzone w kodzie bez pełnej znajomości otaczającego drzewa obiektów. Aby uzyskać szczegółowe informacje, zobacz RelativeSource MarkupExtension.

  • TemplateBinding Umożliwia szablonowi kontrolki używanie wartości dla właściwości szablonu, które pochodzą 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 funkcji TemplateBinding , zobacz Style with ControlTemplates Sample (Style za pomocą przykładu ControlTemplates).

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

  • ComponentResourceKey Elementy ThemeDictionary i obsługują aspekty wyszukiwania zasobów, szczególnie w przypadku zasobów i motywów, które są spakowane z kontrolkami niestandardowymi. Aby uzyskać więcej informacji, zobacz ComponentResourceKey Markup Extension, ThemeDictionary Markup Extensionlub 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 WPF zachowanie każdego rozszerzenia znaczników jest identyfikowane dla procesora XAML za pośrednictwem klasy pochodzącej od klasy i udostępnia implementację *Extension MarkupExtension metody ProvideValue . Ta metoda dla każdego rozszerzenia udostępnia obiekt, który jest zwracany podczas obliczania rozszerzenia znaczników. Zwracany obiekt jest zwykle oceniany na podstawie różnych tokenów ciągów, które są przekazywane do rozszerzenia znaczników.

Na przykład klasa udostępnia implementację powierzchni rzeczywistego wyszukiwania zasobów, tak aby jej implementacja zwracała żądany obiekt , a dane wejściowe tej konkretnej implementacji były ciągiem używanym do wyszukiwania zasobu przez jego StaticResourceExtension ProvideValue x:Key klasę . Większość tych szczegółów implementacji jest nieistotna, jeśli używasz istniejącego rozszerzenia znaczników.

Niektóre rozszerzenia znaczników nie używają argumentów tokenu ciągu. Wynika to z tego, że zwracają statyczną lub spójną wartość lub ponieważ kontekst dla wartości, która powinna zostać zwrócona, jest dostępny za pośrednictwem jednej z usług przekazanych za pośrednictwem serviceProvider parametru .

Wzorzec *Extension nazewnictwa jest dla wygody i spójności. Procesor XAML nie musi identyfikować tej klasy jako obsługi rozszerzenia znaczników. Tak długo, jak baza kodu zawiera system.xaml i używa implementacji usług XAML w języku .NET Framework, wystarczy, że zostanie rozpoznana jako rozszerzenie znaczników XAML, wyprowadzenie z i w celu obsługi składni MarkupExtension konstrukcji. WPF definiuje klasy umożliwiające rozszerzenie znaczników, które nie są zgodne ze wzorcem *Extension nazewnictwa, na przykład Binding . Zazwyczaj przyczyną jest to, że klasa obsługuje scenariusze wykraczające poza czyste wsparcie rozszerzenia znaczników. W przypadku klasy ta klasa obsługuje dostęp w czasie działania do metod i właściwości obiektu w scenariuszach, które nie mają nic wspólnego Binding z xaml.

Interpretacja tekstu inicjalizacji w klasie rozszerzenia

Tokeny ciągów następujące 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 poszczególne rozdzielone 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 w przypadku implementowania niestandardowego rozszerzenia znaczników nie należy dostarczać wielu konstruktorów z taką samą liczbę argumentów. Zachowanie procesora XAML w przypadku, gdy istnieje więcej niż jedna ścieżka konstruktora rozszerzenia znaczników o tej samej liczniku parametrów nie jest zdefiniowana, ale należy oczekiwać, że procesor XAML może zgłosić wyjątek użycia, jeśli taka sytuacja występuje w definicjach typów rozszerzeń znaczników.

  • Jeśli oddzielne tokeny zawierają znaki równości, procesor XAML najpierw wywołuje bezparametrowy konstruktor 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 i zachowaniem ustawienia właściwości w rozszerzeniu znaczników, nie ma znaczenia, którego zachowania używasz. Częściej używa się par wartości właściwości dla rozszerzeń znaczników, które mają więcej niż jedną ustawianą właściwość, jeśli tylko dlatego, że sprawia to, że znacznik jest bardziej zamierzony i istnieje mniejsze prawdopodobieństwo przypadkowej transponowania parametrów = konstruktora. (Po określeniu par właściwość =wartość 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 właściwości, które można ustawić. Na przykład jest rozszerzeniem znaczników z wieloma właściwościami, które można ustawić za pomocą rozszerzenia w postaci wartości właściwości, ale obsługuje tylko dwa konstruktory: konstruktor bez parametrów i jeden, który ustawia ścieżkę Binding = Binding początkową.

  • Przecinek literału nie może być przekazywany do rozszerzenia znaczników bez znaku 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. W razie potrzeby można również utworzyć wartość atrybutu znaku literału nawiasu klamrowego, wprowadzając sekwencję ucieczki przy użyciu pustej pary nawiasów klamrowych, po której następuje literałowy nawias klamrowy. Zobacz {} Sekwencja unikowa — rozszerzenie znaczników.

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

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

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

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

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

W przypadku zastosowania jako elementu obiektu, który wypełnia wartość elementu właściwości, klasa rozszerzenia znaczników jest wizualnie nie do odzywania się od typowego elementu obiektu, który może być używany w języku XAML. Praktyczną różnicą między typowym elementem obiektu a rozszerzeniem znaczników jest to, że rozszerzenie znaczników jest oceniane jako wartość typowa 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ą się różnić, podobnie jak właściwość z późnym wiązaniem w innych modelach programowania. Zwykły element obiektu będzie oceniany pod względem dopasowania typu do właściwości docelowej, która jest ustawiana podczas analizowania kodu XAML.

Większość rozszerzeń znaczników, gdy są używane w składni elementu obiektu do wypełnienia elementu właściwości, nie ma zawartości ani żadnej dalszej składni elementu właściwości. W związku z tym należy zamknąć tag elementu obiektu i nie podać żadnych elementów podrzędnych. Za każdym razem, gdy dowolny element obiektu zostanie napotkany przez procesor XAML, wywoływany jest konstruktor dla tej klasy, który tworzy wystąpienia obiektu utworzonego na podstawie analizowanych elementów. Klasa rozszerzenia znaczników nie różni się: jeśli chcesz, aby rozszerzenie znaczników było użyteczne 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 na potrzeby efektywnego inicjowania. Jeśli tak, ta wartość właściwości jest zwykle przypisywana jako atrybut właściwości w elemencie obiektu. W przestrzeni nazw XAML (x:) Zostaną zanotowe strony referencyjne funkcji języka i rozszerzeń XAML WPF, rozszerzenia znaczników, które mają wymagane właściwości (i nazwy wymaganych właściwości). Strony referencyjne będą również zanotować, czy składnia elementu obiektu lub składnia atrybutów jest niedozwolone w przypadku określonych rozszerzeń znaczników. Warto zaznaczyć, że jest to rozszerzenie znaczników x:Array,które nie obsługuje składni atrybutów, ponieważ zawartość tej tablicy musi być określona w tagowaniu jako zawartość. Zawartość tablicy jest przetwarzana jako obiekty ogólne, dlatego nie można uzyskać domyślnego konwertera typów dla atrybutu. Ponadto rozszerzenie znaczników x:Array wymaga type parametru .

Zobacz też