Definiowanie typów niestandardowych do użycia z usługami XAML platformy .NET
Podczas definiowania typów niestandardowych, które są obiektami biznesowymi lub typami, które nie mają zależności od określonych struktur, istnieją pewne najlepsze rozwiązania dotyczące języka XAML, które można wykonać. Jeśli zastosujesz się do tych praktyk, usługi XAML platformy .NET i jego czytniki XAML oraz autorzy XAML mogą odnaleźć charakterystykę XAML typu i nadać jej odpowiednią reprezentację w strumieniu węzła XAML przy użyciu systemu typów XAML. W tym temacie opisano najlepsze rozwiązania dotyczące definicji typów, definicji składowych i przypisywanie typów lub składowych CLR.
Wzorce konstruktorów i definicje typów dla języka XAML
Aby utworzyć wystąpienie elementu obiektu w języku XAML, klasa niestandardowa musi spełniać następujące wymagania:
Klasa niestandardowa musi być publiczna i musi uwidocznić bez parametrów publiczny konstruktor. (Zobacz następującą sekcję, aby uzyskać uwagi dotyczące struktur).
Klasa niestandardowa nie może być klasą zagnieżdżonych. Dodatkowa kropka w pełnej nazwie ścieżki sprawia, że podział przestrzeni nazw klasy jest niejednoznaczny i zakłóca działanie innych funkcji XAML, takich jak dołączone właściwości. Jeśli obiekt może zostać utworzony jako element obiektu, utworzony obiekt może wypełnić formularz elementu właściwości dowolnych właściwości, które przyjmują obiekt jako ich typ bazowy.
Nadal można podać wartości obiektów dla typów, które nie spełniają tych kryteriów, jeśli włączysz konwerter wartości. Aby uzyskać więcej informacji, zobacz Type Converters and Markup Extensions for XAML.
Struktur
Struktury są zawsze w stanie tworzyć w języku XAML według definicji ŚRODOWISKA CLR. Dzieje się tak, ponieważ kompilator CLR niejawnie tworzy konstruktor bez parametrów dla struktury. Ten konstruktor inicjuje wszystkie wartości właściwości do ich wartości domyślnych.
W niektórych przypadkach domyślne zachowanie konstrukcji struktury nie jest pożądane. Może to być spowodowane tym, że struktura ma wypełniać wartości i działać koncepcyjnie jako związek. Jako związek zawarte wartości mogą mieć wzajemnie wykluczające się interpretacje, a zatem żadna z jego właściwości nie jest ustawiana. Przykładem takiej struktury słownictwa WPF jest GridLength. Takie struktury powinny implementować konwerter typów, aby wartości można było wyrazić w formie atrybutu przy użyciu konwencji ciągów, które tworzą różne interpretacje lub tryby wartości struktury. Struktura powinna również uwidaczniać podobne zachowanie w przypadku konstruowania kodu za pomocą konstruktora bez parametrów.
Interfejsów
Interfejsy mogą być używane jako podstawowe typy elementów członkowskich. System typów XAML sprawdza listę możliwych do przypisania i oczekuje, że obiekt, który jest podany jako wartość, można przypisać do interfejsu. Nie ma pojęcia, w jaki sposób interfejs musi być prezentowany jako typ XAML, o ile odpowiedni typ możliwy do przypisania obsługuje wymagania dotyczące konstrukcji XAML.
Metody fabryki
Metody fabryki to funkcja XAML 2009. Modyfikują zasadę XAML, że obiekty muszą mieć konstruktory bez parametrów. Metody fabryki nie są udokumentowane w tym artykule. Zobacz x:FactoryMethod, dyrektywa.
Wyliczenia
Wyliczenia mają zachowanie konwersji typu natywnego XAML. Nazwy stałe wyliczenia określone w języku XAML są rozpoznawane względem bazowego typu wyliczenia i zwracają wartość wyliczenia do składnika zapisywania obiektów XAML.
Język XAML obsługuje użycie w stylu flag dla wyliczenia z zastosowanymi FlagsAttribute. Aby uzyskać więcej informacji, zobacz Składnia XAML w szczegółach. (Składnia XAML w szczegółach jest napisana dla odbiorców WPF, ale większość informacji w tym temacie jest odpowiednia dla języka XAML, który nie jest specyficzny dla konkretnej struktury implementowania.
Definicje składowych
Typy mogą definiować składowe dla użycia języka XAML. Istnieje możliwość, aby typy definiowały elementy członkowskie, które mogą być używane przez język XAML, nawet jeśli dany typ nie jest używany do użycia w języku XAML. Jest to możliwe z powodu dziedziczenia CLR. Tak długo, jak jakiś typ, który dziedziczy element członkowski obsługuje użycie XAML jako typ, a element członkowski obsługuje użycie XAML dla jego typu bazowego lub ma dostępną natywną składnię XAML, ten element członkowski jest używany do użycia w języku XAML.
Właściwości
Jeśli zdefiniujesz właściwości jako publiczną właściwość CLR przy użyciu typowych get
CLR i set
wzorców metod dostępu i odpowiedniego języka, system typów XAML może zgłosić właściwość jako element członkowski z odpowiednimi informacjami podanymi dla właściwości XamlMember, takich jak IsReadPublic i IsWritePublic.
Określone właściwości mogą włączyć składnię tekstu, stosując TypeConverterAttribute. Aby uzyskać więcej informacji, zobacz Type Converters and Markup Extensions for XAML.
W przypadku braku składni tekstowej lub natywnej konwersji XAML i braku dalszego pośredniego użycia, takiego jak użycie rozszerzenia znaczników, typ właściwości (TargetType w systemie typów XAML) musi być w stanie zwrócić wystąpienie do modułu zapisywania obiektów XAML, traktując typ docelowy jako typ CLR.
Jeśli używasz języka XAML 2009, x:Reference Markup Extension może służyć do podawania wartości, jeśli poprzednie zagadnienia nie zostały spełnione; jednak jest to bardziej problem z użyciem niż problem z definicją typu.
Zdarzenia
Jeśli zdefiniujesz zdarzenia jako publiczne zdarzenie CLR, system typów XAML może zgłosić zdarzenie jako element członkowski z IsEvent jako true
. Podłączanie programów obsługi zdarzeń nie mieści się w zakresie możliwości usług XAML platformy .NET; Okablowanie pozostaje w określonych strukturach i implementacjach.
Metody
Wbudowany kod dla metod nie jest domyślną funkcją XAML. W większości przypadków nie odwołujesz się bezpośrednio do elementów członkowskich metody z języka XAML, a rola metod w języku XAML polega tylko na zapewnieniu obsługi określonych wzorców XAML. x:FactoryMethod, dyrektywy jest wyjątkiem.
Pola
Wytyczne dotyczące projektowania środowiska CLR zniechęcają do niestatycznych pól. W przypadku pól statycznych można uzyskać dostęp do wartości pól statycznych tylko za pośrednictwem x:Static Markup Extension; w tym przypadku nie wykonujesz żadnych specjalnych czynności w definicji środowiska CLR, aby uwidocznić pole dla x:Statyczne użycie.
Dołączane elementy członkowskie
Dołączane elementy członkowskie są widoczne dla języka XAML za pomocą wzorca metody dostępu w typie definiującym. Sam typ definiujący nie musi być używany jako obiekt XAML. W rzeczywistości typowym wzorcem jest zadeklarowanie klasy usługi, której rolą jest posiadanie dołączonego elementu członkowskiego i zaimplementowanie powiązanych zachowań, ale nie pełni żadnej innej funkcji, takiej jak reprezentacja interfejsu użytkownika. W poniższych sekcjach symbol zastępczy PropertyName reprezentuje nazwę dołączanego elementu członkowskiego. Ta nazwa musi być prawidłowa w XamlName Grammar.
Należy zachować ostrożność w przypadku kolizji nazw między tymi wzorcami a innymi metodami typu. Jeśli element członkowski istnieje, który pasuje do jednego z wzorców, można go interpretować jako ścieżkę użycia dołączanego elementu członkowskiego przez procesor XAML, nawet jeśli nie był to twój zamiar.
Metodę dostępu GetPropertyName
Podpis metody dostępu GetPropertyName
musi być:
public static object GetPropertyName(object target)
Obiekt
target
można określić jako bardziej szczegółowy typ implementacji. Za pomocą tej opcji można określić zakres użycia dołączanego elementu członkowskiego; użycie poza zamierzonym zakresem spowoduje zgłoszenie nieprawidłowych wyjątków rzutowanych, które są następnie wyświetlane przez błąd analizy XAML. Nazwa parametrutarget
nie jest wymagana, ale nosi nazwętarget
zgodnie z konwencją w większości implementacji.Wartość zwracaną można określić jako bardziej konkretny typ w implementacji.
Aby obsługiwać TypeConverter włączoną składnię tekstu na potrzeby użycia atrybutów elementu członkowskiego dołączanego, zastosuj TypeConverterAttribute do metody dostępu GetPropertyName
. Zastosowanie do get
zamiast set
może wydawać się nie intuicyjne; Jednak ta konwencja może obsługiwać koncepcję elementów członkowskich dołączanych tylko do odczytu, które można serializować, co jest przydatne w scenariuszach projektanta.
Metodę dostępu SetPropertyName
Podpis metody dostępu SetPropertyName
musi być:
public static void SetPropertyName(object target, object value)
Obiekt
target
można określić jako bardziej konkretny typ w implementacji, z taką samą logiką i konsekwencjami, jak opisano w poprzedniej sekcji.Obiekt
value
można określić jako bardziej szczegółowy typ implementacji.
Pamiętaj, że wartość tej metody to dane wejściowe pochodzące z użycia XAML, zazwyczaj w postaci atrybutu. Z formularza atrybutu musi istnieć obsługa konwertera wartości dla składni tekstowej, a atrybut na GetPropertyName
akcesorium.
Dołączane magazyny elementów członkowskich
Metody metody dostępu zazwyczaj nie są wystarczające, aby zapewnić metodę umieszczania dołączanych wartości składowych do grafu obiektów lub pobierania wartości z grafu obiektu i ich prawidłowego serializacji. Aby zapewnić tę funkcję, obiekty target
w poprzednich sygnaturach dostępu muszą być w stanie przechowywać wartości. Mechanizm przechowywania powinien być zgodny z zasadą dołączania elementu członkowskiego, że element członkowski jest dołączany do elementów docelowych, w których dołączany element członkowski nie znajduje się na liście członków. Usługi XAML platformy .NET udostępniają technikę implementacji dla dołączanych magazynów składowych za pośrednictwem interfejsów API IAttachedPropertyStore i AttachablePropertyServices.
IAttachedPropertyStore jest używany przez pisarzy XAML do odnajdywania implementacji magazynu i powinien być implementowany na typie, który jest target
akcesoriów. Statyczne interfejsy API AttachablePropertyServices są używane w treści akcesoriów i odwołują się do dołączanego elementu członkowskiego przez jego AttachableMemberIdentifier.
atrybuty środowiska CLR XAML-Related
Prawidłowe przypisywanie typów, składowych i zestawów jest ważne w celu raportowania informacji o systemie typów XAML do usług XAML platformy .NET. Raportowanie informacji o systemie typu XAML jest istotne, jeśli ma zastosowanie jeden z następujących sytuacji:
- Zamierzasz używać typów z systemami XAML, które są bezpośrednio oparte na czytnikach XAML usług .NET XAML i programach zapisywania XAML.
- Definiujesz lub używasz platformy wykorzystującej język XAML, która jest oparta na tych czytnikach XAML i składnikach zapisywania XAML.
Aby uzyskać listę każdego atrybutu powiązanego z XAML, który jest odpowiedni dla obsługi XAML typów niestandardowych, zobacz XAML-Related ATRYBUTy CLR dla typów niestandardowych i bibliotek.
Zwyczaj
Użycie typów niestandardowych wymaga, aby autor znaczników musiał mapować prefiks dla zestawu i przestrzeni nazw CLR, które zawierają typ niestandardowy. Ta procedura nie jest udokumentowana w tym temacie.
Poziom dostępu
Język XAML umożliwia ładowanie i tworzenie wystąpień typów, które mają poziom dostępu internal
. Ta funkcja jest udostępniana tak, aby kod użytkownika mógł definiować własne typy, a następnie utworzyć wystąpienie tych klas z znaczników, który jest również częścią tego samego zakresu kodu użytkownika.
Przykładem Z WPF jest zawsze, gdy kod użytkownika definiuje UserControl, który jest przeznaczony jako sposób refaktoryzacji zachowania interfejsu użytkownika, ale nie jako część dowolnego możliwego mechanizmu rozszerzenia, który może być dorozumiany przez zadeklarowanie klasy pomocniczej przy użyciu poziomu dostępu public
. Taki UserControl można zadeklarować za pomocą internal
dostępu, jeśli kod kopii zapasowej jest kompilowany w tym samym zestawie, z którego jest przywołyny jako typ XAML.
W przypadku aplikacji, która ładuje kod XAML w ramach pełnego zaufania i używa XamlObjectWriter, klasy ładujące z poziomem dostępu internal
są zawsze włączone.
W przypadku aplikacji, która ładuje kod XAML w ramach częściowego zaufania, można kontrolować charakterystykę poziomu dostępu przy użyciu interfejsu API XamlAccessLevel. Ponadto mechanizmy odroczenia (takie jak system szablonów WPF) muszą być w stanie propagować wszelkie uprawnienia na poziomie dostępu i zachowywać je na potrzeby ostatecznej oceny czasu wykonywania; Jest to obsługiwane wewnętrznie przez przekazanie informacji o XamlAccessLevel.
Implementacja WPF
WPF XAML używa modelu dostępu częściowego zaufania, w którym jeśli język BAML jest ładowany w ramach częściowego zaufania, dostęp jest ograniczony do AssemblyAccessTo dla zestawu, który jest źródłem BAML. W przypadku odroczenia WPF używa IXamlObjectWriterFactory.GetParentSettings jako mechanizmu przekazywania informacji o poziomie dostępu.
W terminologii WPF XAML typu wewnętrznego jest typem zdefiniowanym przez ten sam zestaw, który zawiera również odwołanie do XAML. Taki typ można zamapować za pomocą przestrzeni nazw XAML, która celowo pomija zestaw = część mapowania, na przykład xmlns:local="clr-namespace:WPFApplication1"
. Jeśli język BAML odwołuje się do typu wewnętrznego i ten typ ma internal
poziom dostępu, generuje to klasę GeneratedInternalTypeHelper
dla zestawu. Jeśli chcesz uniknąć GeneratedInternalTypeHelper
, musisz użyć public
poziomu dostępu lub należy uwzględnić odpowiednią klasę w osobnym zestawie i ustawić ten zestaw zależny.
Zobacz też
- atrybuty środowiska CLR XAML-Related dla typów niestandardowych i bibliotek
- usług XAML
.NET Desktop feedback