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. Nazwa target parametru nie jest wymagana, ale jest nazwana zgodnie target 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 GetPropertyNamedostę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.

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ż