TypeConverters und XAML
In diesem Thema wird der Zweck der Typumwandlung von einer Zeichenfolge als allgemeine XAML-Sprachfunktion beschrieben. In .NET Framework dient die TypeConverter-Klasse einem bestimmten Zweck als Teil der Implementierung für eine verwaltete benutzerdefinierte Klasse, die als Eigenschaftswert in der XAML-Attributverwendung verwendet werden kann. Wenn Sie eine benutzerdefinierte Klasse schreiben und möchten, dass Instanzen Ihrer Klasse als XAML setzbare Attributwerte verwendet werden können, müssen Sie möglicherweise eine TypeConverterAttribute auf Ihre Klasse anwenden oder eine benutzerdefinierte TypeConverter-Klasse schreiben oder beides.
Typumwandlungskonzepte
XAML- und Zeichenfolgenwerte
Wenn Sie einen Attributwert in einer XAML-Datei festlegen, ist der anfängliche Typ dieses Werts eine Zeichenfolge in reinem Text. Auch andere Grundtypen wie Double sind anfänglich Textzeichenfolgen für einen XAML-Prozessor.
Ein XAML-Prozessor benötigt zwei Informationen, um einen Attributwert zu verarbeiten. Der erste Informationsteil ist der Werttyp der eigenschaft, die festgelegt wird. Jede Zeichenfolge, die einen Attributwert definiert und in XAML verarbeitet wird, muss letztendlich in einen Wert dieses Typs konvertiert oder aufgelöst werden. Wenn der Wert ein Grundtyp ist, der vom XAML-Parser (z. B. einem numerischen Wert) verstanden wird, wird eine direkte Konvertierung der Zeichenfolge versucht. Wenn es sich bei dem Wert um eine Enumeration handelt, wird die Zeichenfolge verwendet, um zu überprüfen, ob ein Name mit einer benannten Konstante in dieser Enumeration übereinstimmt. Wenn der Wert weder ein parser-verstandener Grundtyp noch eine Aufzählung ist, muss der betreffende Typ basierend auf einer konvertierten Zeichenfolge eine Instanz des Typs oder einen Wert bereitstellen können. Dazu wird eine Typkonverterklasse angegeben. Der Typkonverter ist im Grunde eine Hilfsklasse zum Liefern von Werten einer anderen Klasse, sowohl für XAML-Szenarien als auch für Codeaufrufe in .NET-Code.
Verwenden des vorhandenen Typkonvertierungsverhaltens in XAML
Je nach Vertrautheit mit den zugrunde liegenden XAML-Konzepten verwenden Sie möglicherweise bereits Typkonvertierungsverhalten in grundlegendem Anwendungs-XAML, ohne sie zu erkennen. Beispielsweise definiert WPF Hunderte von Eigenschaften, die einen Wert vom Typ Pointannehmen. Ein Point ist ein Wert, der eine Koordinate in einem zweidimensionalen Koordinatenbereich beschreibt und tatsächlich nur zwei wichtige Eigenschaften aufweist: X und Y. Wenn Sie einen Punkt in XAML angeben, geben Sie ihn als Zeichenfolge mit einem Trennzeichen (in der Regel ein Komma) zwischen dem angegebenen X und Y Werten an. Beispiel: <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"/>
.
Auch diese einfache Art von Point und seine einfache Nutzung in XAML erfordert einen Typkonverter. In diesem Fall ist die Klasse PointConverter.
Der Typkonverter für Point, der auf Klassenebene definiert ist, vereinfacht die Verwendung von Markups für alle Eigenschaften, die Pointverwenden. Ohne einen Typkonverter benötigen Sie hier das folgende ausführlichere Markup für das zuvor gezeigte Beispiel:
<LinearGradientBrush>
<LinearGradientBrush.StartPoint>
<Point X="0" Y="0"/>
</LinearGradientBrush.StartPoint>
<LinearGradientBrush.EndPoint>
<Point X="1" Y="1"/>
</LinearGradientBrush.EndPoint>
</LinearGradientBrush>
Ob die Typkonvertierungszeichenfolge oder eine ausführlichere äquivalente Syntax verwendet werden soll, ist im Allgemeinen eine Codierungsstilauswahl. Ihr XAML-Toolworkflow kann auch beeinflussen, wie Werte festgelegt werden. Einige XAML-Tools neigen dazu, die ausführlichste Form des Markups zu emittieren, da es einfacher ist, zu Designeransichten oder zu seinem eigenen Serialisierungsmechanismus hinzurunden.
Vorhandene Typkonverter können in der Regel bei WPF- und .NET Framework-Typen gefunden werden, indem eine Klasse (oder Eigenschaft) auf das Vorhandensein eines angewendeten TypeConverterAttributeüberprüft wird. Dieses Attribut benennt die Klasse, die den unterstützenden Typkonverter für Werte dieses Typs bestimmt, sowohl für XAML-Zwecke als auch potenziell für andere Zwecke.
Typkonverter und Markuperweiterungen
Markuperweiterungen und Typkonverter spielen unabhängige Rollen im Hinblick auf das XAML-Prozessorverhalten und die Szenarien, auf die sie angewendet werden. Obwohl der Kontext für die Verwendung von Markuperweiterungen verfügbar ist, wird das Typkonvertierungsverhalten von Eigenschaften, bei denen eine Markuperweiterung einen Wert bereitstellt, in der Regel nicht in den Markuperweiterungsimplementierungen überprüft. Anders ausgedrückt: Selbst wenn eine Markuperweiterung eine Textzeichenfolge als ProvideValue
-Ausgabe zurückgibt, wird das Typkonvertierungsverhalten nicht aktiviert, wenn diese Zeichenfolge auf eine bestimmte Eigenschaft oder einen Eigenschaftswerttyp angewendet wird. Im Allgemeinen besteht der Zweck einer Markuperweiterung darin, eine Zeichenfolge zu verarbeiten und ein Objekt ohne Beteiligung eines Typkonverters zurückzugeben.
Eine häufige Situation, in der eine Markuperweiterung anstelle eines Typkonverters erforderlich ist, besteht darin, einen Verweis auf ein bereits vorhandenes Objekt zu erstellen. Ein zustandsloser Typkonverter konnte am besten nur eine neue Instanz generieren, die möglicherweise nicht wünschenswert ist. Weitere Informationen zu Markuperweiterungen finden Sie unter Markuperweiterungen und WPF XAML.
Systemeigene Typkonverter
In der WPF- und .NET Framework-Implementierung des XAML-Parsers gibt es bestimmte Typen, die über eine systemeigene Typkonvertierungsbehandlung verfügen, jedoch keine Typen, die konventionell als Grundtypen betrachtet werden können. Ein Beispiel für einen solchen Typ ist DateTime. Der Grund dafür basiert darauf, wie die .NET Framework-Architektur funktioniert: Der Typ DateTime wird in mscorlib, der einfachsten Bibliothek in .NET definiert. DateTime darf nicht mit einem Attribut attributiert werden, das von einer anderen Assembly stammt, die eine Abhängigkeit einführt (TypeConverterAttribute von System), sodass der übliche Mechanismus zur Typkonverterermittlung durch Attributierung nicht unterstützt werden kann. Stattdessen verfügt der XAML-Parser über eine Liste von Typen, die eine solche systemeigene Verarbeitung benötigen, und verarbeitet diese ähnlich wie die tatsächlichen Primitiven. (Im Falle von DateTime umfasst dies einen Aufruf von Parse.)
Implementieren eines Typkonverters
Typkonverter
Im zuvor angegebenen Point Beispiel wurde die Klasse PointConverter erwähnt. Bei .NET-Implementierungen von XAML sind alle Typkonverter, die für XAML-Zwecke verwendet werden, Klassen, die von der Basisklasse TypeConverterabgeleitet werden. Die TypeConverter-Klasse ist in Versionen von .NET Framework vorhanden, die vor dem Vorhandensein von XAML stehen; Eine seiner ursprünglichen Verwendungen bestand darin, eine Zeichenfolgenkonvertierung für Eigenschaftendialoge in visuellen Designern bereitzustellen. Bei XAML wird die Rolle von TypeConverter erweitert, um als Basisklasse für Konvertierungen zu und von Zeichenfolgen zu dienen, die das Parsen eines Zeichenfolgenattributwerts ermöglichen und möglicherweise den Laufzeitwert einer bestimmten Objekteigenschaft wieder in eine Zeichenfolge zur Serialisierung als Attribut umwandeln.
TypeConverter definiert vier Elemente, die für die Konvertierung in und aus Zeichenfolgen für XAML-Verarbeitungszwecke relevant sind:
Von diesen ist die wichtigste Methode ConvertFrom. Diese Methode konvertiert die Eingabezeichenfolge in den erforderlichen Objekttyp. Genau genommen könnte die ConvertFrom-Methode implementiert werden, um einen viel breiteren Bereich von Typen in den beabsichtigten Zieltyp des Konverters zu konvertieren, und dient daher Zwecken, die über XAML hinausgehen, z. B. die Unterstützung von Laufzeitkonvertierungen, aber für XAML-Zwecke ist es nur der Codepfad, der eine String Eingabe verarbeiten kann, die wichtig ist.
Die zweitwichtigste Methode ist ConvertTo. Wenn eine Anwendung in eine Markupdarstellung konvertiert wird (z. B. wenn sie in XAML als Datei gespeichert wird), ist ConvertTo für die Erstellung einer Markupdarstellung verantwortlich. In diesem Fall ist es für XAML wichtig, wenn Sie einen Codepfad übergeben, der eine destinationType
von String umfasst.
CanConvertTo und CanConvertFrom sind Supportmethoden, die verwendet werden, wenn ein Dienst die Funktionen der TypeConverter Implementierung abfragt. Sie müssen diese Methoden implementieren, um true
für typspezifische Fälle zurückzugeben, die die entsprechenden Konvertierungsmethoden Ihres Konverters unterstützen. Für XAML-Zwecke bedeutet dies im Allgemeinen den String Typ.
Kulturelle Informationen und Typkonverter für XAML
Jede TypeConverter Implementierung kann eine eigene Interpretation davon haben, was eine gültige Zeichenfolge für eine Konvertierung darstellt, und kann auch die als Parameter übergebene Typbeschreibung verwenden oder ignorieren. Es gibt eine wichtige Überlegung hinsichtlich Kultur und XAML-Typkonvertierung. Die Verwendung lokalisierbarer Zeichenfolgen als Attributwerte wird vollständig von XAML unterstützt. Die Verwendung dieser lokalisierbaren Zeichenfolge als Eingabe für den Typkonverter mit kulturspezifischen Anforderungen wird jedoch nicht unterstützt, da Typkonverter für XAML-Attributwerte ein zwangsläufig festgelegtes Sprachverhalten erfordern, bei dem die en-US
-Kultur verwendet wird. Weitere Informationen zu den Entwurfsgründen für diese Einschränkung finden Sie in der XAML-Sprachspezifikation ([MS-XAML].
Als Beispiel, bei dem Kultur ein Problem sein kann, verwenden einige Kulturen ein Komma als Dezimalkommatrennzeichen für Zahlen. Dies kollidiert mit dem Verhalten, das viele der WPF-XAML-Typkonverter aufweisen, die ein Komma als Trennzeichen verwenden (basierend auf historischen Vorgängern wie dem allgemeinen X,Y-Formular oder kommagetrennten Listen). Selbst das Übergeben einer Kultur im umgebenden XAML-Code (Einstellen von Language
oder xml:lang
auf die sl-SI
-Kultur, ein Beispiel für eine Kultur, die auf diese Weise ein Komma für Dezimalzahlen verwendet) löst das Problem nicht.
Implementierung von ConvertFrom
Damit sie als TypeConverter Implementierung verwendet werden kann, die XAML unterstützt, muss die ConvertFrom-Methode für diesen Konverter eine Zeichenfolge als value
-Parameter akzeptieren. Wenn die Zeichenfolge in einem gültigen Format vorliegt und durch die TypeConverter-Implementierung konvertiert werden kann, muss das zurückgegebene Objekt eine Konvertierung in den von der Eigenschaft erwarteten Typ unterstützen. Andernfalls muss die ConvertFrom-Implementierung null
zurückgeben.
Jede TypeConverter-Implementierung kann ihre eigene Interpretation davon haben, was eine gültige Zeichenfolge für eine Konvertierung darstellt. Zudem kann sie die übergebenen Typbeschreibungen oder Kulturkontexte verwenden oder ignorieren. Die WPF-XAML-Verarbeitung übergibt jedoch in allen Fällen möglicherweise keine Werte an den Typbeschreibungskontext, und es wird auch keine Kultur basierend auf xml:lang
übergeben.
Anmerkung
Verwenden Sie nicht die geschweiften Klammernzeichen, insbesondere {, als mögliches Element des Zeichenfolgenformats. Diese Zeichen sind als Eingang und Ausgang für eine Markup-Erweiterungssequenz reserviert.
Implementierung von ConvertTo
ConvertTo wird potenziell zur Serialisierungsunterstützung verwendet. Serialisierungssupport durch ConvertTo für Ihren benutzerdefinierten Typ und dessen Typkonverter ist keine absolute Anforderung. Wenn Sie jedoch ein Steuerelement implementieren oder die Serialisierung als Teil der Features oder des Entwurfs Ihrer Klasse verwenden, sollten Sie ConvertToimplementieren.
Damit sie als TypeConverter Implementierung verwendet werden kann, die XAML unterstützt, muss die ConvertTo-Methode für diesen Konverter eine Instanz des Typs (oder eines Werts) akzeptieren, der als value
-Parameter unterstützt wird. Wenn der destinationType
-Parameter der Typ Stringist, muss das zurückgegebene Objekt als Stringumgewandelt werden können. Die zurückgegebene Zeichenfolge muss einen serialisierten Wert von value
repräsentieren. Im Idealfall sollte das von Ihnen ausgewählte Serialisierungsformat in der Lage sein, denselben Wert zu generieren, wenn diese Zeichenfolge an die ConvertFrom Implementierung desselben Konverters ohne erheblichen Informationsverlust übergeben wurde.
Wenn der Wert nicht serialisiert werden kann oder der Konverter die Serialisierung nicht unterstützt, muss die ConvertTo-Implementierung null
zurückgeben und darf in diesem Fall eine Ausnahme auslösen. Wenn Sie jedoch Ausnahmen auslösen, sollten Sie die Unfähigkeit melden, diese Konvertierung als Teil Ihrer CanConvertTo Implementierung zu verwenden, damit die bewährte Methode der Überprüfung mit CanConvertTo zuerst unterstützt wird, um Ausnahmen zu vermeiden.
Wenn der Parameter destinationType
nicht vom Typ Stringist, können Sie eine eigene Konvertersteuerung auswählen. Normalerweise würden Sie zur Basisimplementierung zurückkehren, die im grundlegendsten Fall ConvertTo eine spezifische Ausnahme auslöst.
Implementierung von CanConvertTo
Ihre CanConvertTo-Implementierung sollte true
für destinationType
vom Typ Stringzurückgeben und ansonsten auf die Basisimplementierung zurückstellen.
Implementieren von CanConvertFrom
Ihre CanConvertFrom-Implementierung sollte true
für sourceType
vom Typ Stringzurückgeben und andernfalls auf die Basisimplementierung zurückstellen.
Anwenden von TypeConverterAttribute
Damit Ihr benutzerdefinierter Typkonverter als aktiver Typkonverter für eine benutzerdefinierte Klasse durch einen XAML-Prozessor verwendet werden kann, müssen Sie die TypeConverterAttribute auf die Klassendefinition anwenden. Die ConverterTypeName, die Sie über das Attribut angeben, muss der Typname des benutzerdefinierten Typkonverters sein. Mit diesem Attribut angewendet, kann ein XAML-Prozessor, wenn er Werte verarbeitet, bei denen der Eigenschaftstyp Ihren benutzerdefinierten Klassentyp verwendet, Zeichenfolgen eingeben und Objektinstanzen zurückgeben.
Sie können auch einen Typkonverter pro Eigenschaft bereitstellen. Anstatt TypeConverterAttribute auf die Klassendefinition anzuwenden, wenden Sie sie auf die Definition einer Eigenschaft an (die Hauptdefinition, nicht die Implementierungen von get
/set
darin). Der Typ der Eigenschaft muss mit dem Typ übereinstimmen, der von Ihrem benutzerdefinierten Typkonverter verarbeitet wird. Wenn dieses Attribut angewendet wird, kann ein XAML-Prozessor, wenn er Werte dieser Eigenschaft verarbeitet, Eingabestrings verarbeiten und Objektinstanzen zurückgeben. Die Konvertertechnik pro Eigenschaft ist besonders nützlich, wenn Sie einen Eigenschaftstyp aus Microsoft .NET Framework oder aus einer anderen Bibliothek verwenden, in der Sie die Klassendefinition nicht steuern können und dort keine TypeConverterAttribute anwenden können.
Siehe auch
.NET Desktop feedback