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 (Konwertery typów i rozszerzenia znaczników dla języka XAML).
Struktury
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.
Interfejsy
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 wyliczeń zastosowanych 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 określonej 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 wzorców CLR get
i metod dostępu oraz set
odpowiedniego języka słowa kluczowego, system typów XAML może zgłosić właściwość jako element członkowski z odpowiednimi informacjami podanymi dla XamlMember właściwości, takich jak IsReadPublic i IsWritePublic.
Określone właściwości mogą włączyć składnię tekstu, stosując polecenie TypeConverterAttribute. Aby uzyskać więcej informacji, zobacz Type Converters and Markup Extensions for XAML (Konwertery typów i rozszerzenia znaczników dla języka XAML).
W przypadku braku składni tekstu 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, rozszerzenie 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 problem z użyciem bardziej niż problem z definicją typu.
Wydarzenia
Jeśli zdefiniujesz zdarzenia jako publiczne zdarzenie CLR, system typów XAML może zgłosić zdarzenie jako element członkowski z wartością IsEventtrue
. 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, dyrektywa 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 rozszerzenia x:Static Markup. W tym przypadku nie wykonujesz żadnych specjalnych czynności w definicji CLR, aby uwidocznić pole dla wartości x:Static usages.
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 gramatyce XamlName.
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 GetPropertyName
dostępu musi być:
public static object GetPropertyName(object target)
Obiekt
target
można określić jako bardziej konkretny typ w 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. Nazwatarget
parametru nie jest wymagana, ale jest nazwana zgodnietarget
z konwencją w większości implementacji.Wartość zwracaną można określić jako bardziej konkretny typ w implementacji.
Aby obsługiwać włączoną składnię TypeConverter tekstu dla użycia atrybutów dołączanego elementu członkowskiego, zastosuj TypeConverterAttribute do GetPropertyName
metody dostępu. Zastosowanie do get
elementu zamiast set
elementu 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 SetPropertyName
dostępu 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 konkretny typ w 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 metodzie GetPropertyName
dostępu.
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ę, target
obiekty 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 IAttachedPropertyStore API i AttachablePropertyServices. IAttachedPropertyStore jest używany przez składniki zapisywania XAML do odnajdywania implementacji magazynu i powinien być zaimplementowany na typie, który jest target
akcesorami. Statyczne AttachablePropertyServices interfejsy API są używane w treści akcesoriów i odwołują się do dołączanego elementu członkowskiego przez element AttachableMemberIdentifier.
Atrybuty CLR związane z XAML
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 Atrybuty CLR związane z XAML dla typów niestandardowych i bibliotek.
Użycie
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ą internal
poziom dostępu. 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ład 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ęść jakiegokolwiek możliwego mechanizmu rozszerzenia, który może być dorozumiany przez zadeklarowanie klasy pomocniczej z public
poziomem dostępu. Taki element UserControl można zadeklarować przy użyciu 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 XamlObjectWritermetody , klasy ładujące z internal
poziomem dostępu 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 XamlAccessLevel API. 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 XamlAccessLevel informacji.
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 zestawu, który jest źródłem BAML. W przypadku odroczenia platforma WPF używa IXamlObjectWriterFactory.GetParentSettings jako mechanizmu przekazywania informacji o poziomie dostępu.
W terminologii WPF XAML typ wewnętrzny 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 klasa BAML odwołuje się do typu wewnętrznego i ten typ ma internal
poziom dostępu, spowoduje to wygenerowanie GeneratedInternalTypeHelper
klasy 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ż
.NET Desktop feedback