Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Artikel werden die Features der XAML-Sprache beschrieben und veranschaulicht, wie Sie WINDOWS Presentation Foundation (WPF)-Apps mit XAML schreiben können. In diesem Artikel wird xaml speziell beschrieben, wie es von WPF implementiert wird. XAML selbst ist ein größeres Sprachkonzept als WPF.
Was ist XAML?
XAML ist eine deklarative Markupsprache. Wie auf das .NET-Programmiermodell angewendet, vereinfacht XAML das Erstellen einer Benutzeroberfläche für eine .NET-App. Sie können sichtbare UI-Elemente im deklarativen XAML-Markup erstellen und dann die UI-Definition von der Laufzeitlogik trennen, indem Sie CodeBehind-Dateien verwenden, die durch partielle Klassendefinitionen mit dem Markup verknüpft sind. XAML stellt direkt die Instanziierung von Objekten in einer bestimmten Gruppe von unterstützenden Typen dar, die in Assemblies definiert sind. Dies ist im Gegensatz zu den meisten anderen Markupsprachen, die in der Regel interpretierte Sprachen ohne eine solche direkte Verbindung zu einem unterstützenden Typsystem sind. XAML ermöglicht einen Workflow, in dem separate Parteien auf der Benutzeroberfläche und der Logik einer App mit potenziell unterschiedlichen Tools arbeiten können.
Wenn sie als Text dargestellt wird, sind XAML-Dateien XML-Dateien, die in der Regel über die .xaml
Erweiterung verfügen. Die Dateien können durch eine beliebige XML-Codierung codiert werden, aber die Codierung als UTF-8 ist typisch.
Das folgende Beispiel zeigt, wie Sie eine Schaltfläche als Teil einer Benutzeroberfläche erstellen können. Dieses Beispiel soll Ihnen einen Geschmack geben, wie XAML allgemeine Metaphern für die Benutzeroberflächenprogrammierung darstellt (es ist kein vollständiges Beispiel).
<StackPanel>
<Button Content="Click Me"/>
</StackPanel>
XAML-Syntax kurz
In den folgenden Abschnitten werden die grundlegenden Formen der XAML-Syntax erläutert und ein kurzes Markupbeispiel gegeben. Diese Abschnitte sollen keine vollständigen Informationen zu den einzelnen Syntaxformen bereitstellen, z. B. wie diese im Basistypsystem dargestellt werden. Weitere Informationen zu den Besonderheiten der XAML-Syntax finden Sie unter XAML-Syntax im Detail.
Ein Großteil des Materials in den nächsten Abschnitten ist elementar für Sie, wenn Sie bereits mit der XML-Sprache vertraut sind. Dies ist eine Folge der grundlegenden Designprinzipien von XAML. Die XAML-Sprache definiert eigene Konzepte, aber diese Konzepte funktionieren innerhalb der XML-Sprache und des Markupformulars.
XAML-Objektelemente
Ein Objektelement deklariert in der Regel eine Instanz eines Typs. Dieser Typ wird in den Assemblys definiert, auf die von der Technologie verwiesen wird, die XAML als Sprache verwendet.
Die Syntax des Objektelements beginnt immer mit einer öffnenden spitzen Klammer (<
). Dies folgt dem Namen des Typs, in dem Sie eine Instanz erstellen möchten. (Der Name kann ein Präfix enthalten, ein Konzept, das später erläutert wird.) Danach können Sie Attribute für das Objektelement optional deklarieren. Um das Objektelementtag abzuschließen, beenden Sie es mit einer abschließenden Winkelklammer (>
). Sie können stattdessen ein selbstschließendes Formular verwenden, das keinen Inhalt hat, indem Sie das Tag mit einem Schrägstrich und einem schließenden Winkel in folgeriger Klammer (/>
) ausfüllen. Sehen Sie sich beispielsweise den zuvor angezeigten Markupausschnitt erneut an.
<StackPanel>
<Button Content="Click Me"/>
</StackPanel>
Dies gibt zwei Objekt Elemente an: <StackPanel>
(mit Inhalt und einem später folgenden schließenden Tag) und <Button .../>
(das selbstschließende Element mit mehreren Attributen). Die Objektelemente StackPanel
und Button
werden jeweils dem Namen einer Klasse zugeordnet, die von WPF definiert ist und Teil der WPF-Assembly ist. Wenn Sie ein Objektelementtag angeben, erstellen Sie eine Anweisung für die XAML-Verarbeitung, um eine neue Instanz des zugrunde liegenden Typs zu erstellen. Jede Instanz wird durch Aufrufen des parameterlosen Konstruktors des zugrunde liegenden Typs beim Analysieren und Laden des XAML-Codes erstellt.
Attributsyntax (Eigenschaften)
Eigenschaften eines Objekts können häufig als Attribute des Objektelements ausgedrückt werden. Die Attributsyntax benennt die objekteigenschaft, die festgelegt wird, gefolgt vom Zuordnungsoperator (=). Der Wert eines Attributs wird immer als Zeichenfolge angegeben, die in Anführungszeichen enthalten ist.
Die Attributsyntax ist die optimierte Eigenschafteneinstellungssyntax und ist die intuitivste Syntax für Entwickler, die in der Vergangenheit Markupsprachen verwendet haben. Das folgende Markup erstellt beispielsweise eine Schaltfläche mit rotem Text und einem blauen Hintergrund mit einem Anzeigetext von Content
.
<Button Background="Blue" Foreground="Red" Content="This is a button"/>
Syntax des Eigenschaftenelements
Für einige Eigenschaften eines Objektelements ist die Attributsyntax nicht möglich, da das objekt oder die zum Bereitstellen des Eigenschaftswerts erforderlichen Informationen nicht angemessen innerhalb des Anführungszeichens und der Zeichenfolgenbeschränkungen der Attributsyntax ausgedrückt werden können. In diesen Fällen kann eine andere Syntax verwendet werden, die als Eigenschaftselementsyntax bezeichnet wird.
Die Syntax für das Starttag des Eigenschaftselements lautet <TypeName.PropertyName>
. Im Allgemeinen ist der Inhalt dieses Tags ein Objektelement des Typs, den die Eigenschaft als Wert verwendet. Nachdem Sie den Inhalt angegeben haben, müssen Sie das Eigenschaftselement mit einem Endtag schließen. Die Syntax für das Endtag lautet </TypeName.PropertyName>
.
Wenn eine Attributsyntax möglich ist, ist die Verwendung der Attributsyntax in der Regel praktischer und ermöglicht ein kompakteres Markup, aber das ist oft nur eine Frage der Formatvorlage, nicht eine technische Einschränkung. Das folgende Beispiel zeigt die gleichen Eigenschaften, die wie im vorherigen Attributsyntaxbeispiel festgelegt werden, aber diesmal mithilfe der Eigenschaftselementsyntax für alle Eigenschaften der .Button
<Button>
<Button.Background>
<SolidColorBrush Color="Blue"/>
</Button.Background>
<Button.Foreground>
<SolidColorBrush Color="Red"/>
</Button.Foreground>
<Button.Content>
This is a button
</Button.Content>
</Button>
Sammlungssyntax
Die XAML-Sprache enthält einige Optimierungen, die ein besser lesbares Markup erzeugen. Eine solche Optimierung besteht darin, dass, wenn eine bestimmte Eigenschaft einen Sammlungstyp verwendet, die Elemente, die Sie im Markup als untergeordnete Elemente innerhalb dieses Eigenschaftswerts deklarieren, Teil der Auflistung werden. In diesem Fall ist eine Sammlung von Kindobjektelementen der Wert, der auf die Sammlungseigenschaft festgelegt wird.
Das folgende Beispiel zeigt die Sammlungssyntax zum Festlegen von Werten der GradientStops Eigenschaft.
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<!-- no explicit new GradientStopCollection, parser knows how to find or create -->
<GradientStop Offset="0.0" Color="Red" />
<GradientStop Offset="1.0" Color="Blue" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
XAML-Inhaltseigenschaften
XAML gibt ein Sprachfeature an, mit dem eine Klasse genau eine ihrer Eigenschaften als XAML-Inhaltseigenschaft festlegen kann. Untergeordnete Elemente dieses Objektelements werden verwendet, um den Wert dieser Inhaltseigenschaft festzulegen. Anders ausgedrückt: Nur für die Inhaltseigenschaft können Sie ein Eigenschaftselement weglassen, wenn Sie diese Eigenschaft im XAML-Markup festlegen und so eine deutlichere Elternteil/Kindelement-Metapher im Markup erstellen.
Beispielsweise spezifiziert Border eine Inhaltseigenschaft von Child. Die folgenden beiden Border Elemente werden identisch behandelt. Die erste Methode nutzt die Syntax der Inhaltsproperty und lässt das Border.Child
-Propertyelement weg. Die zweite zeigt Border.Child
explizit an.
<Border>
<TextBox Width="300"/>
</Border>
<!--explicit equivalent-->
<Border>
<Border.Child>
<TextBox Width="300"/>
</Border.Child>
</Border>
Als Regel der XAML-Sprache muss der Wert einer XAML-Inhaltseigenschaft entweder vollständig vor oder vollständig nach anderen Eigenschaftselementen in diesem Objektelement angegeben werden. Beispielsweise wird das folgende Markup nicht kompiliert.
<Button>I am a
<Button.Background>Blue</Button.Background>
blue button</Button>
Weitere Informationen zu den Besonderheiten der XAML-Syntax finden Sie unter XAML-Syntax im Detail.
Textinhalte
Eine kleine Anzahl von XAML-Elementen kann Text direkt als Inhalt verarbeiten. Um dies zu aktivieren, muss einer der folgenden Fälle zutreffen:
Die Klasse muss eine Inhaltseigenschaft deklarieren, und diese Inhaltseigenschaft muss einen Typ aufweisen, der einer Zeichenfolge zugewiesen werden kann (der Typ könnte sein Object). Beispielsweise verwendet jede ContentControlContent als ihre Inhaltseigenschaft und hat den Typ Object. Dies unterstützt die folgende Verwendung auf einem ContentControl, wie einem Button:
<Button>Hello</Button>
.Der Typ muss einen Typkonverter deklarieren, in diesem Fall wird der Textinhalt als Initialisierungstext für diesen Typkonverter verwendet. Zum Beispiel konvertiert
<Brush>Blue</Brush>
den Inhaltswert vonBlue
in einer Pinselkomponente. Dieser Fall ist in der Praxis weniger üblich.Der Typ muss ein bekannter XAML-Sprachgrundtyp sein.
Kombinierte Inhaltseigenschaften und Sammlungssyntax
Betrachten Sie dieses Beispiel.
<StackPanel>
<Button>First Button</Button>
<Button>Second Button</Button>
</StackPanel>
Hier ist jedes Button ein untergeordnetes Element von StackPanel. Dies ist ein optimiertes und intuitives Markup, das aus zwei verschiedenen Gründen zwei Tags ausgelassen.
Ausgelassenes Element der StackPanel.Children-Eigenschaft:StackPanel wird abgeleitet von Panel. Panel definiert Panel.Children als seine XAML-Inhaltseigenschaft.
Ausgelassenes UIElementCollection-Objektelement: Die Panel.Children Eigenschaft verwendet den Typ UIElementCollection, der implementiert IListwird. Das Elementtag der Auflistung kann ausgelassen werden, auf der Grundlage von den XAML-Regeln zur Verarbeitung von Auflistungen wie IList. (In diesem Fall kann UIElementCollection tatsächlich nicht instanziiert werden, da es keinen parameterlosen Konstruktor zur Verfügung stellt. Deshalb ist das UIElementCollection-Objektelement auskommentiert).
<StackPanel>
<StackPanel.Children>
<!--<UIElementCollection>-->
<Button>First Button</Button>
<Button>Second Button</Button>
<!--</UIElementCollection>-->
</StackPanel.Children>
</StackPanel>
Attributsyntax (Ereignisse)
Attributsyntax kann auch für Member verwendet werden, die Ereignisse anstatt Eigenschaften sind. In diesem Fall ist der Name des Attributs der Name des Ereignisses. In der WPF-Implementierung von Ereignissen für XAML ist der Wert des Attributs der Name eines Handlers, der den Delegaten dieses Ereignisses implementiert. Das folgende Markup weist beispielsweise einem im Markup erstellten Click einen Handler für das Button-Ereignis zu.
<Button Click="Button_Click" >Click Me!</Button>
In WPF gibt es mehr zu Ereignissen und XAML als nur in diesem Beispiel für die Attributsyntax. Sie könnten sich beispielsweise fragen, was die ClickHandler
hier referenzierten Elemente darstellen und wie sie definiert sind. Dies wird im bevorstehenden Abschnitt Ereignisse und XAML-Code-Behind in diesem Artikel erläutert.
Groß- und Kleinschreibung und Leerzeichen in XAML
Im Allgemeinen wird bei XAML die Groß-/Kleinschreibung beachtet. Zur Auflösung von Basistypen berücksichtigt WPF XAML die Groß- und Kleinschreibung nach denselben Regeln wie die CLR. Objektelemente, Eigenschaftselemente und Attributnamen müssen alle unter Beachtung der Groß-/Kleinschreibung angegeben werden, wenn sie mit dem zugrunde liegenden Typ in der Assembly oder mit einem Mitglied eines Typs verglichen werden. XAML-Sprachschlüsselwörter und -Grundtypen sind ebenfalls case-sensitive. Bei Werten wird nicht immer zwischen Groß- und Kleinschreibung unterschieden. Die Groß-/Kleinschreibung für Werte hängt vom Verhalten des Typkonverters ab, das der Eigenschaft zugeordnet ist, die den Wert verwendet, oder vom Typ des Eigenschaftswerts. Eigenschaften, die den Boolean-Typ verwenden, können entweder true
oder True
als gleichwertige Werte verwenden werden, aber dies ist nur möglich, weil die Konvertierung des nativen WPF-XAML-Parsers von Zeichenfolgen zu Boolean diese bereits als Entsprechungen zulässt.
WPF-XAML-Prozessoren und Serialisierer ignorieren oder entfernen alle unbedeutenden Leerzeichen und normalisieren alle bedeutenden Leerzeichen. Dies entspricht den Standardmäßigen Empfehlungen für das Leerzeichenverhalten der XAML-Spezifikation. Dieses Verhalten ist nur dann von Bedeutung, wenn Sie Zeichenfolgen innerhalb von XAML-Inhaltseigenschaften angeben. In einfachsten Worten konvertiert XAML Leerzeichen, Zeilenumbruch- und Tabulatorzeichen in ein Leerzeichen und behält dann eines bei, wenn es an einem der Enden einer zusammenhängenden Zeichenfolge gefunden wird. Die vollständige Erläuterung der XAML-Leerraumbehandlung wird in diesem Artikel nicht behandelt. Weitere Informationen finden Sie unter "Leerraumverarbeitung" in XAML.
Markuperweiterungen
Markuperweiterungen sind ein XAML-Sprachkonzept. Wenn der Wert einer Attributsyntax bereitgestellt wird, geben geschweifte Klammern ({
und }
) eine Markuperweiterungsverwendung an. Diese Verwendung leitet die XAML-Verarbeitung an, um von der allgemeinen Behandlung von Attributwerten als wörtliche Zeichenfolge oder als zeichenfolgenkonvertierbarer Wert abzuweichen.
Die am häufigsten in der WPF-App-Programmierung verwendeten Markuperweiterungen sind Binding
, die für Datenbindungsausdrücke, sowie die Ressourcenverweise StaticResource
und DynamicResource
genutzt werden. Mithilfe von Markuperweiterungen können Sie mithilfe der Attributsyntax Werte für Eigenschaften bereitstellen, auch wenn diese Eigenschaft im Allgemeinen keine Attributsyntax unterstützt. Markuperweiterungen verwenden häufig Zwischenausdrucktypen, um Features wie das Zurückstellen von Werten oder das Verweisen auf andere Objekte zu ermöglichen, die nur zur Laufzeit vorhanden sind.
Das folgende Markup legt beispielsweise den Wert der Eigenschaft mithilfe der Style Attributsyntax fest. Die Style Eigenschaft verwendet eine Instanz der Style Klasse, die standardmäßig nicht durch eine Attributsyntaxzeichenfolge instanziiert werden konnte. In diesem Fall verweist das Attribut jedoch auf eine bestimmte Markuperweiterung. StaticResource
Wenn diese Markuperweiterung verarbeitet wird, wird ein Verweis auf eine Formatvorlage zurückgegeben, die zuvor als Schlüsselressource in einem Ressourcenverzeichnis instanziiert wurde.
<Window x:Class="index.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="100" Width="300">
<Window.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
<Style TargetType="Border" x:Key="PageBackground">
<Setter Property="BorderBrush" Value="Blue"/>
<Setter Property="BorderThickness" Value="5" />
</Style>
</Window.Resources>
<Border Style="{StaticResource PageBackground}">
<StackPanel>
<TextBlock Text="Hello" />
</StackPanel>
</Border>
</Window>
Eine Referenzliste aller Markuperweiterungen für XAML, die speziell in WPF implementiert wurden, finden Sie unter WPF-XAML-Erweiterungen. Eine Liste von Verweisen auf die Markuperweiterungen, die von System.Xaml definiert sind und für .NET-XAML-Implementierungen verbreitet verfügbar sind, finden Sie unter Sprachfunktionen des XAML-Namespaces (x:) Language Features. Weitere Informationen zu Markuperweiterungskonzepten finden Sie unter Markuperweiterungen und WPF-XAML.
Typumwandler
In der XAML-Syntax im Kurzen Abschnitt wurde angegeben, dass der Attributwert durch eine Zeichenfolge festgelegt werden muss. Die grundlegende, systemeigene Behandlung der Konvertierung von Zeichenfolgen in andere Objekttypen oder Grundtypenwerte basiert auf dem String Typ selbst sowie der systemeigenen Verarbeitung für bestimmte Typen wie DateTime z. B. oder Uri. Viele WPF-Typen oder Member dieser Typen erweitern jedoch das grundlegende Verarbeitungsverhalten von Zeichenfolgenattributen so, dass Instanzen komplexerer Objekttypen als Zeichenfolgen und Attribute angegeben werden können.
Die Thickness Struktur ist ein Beispiel für einen Typ, der eine Typkonvertierung für XAML-Verwendungen aktiviert hat. Thickness gibt Maßangaben innerhalb eines geschachtelten Rechtecks an und wird als Wert für Eigenschaften wie Margin genutzt. Durch das Einfügen eines Typkonverters auf Thickness sind alle Eigenschaften, die einen Thickness verwenden, in XAML leichter anzugeben, da sie als Attribute angegeben werden können. Im folgenden Beispiel wird die Syntax der Typumwandlung und der Attribute verwendet, um einen Wert für ein Margin bereitzustellen.
<Button Margin="10,20,10,30" Content="Click me"/>
Das vorherige Attributsyntax-Beispiel entspricht dem folgenden ausführlicheren Syntax-Beispiel, bei dem Margin stattdessen durch die Eigenschafts-Elementsyntax festgelegt wird, die ein Thickness-Objektelement enthält. Die vier zentralen Eigenschaften von Thickness werden als Attribute auf der neuen Instanz festgelegt.
<Button Content="Click me">
<Button.Margin>
<Thickness Left="10" Top="20" Right="10" Bottom="30"/>
</Button.Margin>
</Button>
Hinweis
Es gibt auch eine begrenzte Anzahl von Objekten, bei denen die Typkonvertierung die einzige öffentliche Möglichkeit ist, eine Eigenschaft auf diesen Typ festzulegen, ohne eine Unterklasse einzubeziehen, da der Typ selbst keinen parameterlosen Konstruktor aufweist. Beispiel ist Cursor.
Weitere Informationen zur Typkonvertierung finden Sie unter TypeConverters und XAML.
Stammelemente und Namespaces
Eine XAML-Datei darf nur ein Stammelement aufweisen, um sowohl eine wohlgeformte XML-Datei als auch eine gültige XAML-Datei zu sein. Für typische WPF-Szenarien verwenden Sie ein Stammelement, das im WPF-App-Modell eine prominente Bedeutung hat (z WindowPage . B. für eine Seite, ResourceDictionary für ein externes Wörterbuch oder Application für die App-Definition). Das folgende Beispiel zeigt das Stammelement einer typischen XAML-Datei für eine WPF-Seite mit dem Stammelement von Page.
<Page x:Class="index.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Page1">
</Page>
Das Stammelement enthält auch die Attribute xmlns
und xmlns:x
. Diese Attribute geben einem XAML-Prozessor an, welche XAML-Namespaces die Typdefinitionen für die implementierenden Typen enthalten, auf die das Markup als Elemente verweist. Das xmlns
Attribut gibt speziell den standardmäßigen XAML-Namespace an. Innerhalb des standardmäßigen XAML-Namespaces können Objektelemente im Markup ohne Präfix angegeben werden. Für die meisten WPF-App-Szenarien und für fast alle Beispiele im WPF-Abschnitt des SDK wird der standardmäßige XAML-Namespace dem WPF-Namespace http://schemas.microsoft.com/winfx/2006/xaml/presentation
zugeordnet. Das xmlns:x
Attribut gibt einen zusätzlichen XAML-Namespace an, der dem XAML-Sprachnamespace http://schemas.microsoft.com/winfx/2006/xaml
zugeordnet ist.
Diese Verwendung von xmlns
zum Definieren eines Bereichs für die Nutzung und Zuordnung eines Namensbereichs entspricht der XML-1.0-Spezifikation. XAML-NameScopes unterscheiden sich von XML-NameScopes nur darin, dass ein XAML-NameScope auch etwas darüber impliziert, wie die Elemente des NameScopes von Typen unterstützt werden, wenn es um die Typauflösung geht und die XAML analysiert.
Die xmlns
Attribute sind nur für das Stammelement jeder XAML-Datei unbedingt erforderlich.
xmlns
Definitionen gelten für alle untergeordneten Elemente des Stammelements (dieses Verhalten entspricht erneut der XML 1.0-Spezifikation für xmlns
.) xmlns
attributen sind auch für andere Elemente unter dem Stamm zulässig und gelten für alle untergeordneten Elemente des definierenden Elements. Eine häufige Definition oder Neudefinition von XAML-Namespaces kann jedoch zu einem XAML-Markupstil führen, der schwer zu lesen ist.
Die WPF-Implementierung des XAML-Prozessors enthält eine Infrastruktur, die die WPF-Kernassemblys berücksichtigt. Die WPF-Kernassemblies sind dafür bekannt, die Typen zu enthalten, die die WPF-Zuordnungen zum standardmäßigen XAML-Namespace unterstützen. Dies wird über die Konfiguration ermöglicht, die Teil der Projektbuilddatei und der WPF-Build- und Projektsysteme ist. Daher ist das Deklarieren des standardmäßigen XAML-Namespace als Standard xmlns
alles, was erforderlich ist, um auf XAML-Elemente zu verweisen, die aus WPF-Assemblys stammen.
Das x: Präfix
Im vorherigen Stammelementbeispiel wurde das Präfix x:
verwendet, um den XAML-Namespace http://schemas.microsoft.com/winfx/2006/xaml
zuzuordnen, der den dedizierten XAML-Namespace darstellt, der XAML-Sprachkonstrukte unterstützt. Dieses x:
Präfix wird zum Zuordnen dieses XAML-Namespaces in den Vorlagen für Projekte, in Beispielen und in der Dokumentation in diesem SDK verwendet. Der XAML-Namespace für die XAML-Sprache enthält mehrere Programmierkonstrukte, die Sie häufig in Xaml verwenden werden. Im Folgenden finden Sie eine Auflistung der am häufigsten verwendeten x:
Präfixprogrammierungskonstrukte:
x:Key: Legt einen eindeutigen Schlüssel für jede Ressource in einem ResourceDictionary (oder ähnlichen Wörterbuchkonzepten in anderen Frameworks) fest.
x:Key
wird wahrscheinlich 90 Prozent der Verwendungen ausmachen, die Sie im typischen Markup von WPF-Apps sehen.x:Class: Gibt den CLR-Namespace und den Klassennamen für die Klasse an, die CodeBehind für eine XAML-Seite bereitstellt. Sie müssen eine solche Klasse haben, um Code-behind gemäß dem WPF-Programmiermodell zu unterstützen. Daher werden Sie fast immer
x:
zugeordnet sehen, selbst wenn keine Ressourcen vorhanden sind.x:Name: Gibt einen Laufzeitobjektnamen für die Instanz an, die im Laufzeitcode vorhanden ist, nachdem ein Objektelement verarbeitet wurde. Im Allgemeinen verwenden Sie häufig eine WPF-definierte entsprechungseigenschaft für x:Name. Solche Eigenschaften werden speziell einer CLR-Sicherungseigenschaft zugeordnet und eignen sich daher für die App-Programmierung, bei der Sie häufig Laufzeitcode verwenden, um die benannten Elemente aus initialisiertem XAML zu finden. Die am häufigsten verwendete Eigenschaft ist FrameworkElement.Name. Möglicherweise verwenden Sie weiterhin "x:Name ", wenn die entsprechende WPF-Framework-Level-Eigenschaft Name in einem bestimmten Typ nicht unterstützt wird. Dies geschieht in bestimmten Animationsszenarien.
x:Static: Aktiviert einen Verweis, der einen statischen Wert zurückgibt, der andernfalls keine XAML-kompatible Eigenschaft ist.
x:Type: Erstellt einen Type Verweis basierend auf einem Typnamen. Dies wird verwendet, um Attribute wie Type anzugeben, die Style.TargetType nutzen, obwohl die Eigenschaft häufig eine native Zeichenfolgen-zu-Type-Konvertierung hat, sodass die Verwendung der x:Type-Markuperweiterung optional ist.
Es gibt zusätzliche Programmierkonstrukte im x:
Präfix-/XAML-Namespace, die nicht so häufig sind. Ausführliche Informationen finden Sie unter XAML-Namespace (x:) Sprachfeatures.
Benutzerdefinierte Präfixe und benutzerdefinierte Typen
Für Ihre eigenen benutzerdefinierten Assemblys oder für Assemblys außerhalb des WPF-Kerns von PresentationCore, PresentationFramework und WindowsBase können Sie die Assembly als Teil einer benutzerdefinierten xmlns
Zuordnung angeben. Sie können dann auf Typen aus dieser Assembly in XAML verweisen, solange dieser Typ ordnungsgemäß implementiert ist, um die XAML-Verwendungen zu unterstützen, die Sie versuchen.
Im Folgenden sehen Sie ein grundlegendes Beispiel für die Funktionsweise von benutzerdefinierten Präfixen im XAML-Markup. Das Präfix custom
wird im Stammelementtag definiert und einer bestimmten Assembly zugeordnet, die verpackt und für die App verfügbar ist. Diese Assembly enthält einen Typ NumericUpDown
, der implementiert wird, um die allgemeine XAML-Verwendung zu unterstützen und eine Klassenvererbung zu verwenden, die das Einfügen an diesem bestimmten Punkt in einem WPF-XAML-Inhaltsmodell zulässt. Eine Instanz dieses NumericUpDown
Steuerelements wird mithilfe des Präfixes als Objektelement deklariert, sodass ein XAML-Parser weiß, welcher XAML-Namespace den Typ enthält, und daher, wo die Sicherungsassembly die Typdefinition enthält.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:NumericUpDownCustomControl;assembly=CustomLibrary"
>
<StackPanel Name="LayoutRoot">
<custom:NumericUpDown Name="numericCtrl1" Width="100" Height="60"/>
...
</StackPanel>
</Page>
Weitere Informationen zu benutzerdefinierten Typen in XAML finden Sie unter XAML und benutzerdefinierte Klassen für WPF.
Weitere Informationen dazu, wie XML-Namespaces und Codenamespaces in Assemblys verknüpft sind, finden Sie unter XAML-Namespaces und Namespacezuordnung für WPF-XAML.
Ereignisse und XAML-Code-Behind
Die meisten WPF-Anwendungen bestehen sowohl aus XAML-Markup als auch aus Code-Behind. Innerhalb eines Projekts wird der XAML-Code als .xaml
Datei geschrieben, und eine CLR-Sprache wie Microsoft Visual Basic oder C# wird verwendet, um eine CodeBehind-Datei zu schreiben. Wenn eine XAML-Datei als Teil der WPF-Programmierungs- und Anwendungsmodelle kompiliert wird, wird der Speicherort der XAML-CodeBehind-Datei für eine XAML-Datei durch Angeben eines Namespaces und einer Klasse als x:Class
Attribut des Stammelements des XAML-Codes identifiziert.
In den bisherigen Beispielen haben Sie mehrere Schaltflächen gesehen, aber keine dieser Schaltflächen hatte bisher ein logisches Verhalten, das ihnen zugeordnet war. Der primäre Mechanismus auf Anwendungsebene zum Hinzufügen eines Verhaltens für ein Objektelement besteht darin, ein vorhandenes Ereignis der Elementklasse zu verwenden und einen bestimmten Handler für dieses Ereignis zu schreiben, der aufgerufen wird, wenn dieses Ereignis zur Laufzeit ausgelöst wird. Der Ereignisname und der Name des zu verwendenden Handlers werden im Markup angegeben, während der Code, der den Handler implementiert, im CodeBehind definiert ist.
<Page x:Class="ExampleNamespace.ExamplePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Button Click="Button_Click">Click me</Button>
</StackPanel>
</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace ExampleNamespace;
public partial class ExamplePage : Page
{
public ExamplePage() =>
InitializeComponent();
private void Button_Click(object sender, RoutedEventArgs e)
{
var buttonControl = (Button)e.Source;
buttonControl.Foreground = Brushes.Red;
}
}
Class ExamplePage
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
Dim buttonControl = DirectCast(e.Source, Button)
buttonControl.Foreground = Brushes.Red
End Sub
End Class
Beachten Sie, dass die CodeBehind-Datei den CLR-Namespace ExampleNamespace
verwendet (der Namespace ist in Visual Basic nicht sichtbar) und ExamplePage
als partielle Klasse innerhalb dieses Namespaces deklariert. Der x:Class
-Attributwert entspricht dem von ExampleNamespace
.
ExamplePage
, das im Markup-Stamm bereitgestellt wurde. Der WPF-Markupcompiler erstellt eine partielle Klasse für jede kompilierte XAML-Datei, indem eine Klasse vom Stammelementtyp abgeleitet wird. Wenn Sie CodeBehind bereitstellen, der auch dieselbe Partielle Klasse definiert, wird der resultierende Code innerhalb desselben Namespaces und der Klasse der kompilierten App kombiniert.
Von Bedeutung
In Visual Basic wird der Stammnamespace sowohl für XAML als auch für Code-Behind impliziert. Nur geschachtelte Namespaces sind sichtbar. In diesem Artikel wird der XAML-Code des C#-Projekts veranschaulicht.
Weitere Informationen zu den Anforderungen für die CodeBehind-Programmierung in WPF finden Sie unter CodeBehind-, Ereignishandler- und Partielle Klassenanforderungen in WPF.
Wenn Sie keine separate CodeBehind-Datei erstellen möchten, können Sie ihren Code auch in einer XAML-Datei inlineieren. Inlinecode ist jedoch eine weniger vielseitige Technik, die erhebliche Einschränkungen aufweist. Weitere Informationen finden Sie unter Code-Behind und XAML in WPF.
Routingereignisse
Ein bestimmtes Ereignisfeature, das für WPF grundlegend ist, ist ein Routingereignis. Geroutete Ereignisse ermöglichen es einem Element, ein Ereignis zu behandeln, das von einem anderen Element ausgelöst wurde, solange die Elemente über eine Baumbeziehung verbunden sind. Wenn Sie die Ereignisbehandlung mit einem XAML-Attribut angeben, kann das Routingereignis auf jedes Element überwacht und behandelt werden, einschließlich Elementen, die dieses bestimmte Ereignis nicht in der Klassenmembertabelle auflisten. Dazu wird das Attribut "Ereignisname" mit dem eigenen Klassennamen qualifiziert. Beispielsweise könnte das übergeordnete Element StackPanel
im fortlaufenden StackPanel
/ Button
Beispiel einen Handler für das Ereignis des Schaltflächenelements des untergeordneten Elements Click registrieren, indem der Attributname Button.Click
auf dem Objektelement StackPanel
mit Ihrem Handlernamen als Attributwert angegeben wird. Weitere Informationen finden Sie unter Übersicht über Routingereignisse.
Benannte Elemente
Standardmäßig verfügt die Objektinstanz, die in einem Objektdiagramm erstellt wird, indem ein XAML-Objektelement verarbeitet wird, keinen eindeutigen Bezeichner oder Objektverweis. Wenn Sie hingegen einen Konstruktor im Code aufrufen, verwenden Sie fast immer das Konstruktorergebnis, um eine Variable auf die erstellte Instanz festzulegen, damit Sie später im Code auf die Instanz verweisen können. Um standardisierten Zugriff auf Objekte bereitzustellen, die über eine Markupdefinition erstellt wurden, definiert XAML das x:Name-Attribut. Sie können den Wert des x:Name
Attributs für ein beliebiges Objektelement festlegen. In Ihrem Code-Behind entspricht der von Ihnen gewählte Bezeichner einer Instanzvariablen, die auf die konstruierte Instanz verweist. In allen Fällen funktionieren benannte Elemente so, als wären sie Objektinstanzen (der Name verweist auf diese Instanz), und Ihr CodeBehind kann auf die benannten Elemente verweisen, um Laufzeitinteraktionen innerhalb der App zu behandeln. Diese Verbindung zwischen Instanzen und Variablen wird vom WPF-XAML-Markupcompiler erreicht und genauer gesagt umfassen Features und Muster, wie InitializeComponent, die in diesem Artikel nicht ausführlich erläutert werden.
Xaml-Elemente auf WPF-Frameworkebene erben eine Name Eigenschaft, die dem definierten x:Name
XAML-Attribut entspricht. Bestimmte andere Klassen bieten auch Entsprechungen auf Eigenschaftsebene für x:Name
an, die normalerweise als Name
Eigenschaft definiert sind. Wenn Sie generell keine Name
-Eigenschaft in der Membertabelle für Ihr ausgewähltes Element oder Typ finden können, verwenden Sie stattdessen x:Name
. Die x:Name
Werte stellen einen Bezeichner für ein XAML-Element bereit, das zur Laufzeit genutzt werden kann, entweder durch spezifische Subsysteme oder durch Hilfsmethoden wie FindName z.B.
Im folgenden Beispiel wird Name auf einem StackPanel Element festgelegt. Dann referenziert ein Handler auf einem Button innerhalb dieser StackPanel das StackPanel über seine Instanzreferenz buttonContainer
, die durch Name festgelegt ist.
<StackPanel Name="buttonContainer">
<Button Click="RemoveThis_Click">Click to remove this button</Button>
</StackPanel>
private void RemoveThis_Click(object sender, RoutedEventArgs e)
{
var element = (FrameworkElement)e.Source;
if (buttonContainer.Children.Contains(element))
buttonContainer.Children.Remove(element);
}
Private Sub RemoveThis_Click(sender As Object, e As RoutedEventArgs)
Dim element = DirectCast(e.Source, FrameworkElement)
If buttonContainer.Children.Contains(element) Then
buttonContainer.Children.Remove(element)
End If
End Sub
Genau wie eine Variable unterliegt der XAML-Name einer Instanz dem Konzept des Geltungsbereichs, sodass Namen innerhalb eines bestimmten, vorhersagbaren Geltungsbereichs eindeutig erzwungen werden können. Das primäre Markup, das eine Seite definiert, zeigt einen eindeutigen XAML-NameScope an, wobei die XAML-NameScope-Grenze das Stammelement dieser Seite ist. Andere Markupquellen können jedoch zur Laufzeit mit einer Seite interagieren, z. B. Formatvorlagen oder Vorlagen innerhalb von Formatvorlagen, und solche Markupquellen verfügen häufig über eigene XAML-NameScopes, die nicht unbedingt mit dem XAML-NameScope der Seite verbunden sind. Weitere Informationen zu x:Name
und XAML-NameScopes finden Sie unter Name"x:Name-Direktive" oder "WPF-XAML-NameScopes".
Angefügte Eigenschaften und angefügte Ereignisse
XAML gibt ein Sprachfeature an, mit dem bestimmte Eigenschaften oder Ereignisse für jedes Element angegeben werden können, auch wenn die Eigenschaft oder das Ereignis nicht in den Definitionen des Typs für das Element vorhanden ist, für das es festgelegt wird. Die Eigenschaftenversion dieses Features wird als angefügte Eigenschaft bezeichnet, die Ereignisversion wird als angefügtes Ereignis bezeichnet. Konzeptionell können Sie sich angefügte Eigenschaften und angefügte Ereignisse als globale Member vorstellen, die für jede XAML-Element-/Objektinstanz festgelegt werden können. Dieses Element/diese Klasse oder eine größere Infrastruktur muss jedoch einen unterstützenden Eigenschaftenspeicher für die angefügten Werte unterstützen.
Angefügte Eigenschaften in XAML werden in der Regel durch Attributsyntax verwendet. In der Attributsyntax geben Sie eine angefügte Eigenschaft im Formular ownerType.propertyName
an.
Oberflächlich ähnelt dies einer Eigenschaftselementverwendung, aber in diesem Fall ist die ownerType
angegebene Eigenschaft immer ein anderer Typ als das Objektelement, bei dem die angefügte Eigenschaft festgelegt wird.
ownerType
ist der Typ, der die Accessormethoden bereitstellt, die von einem XAML-Prozessor erforderlich sind, um den Wert der angefügten Eigenschaft abzurufen oder festzulegen.
Das häufigste Szenario für angefügte Eigenschaften besteht darin, untergeordneten Elementen das Melden eines Eigenschaftswerts an das übergeordnete Element zu ermöglichen.
Das folgende Beispiel veranschaulicht die DockPanel.Dock angefügte Eigenschaft. Die DockPanel Klasse definiert die Accessoren für DockPanel.Dock und besitzt die angefügte Eigenschaft. Die DockPanel Klasse enthält auch Logik, die die untergeordneten Elemente durchläuft und die einzelnen Elemente speziell auf einen festgelegten Wert überprüft DockPanel.Dock. Wenn ein Wert gefunden wird, wird dieser Wert während des Layouts verwendet, um die untergeordneten Elemente zu positionieren. Die Verwendung der DockPanel.Dock angefügten Eigenschaft und diese Positionierungsfunktion ist tatsächlich das motivierende Szenario für die DockPanel Klasse.
<DockPanel>
<Button DockPanel.Dock="Left" Width="100" Height="20">I am on the left</Button>
<Button DockPanel.Dock="Right" Width="100" Height="20">I am on the right</Button>
</DockPanel>
In WPF werden die meisten oder alle angefügten Eigenschaften auch als Abhängigkeitseigenschaften implementiert. Weitere Informationen finden Sie unter "Übersicht über angefügte Eigenschaften".
Angefügte Ereignisse verwenden eine ähnliche ownerType.eventName
Form von Attributsyntax. Genau wie die nicht angefügten Ereignisse gibt der Attributwert für ein angefügtes Ereignis in XAML den Namen der Handlermethode an, die aufgerufen wird, wenn das Ereignis für das Element behandelt wird. "Verwendungen von angefügten Ereignissen in WPF-XAML sind seltener." Weitere Informationen finden Sie unter "Übersicht über angefügte Ereignisse".
Basistypen
Zugrunde liegendes WPF-XAML und sein XAML-Namespace sind eine Sammlung von Typen, die CLR-Objekten und Markupelementen für XAML entsprechen. Allerdings können nicht alle Klassen Elementen zugeordnet werden. Abstrakte Klassen, z ButtonBase. B. und bestimmte nicht abstrakte Basisklassen, werden für die Vererbung im CLR-Objektmodell verwendet. Basisklassen, einschließlich abstrakter Klassen, sind für die XAML-Entwicklung immer noch wichtig, da jedes der konkreten XAML-Elemente Member von einer Basisklasse in der Hierarchie erbt. Häufig enthalten diese Member Eigenschaften, die als Attribute für das Element festgelegt werden können, oder Ereignisse, die behandelt werden können. FrameworkElement ist die konkrete Basis-UI-Klasse von WPF auf der WPF-Frameworkebene. Beim Entwerfen der Benutzeroberfläche verwenden Sie verschiedene Formen, Panels, Dekorateure oder Steuerelementklassen, von denen alle abgeleitet FrameworkElementsind. Eine verwandte Basisklasse, FrameworkContentElement, unterstützt dokumentorientierte Elemente, die gut für eine Flusslayoutpräsentation funktionieren, und verwendet APIs, die absichtlich die APIs in FrameworkElement spiegeln. Die Kombination von Attributen auf Elementebene und einem CLR-Objektmodell bietet Ihnen eine Reihe allgemeiner Eigenschaften, die für die meisten konkreten XAML-Elemente festgelegt werden können, unabhängig vom spezifischen XAML-Element und dem zugrunde liegenden Typ.
Sicherheit
XAML ist eine Markupsprache, die die Objektinstanziierung und -ausführung direkt darstellt. Aus diesem Grund können elemente, die in XAML erstellt wurden, mit Systemressourcen (z. B. Netzwerkzugriff, Dateisystem-E/A) interagieren, wie ihr App-Code tut. XAML hat auch den gleichen Zugriff auf die Systemressourcen wie die Host-App.
Codezugriffssicherheit (Code Access Security, CAS) in WPF
Im Gegensatz zu .NET Framework unterstützt WPF für .NET CAS nicht. Weitere Informationen finden Sie unter Unterschiede bei der Codezugriffssicherheit.
XAML aus dem Code laden
XAML kann verwendet werden, um die gesamte Benutzeroberfläche zu definieren, aber manchmal ist es auch geeignet, nur ein Stück der Benutzeroberfläche in XAML zu definieren. Diese Funktion kann verwendet werden, um:
- Partielle Anpassung aktivieren.
- Lokaler Speicher von UI-Informationen.
- Modellieren eines Geschäftsobjekts.
Der Schlüssel zu diesen Szenarien ist die XamlReader Klasse und ihre Load Methode. Die Eingabe ist eine XAML-Datei, und die Ausgabe ist ein Objekt, das die gesamte Laufzeitstruktur von Objekten darstellt, die aus diesem Markup erstellt wurden. Anschließend können Sie das Objekt als Eigenschaft eines anderen Objekts einfügen, das bereits in der App vorhanden ist. Solange sich die Eigenschaft im Inhaltsmodell befindet und Über Anzeigefunktionen verfügt, mit denen das Ausführungsmodul benachrichtigt wird, dass der App neue Inhalte hinzugefügt wurden, können Sie den Inhalt einer ausgeführten App ganz einfach ändern, indem Sie dynamisch in XAML laden.
Siehe auch
.NET Desktop feedback