Definieren von benutzerdefinierten Typen für die Verwendung mit .NET XAML Services
Wenn Sie benutzerdefinierte Typen definieren, die Geschäftsobjekte sind oder Typen sind, die keine Abhängigkeit von bestimmten Frameworks haben, gibt es bestimmte bewährte Methoden für XAML, denen Sie folgen können. Wenn Sie diese Methoden befolgen, können .NET XAML Services und seine XAML-Leser und XAML-Autoren die XAML-Merkmale Ihres Typs ermitteln und ihm mithilfe des XAML-Typsystems eine geeignete Darstellung in einem XAML-Knotendatenstrom geben. In diesem Thema werden bewährte Methoden für Typdefinitionen, Memberdefinitionen und CLR-Attributierung von Typen oder Elementen beschrieben.
Konstruktormuster und Typdefinitionen für XAML
Um als Objektelement in XAML instanziiert zu werden, muss eine benutzerdefinierte Klasse die folgenden Anforderungen erfüllen:
Die benutzerdefinierte Klasse muss öffentlich sein und einen parameterlosen öffentlichen Konstruktor verfügbar machen. (Hinweise zu Strukturen finden Sie im folgenden Abschnitt.)
Die benutzerdefinierte Klasse darf keine geschachtelte Klasse sein. Der zusätzliche "Punkt" im vollständigen Namenpfad macht die Klassennamespace-Division mehrdeutig und stört andere XAML-Features wie angefügte Eigenschaften. Wenn ein Objekt als Objektelement instanziiert werden kann, kann das erstellte Objekt die Eigenschaftselementform aller Eigenschaften ausfüllen, die das Objekt als zugrunde liegender Typ verwenden.
Sie können weiterhin Objektwerte für Typen bereitstellen, die diese Kriterien nicht erfüllen, wenn Sie einen Wertkonverter aktivieren. Weitere Informationen finden Sie unter Typkonverter und Markuperweiterungen für XAML-.
Strukturen
Strukturen können immer in XAML erstellt werden, anhand der CLR-Definition. Dies liegt daran, dass ein CLR-Compiler implizit einen parameterlosen Konstruktor für eine Struktur erstellt. Dieser Konstruktor initialisiert alle Eigenschaftswerte auf ihre Standardwerte.
In einigen Fällen ist das Standardkonstruktionsverhalten für eine Struktur nicht wünschenswert. Dies kann darauf zurückzuführen sein, dass die Struktur werte und funktionell als Vereinigung füllen soll. Als Vereinigung können die enthaltenen Werte sich gegenseitig ausschließen, und daher sind keine ihrer Eigenschaften festgelegt. Ein Beispiel für eine solche Struktur im WPF-Vokabular ist GridLength. Solche Strukturen sollten einen Typkonverter implementieren, damit die Werte in Attributform ausgedrückt werden können, indem Zeichenfolgenkonventionen verwendet werden, die die verschiedenen Interpretationen oder Modi der Strukturwerte erstellen. Die Struktur sollte auch ein ähnliches Verhalten für die Codeerstellung über einen nicht parameterlosen Konstruktor verfügbar machen.
Schnittstellen
Schnittstellen können als zugrunde liegende Elementtypen verwendet werden. Das XAML-Typsystem überprüft die zuordnungsfähige Liste und erwartet, dass das Objekt, das als Wert bereitgestellt wird, der Schnittstelle zugewiesen werden kann. Es gibt kein Konzept, wie die Schnittstelle als XAML-Typ dargestellt werden muss, solange ein relevanter zuweisungsfähiger Typ die XAML-Konstruktionsanforderungen unterstützt.
Factory-Methoden
Factorymethoden sind ein XAML 2009-Feature. Sie ändern das XAML-Prinzip, dass Objekte parameterlose Konstruktoren aufweisen müssen. Factorymethoden sind in diesem Artikel nicht dokumentiert. Siehe x:FactoryMethod Directive.
Aufzählungen
Enumerationen weisen ein systemeigenes XAML-Typkonvertierungsverhalten auf. Die in XAML angegebenen Enumerationskonstantennamen werden anhand des zugrunde liegenden Enumerationstyps aufgelöst und geben den Enumerationswert an einen XAML-Objektschreiber zurück.
XAML unterstützt eine Verwendung im Flags-Stil für Enumerationen, auf die FlagsAttribute angewendet werden. Weitere Informationen finden Sie unter XAML-Syntax im Detail. (XAML-Syntax im Detail wird für die WPF-Zielgruppe geschrieben, aber die meisten Informationen in diesem Thema sind für XAML relevant, die nicht für ein bestimmtes Implementierungsframework spezifisch sind.)
Memberdefinitionen
Typen können Member für die XAML-Verwendung definieren. Es ist möglich, dass Typen Elemente definieren, die XAML-verwendbar sind, auch wenn dieser bestimmte Typ nicht XAML-verwendbar ist. Dies ist aufgrund der CLR-Vererbung möglich. Solange ein Typ, der das Element erbt, die XAML-Verwendung als Typ unterstützt, und das Element unterstützt die XAML-Verwendung für den zugrunde liegenden Typ oder eine systemeigene XAML-Syntax verfügbar ist, ist dieses Element XAML-verwendbar.
Eigenschaften
Wenn Sie Eigenschaften als öffentliche CLR-Eigenschaft mit den typischen CLR-get
und set
Accessormustern und sprachgerechten Schlüsselworten definieren, kann das XAML-Typsystem die Eigenschaft als Mitglied mit entsprechenden Informationen für XamlMember Eigenschaften, z. B. IsReadPublic und IsWritePublic, melden.
Bestimmte Eigenschaften können eine Textsyntax aktivieren, indem TypeConverterAttributeangewendet wird. Weitere Informationen finden Sie unter Typkonverter und Markuperweiterungen für XAML-.
Wenn keine Textsyntax oder native XAML-Konvertierung vorhanden ist und keine weitere Dereferenzierung vorhanden ist, z. B. eine Markuperweiterungsverwendung, muss der Typ einer Eigenschaft (TargetType im XAML-Typsystem) eine Instanz an einen XAML-Objektschreiber zurückgeben können, indem der Zieltyp als CLR-Typ behandelt wird.
Bei Verwendung von XAML 2009 können x:Reference Markup Extension verwendet werden, um Werte bereitzustellen, wenn die vorherigen Überlegungen nicht erfüllt sind; Dies ist jedoch eher ein Verwendungsproblem als ein Typdefinitionsproblem.
Ereignisse
Wenn Sie Ereignisse als öffentliches CLR-Ereignis definieren, kann das XAML-Typsystem das Ereignis als Mitglied mit IsEvent als true
melden. Das Verkabeln der Ereignishandler liegt nicht im Bereich der .NET-XAML-Dienste-Funktionen; Die Verkabelung bleibt spezifischen Frameworks und Implementierungen überlassen.
Methodik
Inlinecode für Methoden ist keine Standardmäßige XAML-Funktion. In den meisten Fällen verweisen Sie nicht direkt auf Methodenmmber aus XAML, und die Rolle von Methoden in XAML besteht nur darin, unterstützung für bestimmte XAML-Muster bereitzustellen. x:FactoryMethod-Direktive ist eine Ausnahme.
Felder
CLR-Entwurfsrichtlinien verhindern nicht statische Felder. Bei statischen Feldern können Sie nur über x:Static Markup Extensionauf statische Feldwerte zugreifen; In diesem Fall machen Sie nichts Besonderes in der CLR-Definition, um ein Feld für x:Static Verwendungen verfügbar zu machen.
Anfügende Elemente
Anfügende Member werden xaml über ein Accessormethodenmuster für einen definierenden Typ verfügbar gemacht. Der definierende Typ selbst muss nicht XAML-verwendbar als Objekt sein. Tatsächlich besteht ein gängiges Muster darin, eine Dienstklasse zu deklarieren, deren Rolle das anfügende Element besitzt und die zugehörigen Verhaltensweisen implementiert, aber keine andere Funktion wie eine UI-Darstellung bedient. In den folgenden Abschnitten stellt der Platzhalter PropertyName- den Namen des anfügenden Elements dar. Dieser Name muss im XamlName Grammargültig sein.
Achten Sie auf Namenskonflikte zwischen diesen Mustern und anderen Methoden eines Typs. Wenn ein Element vorhanden ist, das einem der Muster entspricht, kann es von einem XAML-Prozessor als anfügenden Memberverwendungspfad interpretiert werden, auch wenn dies nicht Ihre Absicht war.
Der GetPropertyName-Accessor
Die Signatur für den GetPropertyName
-Accessor muss folgendes sein:
public static object GetPropertyName(object target)
Das
target
-Objekt kann in Ihrer Implementierung als spezifischerer Typ angegeben werden. Sie können dies verwenden, um die Nutzung Ihres anfügenden Mitglieds zu beschränken. Verwendungen außerhalb des beabsichtigten Bereichs lösen ungültige Umwandlungsausnahmen aus, die dann durch einen XAML-Analysefehler angezeigt werden. Der Parameternametarget
ist keine Anforderung, sondern wird in den meisten Implementierungentarget
nach Konvention benannt.Der Rückgabewert kann in Ihrer Implementierung als spezifischerer Typ angegeben werden.
Um eine TypeConverter aktivierte Textsyntax für die Attributverwendung des anfügenden Elements zu unterstützen, wenden Sie TypeConverterAttribute auf den GetPropertyName
Accessor an. Die Anwendung auf die get
anstelle der set
kann nicht intuitiv erscheinen; Diese Konvention kann jedoch das Konzept von schreibgeschützten anfügenden Membern unterstützen, die serialisierbar sind, was in Designerszenarien nützlich ist.
Der SetPropertyName-Accessor
Die Signatur für den SetPropertyName
-Accessor muss folgendes sein:
public static void SetPropertyName(object target, object value)
Das
target
-Objekt kann in Ihrer Implementierung als spezifischerer Typ angegeben werden, mit der gleichen Logik und Folgen wie im vorherigen Abschnitt beschrieben.Das
value
-Objekt kann in Ihrer Implementierung als spezifischerer Typ angegeben werden.
Denken Sie daran, dass der Wert für diese Methode die Eingabe aus der XAML-Verwendung ist, in der Regel in Attributform. Aus Attributform muss eine Wertkonverterunterstützung für eine Textsyntax vorhanden sein, und Sie müssen für den Accessor des GetPropertyName
Attributs attributisieren.
Anfügende Memberspeicher
Die Accessormethoden reichen in der Regel nicht aus, um anfügende Memberwerte in ein Objektdiagramm zu platzieren oder Werte aus dem Objektdiagramm abzurufen und diese ordnungsgemäß zu serialisieren. Um diese Funktionalität bereitzustellen, müssen die target
Objekte in den vorherigen Accessorsignaturen in der Lage sein, Werte zu speichern. Der Speichermechanismus sollte mit dem Grundsatz des anfügenden Mitglieds übereinstimmen, dass das Mitglied an Ziele angefügt werden kann, bei denen sich das anfügende Mitglied nicht in der Mitgliederliste befindet. .NET XAML Services stellt eine Implementierungstechnik für anfügende Memberspeicher über die APIs IAttachedPropertyStore und AttachablePropertyServicesbereit.
IAttachedPropertyStore wird von den XAML-Autoren verwendet, um die Store-Implementierung zu ermitteln, und sollte für den Typ implementiert werden, der die target
der Accessoren ist. Die statischen AttachablePropertyServices-APIs werden innerhalb des Textkörpers der Accessoren verwendet und verweisen auf das anfügende Element anhand der AttachableMemberIdentifier.
XAML-Related CLR-Attribute
Das ordnungsgemäße Attributieren von Typen, Membern und Assemblys ist wichtig, um XAML-Typsysteminformationen an .NET XAML-Dienste zu melden. Die Berichterstellung von XAML-Typsysteminformationen ist relevant, wenn eine der folgenden Situationen zutrifft:
- Sie beabsichtigen Die Typen für die Verwendung mit XAML-Systemen, die direkt auf .NET XAML Services-XAML-Lesern und XAML-Autoren basieren.
- Sie definieren oder verwenden ein XAML-nutzungsbasiertes Framework, das auf diesen XAML-Lesern und XAML-Autoren basiert.
Eine Auflistung der einzelnen XAML-bezogenen Attribute, die für die XAML-Unterstützung Ihrer benutzerdefinierten Typen relevant sind, finden Sie unter XAML-Related CLR-Attribute für benutzerdefinierte Typen und Bibliotheken.
Verwendung
Für die Verwendung von benutzerdefinierten Typen muss der Markupautor ein Präfix für den Assembly- und CLR-Namespace zuordnen, der den benutzerdefinierten Typ enthält. Dieses Verfahren ist in diesem Thema nicht dokumentiert.
Zugriffsebene
XAML bietet eine Möglichkeit zum Laden und Instanziieren von Typen mit einer internal
Zugriffsebene. Diese Funktion wird bereitgestellt, sodass Benutzercode eigene Typen definieren und diese Klassen dann aus Markup instanziieren kann, die ebenfalls Teil desselben Benutzercodebereichs sind.
Ein Beispiel von WPF ist jedes Mal, wenn Benutzercode eine UserControl definiert, die als Möglichkeit zum Umgestalten eines Benutzeroberflächenverhaltens vorgesehen ist, aber nicht als Teil eines möglichen Erweiterungsmechanismus, der durch Deklarieren der unterstützenden Klasse mit public
Zugriffsebene impliziert werden kann. Eine solche UserControl kann mit internal
Zugriff deklariert werden, wenn der Sicherungscode in derselben Assembly kompiliert wird, aus der als XAML-Typ verwiesen wird.
Für eine Anwendung, die XAML unter voller Vertrauenswürdigkeit lädt und XamlObjectWriterverwendet, ist das Laden von Klassen mit internal
Zugriffsebene immer aktiviert.
Für eine Anwendung, die XAML unter teilweise Vertrauenswürdigkeit lädt, können Sie die Merkmale der Zugriffsebene mithilfe der XamlAccessLevel-API steuern. Außerdem müssen Zurückstellungsmechanismen (z. B. das WPF-Vorlagensystem) in der Lage sein, berechtigungen auf Zugriffsebene zu verteilen und sie für die eventuellen Laufzeitauswertungen beizubehalten; Dies wird intern behandelt, indem die XamlAccessLevel Informationen übergeben werden.
WPF-Implementierung
WPF-XAML verwendet ein teilweise vertrauenswürdiges Zugriffsmodell, bei dem der Zugriff auf die Assembly, die die BAML-Quelle ist, auf AssemblyAccessTo beschränkt ist, wenn BAML geladen wird. Für die Verzögerung verwendet WPF IXamlObjectWriterFactory.GetParentSettings als Mechanismus zum Übergeben der Informationen auf Zugriffsebene.
In der WPF-XAML-Terminologie ist ein internen Typs ein Typ, der von derselben Assembly definiert wird, die auch den referenzierenden XAML-Code enthält. Ein solcher Typ kann über einen XAML-Namespace zugeordnet werden, der die Assembly= Teil einer Zuordnung absichtlich weggelassen, z. B. xmlns:local="clr-namespace:WPFApplication1"
. Wenn BAML auf einen internen Typ verweist und dieser Typ über internal
Zugriffsebene verfügt, generiert dies eine GeneratedInternalTypeHelper
Klasse für die Assembly. Wenn Sie GeneratedInternalTypeHelper
vermeiden möchten, müssen Sie entweder public
Zugriffsebene verwenden oder die relevante Klasse in eine separate Assembly aufteilen und diese Assembly abhängig machen.
Siehe auch
.NET Desktop feedback