Ich habe diese Markup-Erweiterung
%Vor%, das eine NULL-fähige Version eines anderen Typs bereitstellen soll. Es funktioniert wie erwartet, wenn es in "normalem" XAML verwendet wird. Zum Beispiel wie in
%Vor% (unter der Annahme, dass My der XML-Namespace ist, der für den C # -Namespace definiert ist, der die Erweiterung enthält, und ähnlich für System). Der Datenkontext für das Steuerelement wird wie erwartet auf System.Type
für Nullable<int>
gesetzt.
Wenn ich jedoch diese Erweiterung verwende, versuche ich, die Eigenschaft DataType
eines DataTemplate
like
Das sagt mir der Compiler,
Ein Schlüssel für ein Wörterbuch kann nicht vom Typ sein 'System.Windows.Controls.Primitives.TextBlock'. Nur Schnur, TypeExtension und StaticExtension werden unterstützt. "
und
"Kein Konstruktor für den Typ 'NullableExtension' hat 1 Parameter.
Weiß jemand, warum nur diese drei Methoden (und nicht einmal Unterklassen von TypeExtension
, wie meiner) erlaubt sind? Was ist das Besondere an der Verarbeitung des XAML an diesem Punkt? Und gibt es eine andere Möglichkeit, dies zu erreichen (Auswahl der Datenvorlage basierend auf Typen, die möglicherweise nullfähig sein können), ohne auf DataTemplateSelector
zurückzugreifen?
Ich bin wirklich auf Ihre Frage eingegangen, und hier ist, was ich gefunden habe.
F: Warum sind nur diese drei (
String
,TypeExtension
undStaticExtension
) zulässig?
A: Durch das Design. Wenn Sie eine benutzerdefinierte Markup-Erweiterung schreiben könnten, die als Schlüssel in einem Wörterbuch verwendet werden soll, welche Nebenwirkungen würde dies verursachen? Bedenken Sie, dass Sie Binding als Wert von DataType haben ... Ich bin mir ziemlich sicher, dass Sie Dutzende von Problemen hinzufügen können, die sich auf die dynamische Natur von Dictionary-Schlüsseln beziehen.
F: Was ist das Besondere an der Verarbeitung des XAML an diesem Punkt?
A . An diesem Punkt haben Sie BAML-Erstellung. Das Problem kommt von der internen Klasse BamlRecordWriter
, aber die Nachricht beschreibt nicht das tatsächliche Problem. Wenn Sie eine benutzerdefinierte Markup-Erweiterung als DataType angeben, wird die untergeordnetes Element von DataTemplate genommen und überprüft, ob sie aus String, TypeExtension oder StaticExtension zuweisbar ist (siehe BamlRecordWriter.WriteElementStart () -Funktion) . Tatsächlich. Nicht Ihre Erweiterung (die TypeExtension zugewiesen werden kann), sondern das erste untergeordnete Element (das nicht zuweisbar ist). Jetzt haben Sie dieses seltsame " kann nicht vom Typ sein". Obwohl es wie ein Fehler von BamlRecordWriter aussieht, haben sie es meiner Meinung nach absichtlich verlassen. Bis Sie nicht benutzerdefinierte Markup-Erweiterung als DataType-Wert verwenden können, wer kümmert sich um Fehlermeldung?
F: Gibt es eine andere Möglichkeit, dies zu erreichen (Auswahl von Datenvorlagen basierend auf Typen, die möglicherweise nullfähig sind), ohne auf einen DataTemplateSelector zurückgreifen zu müssen?
A: Ja, irgendwie. Zuallererst können Sie standardmäßige TypeExtension haben, die alle schmutzigen Jobs für Sie erledigt:
%Vor% Aber in den meisten Fällen (wenn nicht die ganze Zeit) werden Sie die Templates nicht sehen. Warum? Jetzt kommt es zu Boxregeln für NULL-fähige Typen. Wenn Sie einen nicht nullbaren Nullwerttyp boxen, wird der Werttyp selbst eingeschlossen, nicht der System.Nullable, der den Werttyp umschließt. Daher sucht der Standardvorlagen-Selektor nach DataTemplate mit dem Datentyp T
nicht von Nullable<T>
.
Ich verstehe möglicherweise nicht genau das Problem, das Sie versuchen, mit NULL-Erweiterung zu lösen, aber Sie möchten NULL in Ihrem eigenen Ref-Typ einbinden, ein DataTemplate für den Wrapper schreiben und DataTemplate.Triggers
verwenden, um das Aussehen des Inhalts zu wählen. Nun, das sieht wie neu erfundene Datenvorlagenauswahl aus:) ...
NB: Ich bin kein MS-Typ, und meine Ergebnisse basieren auf Reflector und meiner eigenen Erfahrung (die nicht so groß ist, wie ich es mir gewünscht hätte. alt text http://www.kolobok.us/smiles/standart/blush2.gif ). Hoffe ich könnte auf jeden Fall helfen:).
Prost
Ich habe einen fiesen Workaround dafür gefunden. Aus irgendeinem Grund hat @Anvaka Recht: Die DataType-Eigenschaft lässt keine benutzerdefinierte MarkupExtension zu. Es erlaubt Ihnen jedoch, eine StaticResource der benutzerdefinierten MarkupExtension zu verwenden.
Nehmen Sie Ihre MarkupExtension, fügen Sie einen öffentlichen Standardkonstruktor hinzu. Erstellen Sie dann eine Instanz Ihrer Erweiterung in den Ressourcen und legen Sie die Eigenschaften direkt fest. Boom, es braucht es. Das Folgende ist ähnlich wie das, was Sie tun müssten
%Vor%Die Syntax
%Vor%scheint nicht für benutzerdefinierte Typen zu funktionieren :(
Eine andere Möglichkeit besteht darin, einen nicht generischen Basistyp zu erstellen. Setzen Sie die erste Datenvorlage auf diesen Typ und binden Sie ContentPresenter.Content
an die Eigenschaft, die das Objekt von T
enthält. Erstellen Sie dann weitere Datenvorlagen für das gesamte T
.
Tags und Links wpf xaml datatemplate