TypeConverters i XAML

W tym temacie przedstawiono przeznaczenie konwersji typu z ciągu jako ogólną funkcję języka XAML. W programie .NET Framework klasa pełni określony cel w ramach implementacji zarządzanej klasy niestandardowej, TypeConverter która może być używana jako wartość właściwości w użyciu atrybutów XAML. Jeśli napiszesz klasę niestandardową i chcesz, aby wystąpienia klasy mogły być używane jako wartości atrybutów zestawu XAML, może być konieczne zastosowanie TypeConverterAttribute klasy do klasy, napisanie klasy niestandardowej TypeConverter lub obu tych klas.

Pojęcia dotyczące konwersji typów

XAML i wartości ciągu

Po ustawieniu wartości atrybutu w pliku XAML początkowy typ tej wartości jest ciągiem w czystym tekście. Nawet inne elementy pierwotne, takie jak Double , są początkowo ciągami tekstowymi do procesora XAML.

Procesor XAML potrzebuje dwóch informacji w celu przetworzenia wartości atrybutu. Pierwszy element informacji jest typem wartości właściwości, która jest ustawiana. Każdy ciąg, który definiuje wartość atrybutu i który jest przetwarzany w języku XAML, musi zostać ostatecznie przekonwertowany lub rozpoznany na wartość tego typu. Jeśli wartość jest elementem pierwotnym zrozumiałym dla analizatora XAML (na przykład wartością liczbową), podejmowana jest bezpośrednia konwersja ciągu. Jeśli wartość jest wyliczeniem, ciąg jest używany do sprawdzania dopasowania nazwy do nazwanej stałej w tym wyliczenie. Jeśli wartość nie jest ani zrozumiałym elementem pierwotnym, ani wyliczeniem, typ, o których mowa, musi być w stanie podać wystąpienie typu lub wartość na podstawie przekonwertowanego ciągu. Odbywa się to przez wskazanie klasy konwertera typów. Konwerter typów jest skutecznie klasą pomocnika do dostarczania wartości innej klasy, zarówno dla scenariusza XAML, jak i potencjalnie dla wywołań kodu w kodzie platformy .NET.

Używanie istniejącego zachowania konwersji typów w języku XAML

W zależności od znajomości podstawowych pojęć XAML możesz już używać zachowania konwersji typów w podstawowej aplikacji XAML bez jego zrozumienia. Na przykład WPF definiuje dosłownie setki właściwości, które przyjmują wartość typu Point. A Point to wartość, która opisuje współrzędną w dwuwymiarowej przestrzeni współrzędnej, a naprawdę ma tylko dwie ważne właściwości: X i Y. Po określeniu punktu w języku XAML należy określić go jako ciąg z ogranicznikiem (zazwyczaj przecinkiem) między X podanymi wartościami i Y . Na przykład: <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"/>.

Nawet ten prosty typ Point i jego proste użycie w XAML obejmują konwerter typów. W tym przypadku jest to klasa PointConverter.

Konwerter typów zdefiniowany na Point poziomie klasy usprawnia użycie znaczników wszystkich właściwości, które przyjmują wartość Point. Bez konwertera typów w tym miejscu potrzebne byłoby znacznie więcej pełnych znaczników dla tego samego przykładu pokazanego wcześniej:

<LinearGradientBrush>
  <LinearGradientBrush.StartPoint>
    <Point X="0" Y="0"/>
  </LinearGradientBrush.StartPoint>
  <LinearGradientBrush.EndPoint>
    <Point X="1" Y="1"/>
  </LinearGradientBrush.EndPoint>
</LinearGradientBrush>

Niezależnie od tego, czy używać ciągu konwersji typu, czy bardziej pełnej składni równoważnej, jest zazwyczaj wyborem stylu kodowania. Przepływ pracy narzędzi XAML może również wpływać na sposób ustawiania wartości. Niektóre narzędzia XAML mają tendencję do emitowania najbardziej pełnej formy znaczników, ponieważ łatwiej jest zaokrąglić widoki projektanta lub własny mechanizm serializacji.

Istniejące konwertery typów można zwykle odnaleźć w typach WPF i .NET Framework, sprawdzając klasę (lub właściwość) pod kątem obecności zastosowanego TypeConverterAttributeelementu . Ten atrybut będzie nazwać klasę, która jest konwerterem typów pomocniczych dla wartości tego typu, w celach XAML, a także potencjalnie innych celów.

Konwertery typów i rozszerzenia znaczników

Rozszerzenia znaczników i konwertery typów wypełniają role ortogonalne pod względem zachowania procesora XAML i scenariuszy, do których są one stosowane. Chociaż kontekst jest dostępny w przypadku użycia rozszerzeń znaczników, zachowanie konwersji typów właściwości, w których rozszerzenie znaczników zapewnia wartość, zazwyczaj nie jest sprawdzane w implementacjach rozszerzeń znaczników. Innymi słowy, nawet jeśli rozszerzenie znaczników zwraca ciąg tekstowy jako jego ProvideValue dane wyjściowe, zachowanie konwersji typów w tym ciągu zastosowane do określonej właściwości lub typu wartości właściwości nie jest wywoływane, ogólnie rzecz biorąc, celem rozszerzenia znaczników jest przetworzenie ciągu i zwrócenie obiektu bez żadnego konwertera typów.

Jedną z typowych sytuacji, w których rozszerzenie znaczników jest konieczne, a nie konwerter typów, jest utworzenie odwołania do obiektu, który już istnieje. W najlepszym razie konwerter typów bezstanowych może wygenerować tylko nowe wystąpienie, co może nie być pożądane. Aby uzyskać więcej informacji na temat rozszerzeń znaczników, zobacz Rozszerzenia znaczników i WPF XAML.

Konwertery typów natywnych

W implementacji analizatora XAML WPF i .NET Framework istnieją pewne typy, które mają natywną obsługę konwersji typów, ale nie są typami, które mogą być tradycyjnie uważane za pierwotne. Przykładem takiego typu jest DateTime. Przyczyną tego jest sposób działania architektury programu .NET Framework: typ DateTime jest zdefiniowany w bibliotece mscorlib, czyli najbardziej podstawowej biblioteki na platformie .NET. DateTime nie może być przypisywany atrybutowi pochodzącemu z innego zestawu, który wprowadza zależność (TypeConverterAttribute jest z systemu), więc nie można obsługiwać zwykłego mechanizmu odnajdywania konwertera typów przez przypisywanie. Zamiast tego analizator XAML zawiera listę typów, które wymagają takiego natywnego przetwarzania i przetwarza je podobnie do sposobu przetwarzania prawdziwych elementów pierwotnych. (W takim przypadku DateTime obejmuje wywołanie metody Parse.)

Implementowanie konwertera typów

TypeConverter

W przykładzie podanym Point wcześniej została wymieniona klasa PointConverter . W przypadku implementacji XAML platformy .NET wszystkie konwertery typów używane do celów XAML to klasy pochodzące z klasy TypeConverterbazowej . Klasa TypeConverter istniała w wersjach programu .NET Framework, które poprzedzały istnienie języka XAML. Jednym z jego oryginalnych użycia było zapewnienie konwersji ciągu dla okien dialogowych właściwości w projektantach wizualizacji. W przypadku języka XAML rola TypeConverter jest rozszerzana tak, aby zawierała klasę bazową dla konwersji typu "ciąg" i "od ciągu", które umożliwiają analizowanie wartości atrybutu ciągu i ewentualnie przetwarzanie wartości czasu wykonywania określonej właściwości obiektu z powrotem do ciągu do serializacji jako atrybutu.

TypeConverter definiuje cztery elementy członkowskie, które są istotne do konwersji na ciągi i z ciągów na potrzeby przetwarzania XAML:

Z tych elementów najważniejszą metodą jest ConvertFrom. Ta metoda konwertuje ciąg wejściowy na wymagany typ obiektu. Mówiąc ściśle, ConvertFrom można zaimplementować metodę, aby przekonwertować znacznie szerszy zakres typów na zamierzony typ docelowy konwertera, a tym samym służyć do celów wykraczających poza język XAML, takich jak obsługa konwersji czasu wykonywania, ale w celach XAML jest to tylko ścieżka kodu, która może przetwarzać String dane wejściowe, które mają znaczenie.

Następną najważniejszą metodą jest ConvertTo. Jeśli aplikacja jest konwertowana na reprezentację znaczników (na przykład jeśli jest zapisywana w języku XAML jako plik), ConvertTo jest odpowiedzialna za tworzenie reprezentacji znaczników. W takim przypadku ścieżka kodu, która ma znaczenie dla języka XAML, to po przekazaniu elementu destinationTypeString .

CanConvertTo i CanConvertFrom są obsługiwane metody, które są używane, gdy usługa wykonuje zapytanie o możliwości implementacji TypeConverter . Należy zaimplementować te metody, aby wrócić true do przypadków specyficznych dla typu, które są obsługiwane przez równoważne metody konwersji konwertera. W celach XAML zazwyczaj oznacza String to typ.

Konwertery informacji o kulturze i typów dla języka XAML

Każda implementacja TypeConverter może mieć własną interpretację tego, co stanowi prawidłowy ciąg konwersji, a także może użyć lub zignorować opis typu przekazany jako parametry. W odniesieniu do kultury i konwersji typów XAML należy wziąć pod uwagę ważne kwestie. Używanie ciągów lokalizowalnych jako wartości atrybutów jest całkowicie obsługiwane przez język XAML. Jednak użycie tego lokalizowalnego ciągu jako danych wejściowych konwertera typów z określonymi wymaganiami kultury nie jest obsługiwane, ponieważ konwertery typów dla wartości atrybutów XAML obejmują zachowanie analizy w języku stałym, używając en-US kultury. Aby uzyskać więcej informacji na temat przyczyn projektowania tego ograniczenia, należy zapoznać się ze specyfikacją języka XAML ([MS-XAML].

Jako przykład, w którym kultura może być problemem, niektóre kultury używają przecinka jako ogranicznika separatora dziesiętnego dla liczb. Spowoduje to kolidowanie z zachowaniem, które mają wiele konwerterów typów WPF XAML, czyli użycie przecinka jako ogranicznika (na podstawie historycznych precedensów, takich jak wspólny formularz X,Y lub rozdzielane przecinkami listy). Nawet przekazanie kultury w otaczającym języku XAML (ustawienie Language lub xml:langsl-SI kulturę, przykład kultury używającej przecinka dla przecinka w ten sposób) nie rozwiązuje problemu.

Implementowanie konwersji Z

Aby można było używać go jako implementacji obsługującej TypeConverter język XAML, ConvertFrom metoda tego konwertera musi zaakceptować ciąg jako value parametr. Jeśli ciąg był prawidłowym formatem i może zostać przekonwertowany przez implementację TypeConverter , zwracany obiekt musi obsługiwać rzutowanie do typu oczekiwanego przez właściwość . W przeciwnym razie implementacja ConvertFrom musi zwrócić wartość null.

Każda implementacja TypeConverter może mieć własną interpretację tego, co stanowi prawidłowy ciąg konwersji, a także może użyć lub zignorować opis typu lub konteksty kultury przekazane jako parametry. Jednak przetwarzanie WPF XAML może nie przekazywać wartości do kontekstu opisu typu we wszystkich przypadkach, a także może nie przekazywać kultury na xml:langpodstawie .

Uwaga

Nie używaj znaków nawiasu klamrowego, szczególnie {, jako możliwego elementu formatu ciągu. Te znaki są zastrzeżone jako wpis i wyjście dla sekwencji rozszerzenia znaczników.

Implementowanie narzędzia ConvertTo

ConvertTo jest potencjalnie używany do obsługi serializacji. Obsługa serializacji za pośrednictwem ConvertTo dla typu niestandardowego i konwertera typów nie jest absolutnym wymaganiem. Jeśli jednak implementujesz kontrolkę lub używasz serializacji w ramach funkcji lub projektu klasy, należy zaimplementować element ConvertTo.

Aby można było używać go jako implementacji obsługującej TypeConverter język XAML, ConvertTo metoda tego konwertera musi zaakceptować wystąpienie typu (lub wartości) obsługiwane jako value parametr. Gdy parametr jest typem destinationTypeString, zwracany obiekt musi być w stanie rzutować jako String. Zwrócony ciąg musi reprezentować serializowaną wartość value. Najlepiej, aby wybrany format serializacji mógł wygenerować tę samą wartość, jeśli ciąg został przekazany do ConvertFrom implementacji tego samego konwertera, bez znacznej utraty informacji.

Jeśli nie można serializować wartości lub konwerter nie obsługuje serializacji, ConvertTo implementacja musi zwrócić nullwartość i może zgłosić wyjątek w tym przypadku. Jeśli jednak zgłaszasz wyjątki, należy zgłosić niezdolność do używania tej konwersji w ramach CanConvertTo implementacji, aby najlepsze rozwiązanie w zakresie sprawdzania CanConvertTo z pierwszymi, aby uniknąć wyjątków, jest obsługiwane.

Jeśli destinationType parametr nie jest typu String, możesz wybrać własną obsługę konwertera. Zazwyczaj należy przywrócić podstawową obsługę implementacji, która w najbardziej ConvertTo podstawowym przypadku zgłasza określony wyjątek.

Implementowanie elementu CanConvertTo

Implementacja CanConvertTo powinna zostać zwrócona true dla destinationType typu String, a w przeciwnym razie odroczyć implementację podstawową.

Implementowanie elementu CanConvertFrom

Implementacja CanConvertFrom powinna zostać zwrócona true dla sourceType typu String, a w przeciwnym razie odroczyć implementację podstawową.

Stosowanie atrybutu TypeConverterAttribute

Aby konwerter typów niestandardowych był używany jako konwerter typów działających dla klasy niestandardowej przez procesor XAML, należy zastosować element TypeConverterAttribute do definicji klasy. Określony ConverterTypeName za pomocą atrybutu musi być nazwą typu konwertera typów niestandardowych. Po zastosowaniu tego atrybutu, gdy procesor XAML obsługuje wartości, w których typ właściwości używa niestandardowego typu klasy, może wprowadzać ciągi i zwracać wystąpienia obiektów.

Można również podać konwerter typów na podstawie właściwości. Zamiast stosować TypeConverterAttribute element do definicji klasy, zastosuj ją do definicji właściwości (głównej definicji, a nie get/set implementacji w niej). Typ właściwości musi być zgodny z typem przetwarzanym przez konwerter typów niestandardowych. Po zastosowaniu tego atrybutu, gdy procesor XAML obsługuje wartości tej właściwości, może przetwarzać ciągi wejściowe i zwracać wystąpienia obiektów. Technika konwertera typów właściwości jest szczególnie przydatna, jeśli zdecydujesz się użyć typu właściwości z programu Microsoft .NET Framework lub innej biblioteki, w której nie można kontrolować definicji klasy i nie można jej zastosować TypeConverterAttribute .

Zobacz też