Vue d’ensemble XAML (WPF .NET)
Cet article décrit les fonctionnalités du langage XAML et montre comment utiliser XAML pour écrire des applications Windows Presentation Foundation (WPF). Cet article décrit spécifiquement xaml comme implémenté par WPF. XAML lui-même est un concept de langage plus grand que WPF.
Important
La documentation du Guide du bureau pour .NET 6 et .NET 5 (y compris .NET Core 3.1) est en cours de construction.
Qu’est-ce que XAML
XAML est un langage de balisage déclaratif. Comme appliqué au modèle de programmation .NET Core, XAML simplifie la création d’une interface utilisateur pour une application .NET Core. Vous pouvez créer des éléments d’interface utilisateur visibles dans le balisage XAML déclaratif, puis séparer la définition de l’interface utilisateur de la logique d’exécution à l’aide de fichiers code-behind joints au balisage via des définitions de classes partielles. XAML représente directement l’instanciation d’objets dans un ensemble spécifique de types de stockage définis dans des assemblys. C’est ce qui le différencie de la plupart des autres langages de balisage, qui sont en général des langages interprétés sans un lien aussi direct à un système de type de stockage. XAML permet un flux de travail où des parties distinctes peuvent travailler sur l’interface utilisateur et la logique d’une application, à l’aide d’outils potentiellement différents.
Représentés sous forme de texte, les fichiers XAML sont des fichiers XML qui ont généralement l’extension .xaml. Les fichiers peuvent être encodés par un encodage XML, même si UTF-8 est l’encodage classique.
L’exemple suivant montre comment créer un bouton dans le cadre d’une interface utilisateur. Cet exemple est destiné à vous donner une saveur de la façon dont XAML représente les métaphores courantes de programmation d’interface utilisateur (il ne s’agit pas d’un exemple complet).
<StackPanel>
<Button Content="Click Me"/>
</StackPanel>
Syntaxe XAML en bref
Les sections suivantes expliquent les bases de la syntaxe XAML et donnent un court exemple de balisage. Ces sections ne sont pas destinées à fournir des informations complètes sur chaque formulaire de syntaxe, telles que la façon dont elles sont représentées dans le système de type de stockage. Pour plus d’informations sur les spécificités de la syntaxe XAML, consultez Syntaxe XAML en détail.
La majeure partie du matériel des sections suivantes sera élémentaire pour vous si vous connaissez déjà le langage XML. C’est une conséquence d’un des principes de base de la conception du langage XAML. Le langage XAML définit les concepts de son propre, mais ces concepts fonctionnent dans le langage XML et le formulaire de balisage.
Éléments d’objet XAML
Un élément objet déclare généralement une instance d’un type. Ce type est défini dans les assemblys référencés par la technologie qui utilise XAML comme langage.
La syntaxe d’un élément objet commence toujours par un signe « inférieur à » (<). Le nom du type dans lequel vous souhaitez créer une instance suit. (Le nom peut inclure un préfixe, un concept qui sera expliqué plus tard.) Après cela, vous pouvez éventuellement déclarer des attributs sur l’élément objet. Pour terminer la balise d’élément d’objet, terminez par un crochet d’angle fermant (>). Vous pouvez plutôt utiliser un formulaire auto-fermant qui n’a pas de contenu, en effectuant la balise avec une barre oblique et un crochet d’angle fermant en succession (/>). Par exemple, examinez à nouveau l’extrait de balisage précédemment affiché.
<StackPanel>
<Button Content="Click Me"/>
</StackPanel>
Deux éléments objet sont spécifiés : <StackPanel> (avec du contenu et suivi d’une balise de fermeture) et <Button .../> (avec plusieurs attributs et la forme de fermeture automatique). Les éléments StackPanel d’objet et Button chaque mappage au nom d’une classe définie par WPF et fait partie des assemblys WPF. Lorsque vous spécifiez une balise d’élément d’objet, vous créez une instruction pour le traitement XAML pour créer une nouvelle instance du type sous-jacent. Chaque instance est créée en appelant le constructeur sans paramètre du type sous-jacent lors de l’analyse et du chargement du code XAML.
Syntaxe d’attribut (propriétés)
Les propriétés d’un objet peuvent souvent être exprimées en tant qu’attributs de l’élément objet. La syntaxe d’attribut nomme la propriété d’objet définie, suivie de l’opérateur d’affectation (=). La valeur d’un attribut est toujours spécifiée sous la forme d’une chaîne comprise entre guillemets.
La syntaxe d’attribut est la syntaxe de définition de propriétés la plus simple et la plus intuitive pour les développeurs ayant déjà utilisé des langages de balisage. Par exemple, le balisage suivant crée un bouton qui a du texte rouge et un arrière-plan bleu avec un texte d’affichage de Content.
<Button Background="Blue" Foreground="Red" Content="This is a button"/>
Syntaxe des éléments de la propriété
Pour certaines propriétés d’un élément objet, la syntaxe d’attribut n’est pas possible, car l’objet ou les informations nécessaires pour fournir la valeur de propriété ne peuvent pas être correctement exprimées dans les restrictions de guillemets et de chaîne de syntaxe d’attribut. Pour ces cas particuliers, vous pouvez utiliser une autre syntaxe appelée syntaxe des éléments de propriété.
La syntaxe de l’étiquette de début de l’élément de propriété est <TypeName.PropertyName>. En règle générale, le contenu de cette balise est un élément objet du type que la propriété prend comme valeur. Après avoir spécifié le contenu, vous devez fermer l’élément de propriété avec une balise de fin. La syntaxe de la balise de fin est </TypeName.PropertyName>.
Si une syntaxe d’attribut est possible, son utilisation est généralement plus pratique et permet un balisage plus compact, mais il s’agit souvent d’une simple question de style et non d’une restriction technique. L’exemple suivant montre les mêmes propriétés définies comme dans l’exemple de la syntaxe d’attribut précédent, mais cette fois-ci la syntaxe des éléments de propriété est utilisée pour toutes les propriétés de 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>
Syntaxe de collection
Le langage XAML offre quelques optimisations qui permettent une meilleure lecture des balises. Par exemple, si une propriété particulière utilise un type de collection, les éléments que vous déclarez dans le balisage en tant qu’éléments enfants dans cette valeur de propriété deviennent partie intégrante de la collection. Dans ce cas, une collection d’éléments d’objet enfant est la valeur définie sur la propriété de collection.
L’exemple suivant montre la syntaxe de collection pour définir les valeurs de la GradientStops propriété.
<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>
Propriétés de contenu XAML
XAML spécifie une fonctionnalité de langage dans laquelle une classe peut désigner exactement l’une de ses propriétés comme propriété de contenu XAML. Les éléments enfants de cet élément objet sont utilisés pour définir la valeur de cette propriété de contenu. En d’autres termes, pour la propriété de contenu uniquement, vous pouvez omettre un élément de propriété lors de la définition de cette propriété dans le balisage XAML et produire une métaphore parent/enfant plus visible dans le balisage.
Par exemple, Border spécifie une propriété de contenu de Child. Les deux Border éléments suivants sont traités de manière identique. Le premier tire parti de la syntaxe de la propriété de contenu et omet l’élément de propriété Border.Child. Le deuxième affiche Border.Child explicitement.
<Border>
<TextBox Width="300"/>
</Border>
<!--explicit equivalent-->
<Border>
<Border.Child>
<TextBox Width="300"/>
</Border.Child>
</Border>
En tant que règle du langage XAML, la valeur d’une propriété de contenu XAML doit figurer soit entièrement avant soit entièrement après tous les autres éléments de propriété sur cet élément objet. Par exemple, le balisage suivant ne se compile pas.
<Button>I am a
<Button.Background>Blue</Button.Background>
blue button</Button>
Pour plus d’informations sur les spécificités de la syntaxe XAML, consultez Syntaxe XAML en détail.
Contenu texte
Un petit nombre d’éléments XAML peuvent traiter directement du texte comme étant leur contenu. Pour ce faire, un des cas suivants doit se vérifier :
La classe doit déclarer une propriété de contenu et cette propriété de contenu doit être d’un type assignable à une chaîne (le type peut être Object). Par exemple, toutes ContentControl les utilisations Content comme propriété de contenu et son typeObject, et cela prend en charge l’utilisation suivante sur un ButtonContentControl exemple :
<Button>Hello</Button>Le type doit déclarer un convertisseur de type, auquel cas le contenu de texte est utilisé comme texte d’initialisation pour ce convertisseur de type. Par exemple,
<Brush>Blue</Brush>convertit la valeur de contenu d’unBluepinceau. Ce cas est moins courant dans la pratique.Le type doit être une primitive de langage XAML connue.
Propriétés de contenu et syntaxe de collection combinées
Considérez cet exemple.
<StackPanel>
<Button>First Button</Button>
<Button>Second Button</Button>
</StackPanel>
Ici, chacun Button est un élément enfant de StackPanel. Il s’agit d’un balisage simple et intuitif qui omet deux balises pour deux raisons différentes.
Élément de propriété StackPanel.Children omis :StackPanel dérive de Panel. Panel définit Panel.Children comme sa propriété de contenu XAML.
Élément objet UIElementCollection omis : La Panel.Children propriété accepte le type UIElementCollection, qui implémente IList. La balise d’élément de la collection peut être omise, en fonction des règles XAML pour le traitement des collections telles que IList. (Dans ce cas, en fait, UIElementCollection ne peut pas être instancié, car il n’expose pas de constructeur sans paramètre, et c’est pourquoi l’élément UIElementCollection objet est affiché commenté).
<StackPanel>
<StackPanel.Children>
<Button>First Button</Button>
<Button>Second Button</Button>
</StackPanel.Children>
</StackPanel>
Syntaxe d’attribut (événements)
La syntaxe des attributs peut également servir pour les membres qui sont des événements plutôt que des propriétés. Dans ce cas, le nom de l’attribut est le nom de l’événement. Dans l’implémentation WPF d’événements pour XAML, la valeur de l’attribut est le nom d’un gestionnaire qui implémente le délégué de l’événement. Par exemple, le balisage suivant affecte un gestionnaire pour l’événement à un Button élément créé dans le Click balisage :
<Button Click="Button_Click" >Click Me!</Button>
Il existe plus d’événements et xaml dans WPF que cet exemple de syntaxe d’attribut. Par exemple, vous pouvez vous demander ce que ClickHandler représente ici et comment il est défini. Cela sera expliqué dans la section Événements à venir et code-behind XAML de cet article.
Espace de casse et d’espace blanc en XAML
En général, XAML respecte la casse. Pour résoudre les types de stockage, WPF XAML respecte la casse par les mêmes règles que celles qui respectent la casse. Les éléments objet, les éléments de propriété et les noms d’attribut doivent tous être spécifiés en respectant la casse quand leurs noms sont comparés au type sous-jacent dans l’assembly ou à un membre d’un type. Les mots clés et primitives du langage XAML respectent également la casse. Les valeurs ne respectent pas toujours la casse. Pour les valeurs, le respect de la casse varie selon le comportement du convertisseur de type associé à la propriété qui prend la valeur ou le type de valeur de la propriété. Par exemple, les propriétés qui acceptent le Boolean type peuvent prendre l’une ou trueTrue l’autre des valeurs équivalentes, mais uniquement parce que la conversion de type d’analyseur XAML WPF native pour la chaîne Boolean autorise déjà ces valeurs en tant qu’équivalents.
Les processeurs XAML WPF et les sérialiseurs ignorent ou suppriment tous les espaces blancs non significatifs et normalisent tout espace blanc significatif. Cela est cohérent avec les recommandations de comportement d’espace blanc par défaut de la spécification XAML. Ce comportement n’est qu’une conséquence lorsque vous spécifiez des chaînes dans les propriétés de contenu XAML. En termes les plus simples, XAML convertit l’espace, le flux de lignes et les caractères de tabulation en espaces, puis conserve un espace s’il se trouve à l’une ou l’autre extrémité d’une chaîne contiguë. L’explication complète de la gestion des espaces blancs XAML n’est pas abordée dans cet article. Pour plus d’informations, consultez traitement de l’espace blanc en XAML.
Extensions de balisage
Les extensions de balisage forment un concept de langage XAML. Lorsqu’elles sont utilisées pour fournir la valeur d’une syntaxe d’attributs, les accolades ({ et }) indiquent une extension de balisage. Cette utilisation ordonne au traitement XAML de se soustraire au traitement général des valeurs d’attribut, soit en tant que chaîne littérale, soit en tant que valeur convertible en chaîne.
Les extensions de balisage les plus courantes utilisées dans la programmation d’applications WPF sont Binding, utilisées pour les expressions de liaison de données et les références StaticResource de ressource et DynamicResource. En utilisant des extensions de balisage, vous pouvez utiliser la syntaxe d’attribut pour fournir des valeurs pour les propriétés même si cette propriété ne prend pas en charge une syntaxe d’attribut en général. Les extensions de balisage utilisent souvent des types d’expressions intermédiaires pour activer des fonctionnalités telles que le report de valeurs ou le référencement d’autres objets qui ne sont présents qu’au moment de l’exécution.
Par exemple, le balisage suivant définit la valeur de la propriété à l’aide de la Style syntaxe d’attribut. La Style propriété prend une instance de la Style classe, qui par défaut n’a pas pu être instanciée par une chaîne de syntaxe d’attribut. Toutefois, dans ce cas, l’attribut fait référence à une extension de balisage particulière. StaticResource Lorsque cette extension de balisage est traitée, elle retourne une référence à un style qui a été instancié précédemment en tant que ressource indexée dans un dictionnaire de ressources.
<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>
Pour obtenir la liste de référence de toutes les extensions de balisage XAML spécifiquement implémentées dans WPF, consultez Extensions XAML WPF. Pour obtenir une liste de référence des extensions de balisage définies par System.Xaml et plus largement disponibles pour les implémentations XAML .NET Core, consultez espace de noms XAML (x:) Fonctionnalités linguistiques. Pour plus d’informations sur les concepts d’extension de balisage, consultez Extensions de balisage et XAML WPF.
Convertisseurs de types
La section Syntaxe XAML en bref indique que la valeur d’attribut doit pouvoir être définie par une chaîne. La gestion native de base de la façon dont les chaînes sont converties en d’autres types d’objets ou valeurs primitives est basée sur le String type lui-même, ainsi que le traitement natif pour certains types tels que DateTime ou Uri. Toutefois, de nombreux types WPF ou membres de ces types étendent le comportement de traitement d’attribut de chaîne de base de telle sorte que les instances de types d’objets plus complexes peuvent être spécifiées en tant que chaînes et attributs.
La Thickness structure est un exemple de type pour lequel une conversion de type est activée pour les utilisations XAML. Thickness indique les mesures dans un rectangle imbriqué et est utilisée comme valeur pour les propriétés telles que Margin. En plaçant un convertisseur de type sur Thickness, toutes les propriétés qui utilisent un Thickness sont plus faciles à spécifier en XAML, car elles peuvent être spécifiées en tant qu’attributs. L’exemple suivant utilise une syntaxe de conversion de type et d’attribut pour fournir une valeur pour un Margin:
<Button Margin="10,20,10,30" Content="Click me"/>
L’exemple de syntaxe d’attribut précédent équivaut à l’exemple de syntaxe plus détaillée suivant, où l’élément Margin est défini à la place via la syntaxe d’élément de propriété contenant un Thickness élément objet. Les quatre propriétés clés de Thickness sont définies en tant qu’attributs sur la nouvelle instance :
<Button Content="Click me">
<Button.Margin>
<Thickness Left="10" Top="20" Right="10" Bottom="30"/>
</Button.Margin>
</Button>
Remarque
Il existe également un nombre limité d’objets où la conversion de type est le seul moyen public de définir une propriété sur ce type sans impliquer de sous-classe, car le type lui-même n’a pas de constructeur sans paramètre. par exemple Cursor.
Pour plus d’informations sur la conversion de type, consultez TypeConverters et XAML.
Éléments racines et espaces de noms
Un fichier XAML ne doit avoir qu’un seul élément racine, pour être à la fois un fichier XML bien formé et un fichier XAML valide. Pour les scénarios WPF classiques, vous utilisez un élément racine qui a une signification importante dans le modèle d’application WPF (par exemple, Window pour Page une page, ResourceDictionary pour un dictionnaire externe ou Application pour la définition de l’application). L’exemple suivant montre l’élément racine d’un fichier XAML classique pour une page WPF, avec l’élément racine de 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>
L’élément racine contient également les attributs xmlns et xmlns:x. Ces attributs indiquent à un processeur XAML les espaces de noms XAML contenant les définitions de types pour les types de stockage qui vont être référencés en tant qu’éléments par le balisage. L’attribut xmlns indique explicitement l’espace de noms XAML par défaut. Dans l’espace de noms XAML par défaut, les éléments objet dans le balisage peuvent être spécifiés sans préfixe. Pour la plupart des scénarios d’application WPF et pour presque tous les exemples donnés dans les sections WPF du Kit de développement logiciel (SDK), l’espace de noms XAML par défaut est mappé à l’espace de noms http://schemas.microsoft.com/winfx/2006/xaml/presentationWPF. L’attribut xmlns:x indique un espace de noms XAML supplémentaire qui mappe l’espace de noms du langage XAML http://schemas.microsoft.com/winfx/2006/xaml.
Cette utilisation de xmlns pour définir une étendue de l’utilisation et le mappage d’une portée de nom est conforme à la spécification XML 1.0. Les portées de nom XAML se distinguent des portées de nom XML uniquement parce qu’elles renseignent aussi sur la façon dont les éléments de la portée de nom sont stockés par les types lors d’une résolution de type et d’une analyse du code XAML.
Les xmlns attributs sont uniquement nécessaires sur l’élément racine de chaque fichier XAML. Les définitions xmlns s’appliquent à tous les éléments descendants de l’élément racine (ce comportement est encore une fois conforme à la spécification XML 1.0 pour xmlns), tandis que les attributs xmlns sont également autorisés sur d’autres éléments situés sous la racine et s’appliquent à tous les éléments descendants de l’élément de définition. Toutefois, si vous définissez/redéfinissez fréquemment les espaces de noms XAML, le style de balisage XAML peut devenir difficile à lire.
L’implémentation WPF de son processeur XAML inclut une infrastructure qui a connaissance des assemblys principaux WPF. Les assemblys principaux WPF sont connus pour contenir les types qui prennent en charge les mappages WPF à l’espace de noms XAML par défaut. Cette option est activée par le biais de la configuration faisant partie du fichier de build de votre projet et des systèmes de projet et de build WPF. Par conséquent, déclarer l’espace de noms XAML par défaut comme valeur par défaut xmlns est tout ce qui est nécessaire pour référencer des éléments XAML provenant d’assemblys WPF.
Préfixe x :
Dans l’exemple d’élément racine précédent, le préfixe x: a été utilisé pour mapper l’espace de noms XAML http://schemas.microsoft.com/winfx/2006/xaml, qui est l’espace de noms XAML dédié prenant en charge les constructions du langage XAML. Ce x: préfixe est utilisé pour mapper cet espace de noms XAML dans les modèles de projets, dans des exemples et dans la documentation de ce Kit de développement logiciel (SDK). L’espace de noms XAML pour le langage XAML contient plusieurs constructions de programmation que vous utiliserez fréquemment dans votre code XAML. Voici une liste de constructions de programmation avec le préfixe x: parmi les plus courantes que vous allez utiliser :
x:Key : définit une clé unique pour chaque ressource dans un ResourceDictionary (ou des concepts de dictionnaire similaires dans d’autres frameworks).
x:Keyreprésente probablement 90 % desx:utilisations que vous verrez dans le balisage d’une application WPF classique.x:Class : spécifie l’espace de noms CLR et le nom de classe de la classe qui fournit du code-behind pour une page XAML. Vous devez disposer d’une telle classe pour prendre en charge le code-behind selon le modèle de programmation WPF, et c’est la raison pour laquelle vous voyez presque toujours
x:mappé, même s’il n’ y a aucune ressource.x:Name : spécifie un nom d’objet d’exécution pour l’instance qui existe dans le code d’exécution après le traitement d’un élément objet. En général, vous êtes amené à utiliser fréquemment une propriété équivalente définie par WPF pour x:Name. Ces propriétés mappent spécifiquement à une propriété de stockage CLR et sont donc plus pratiques pour la programmation d’applications, où vous utilisez fréquemment du code d’exécution pour rechercher les éléments nommés à partir du code XAML initialisé. La propriété la plus courante est FrameworkElement.Name. Vous pouvez toujours utiliser x:Name lorsque la propriété de niveau Name framework WPF équivalente n’est pas prise en charge dans un type particulier. Ce cas se présente dans certains scénarios d’animation.
x:Static : active une référence qui retourne une valeur statique qui n’est pas une propriété compatible XAML.
x:Type : construit une Type référence basée sur un nom de type. Il est utilisé pour spécifier des attributs qui prennent Type, par Style.TargetTypeexemple, bien que la propriété ait souvent une conversion de chaîneType en mode natif de telle sorte que l’utilisation de l’extension de balisage x:Type soit facultative.
Il existe des constructions de programmation supplémentaires dans l’espace x: de noms préfixe/XAML, qui ne sont pas aussi courantes. Pour plus d’informations, consultez Fonctionnalités de langage pour les espaces de noms XAML (x:).
Préfixes personnalisés et types personnalisés
Pour vos propres assemblys personnalisés ou pour les assemblys en dehors du cœur WPF de PresentationCore, PresentationFramework et WindowsBase, vous pouvez spécifier l’assembly dans le cadre d’un mappage personnalisé xmlns . Vous pouvez ensuite référencer des types depuis cet assembly dans votre XAML à partir du moment où le type voulu est correctement implémenté pour prendre en charge les utilisations XAML que vous essayez.
Voici un exemple de base du fonctionnement des préfixes personnalisés dans le balisage XAML. Le préfixe custom est défini dans la balise d’élément racine et mappé à un assembly spécifique empaqueté et disponible avec l’application. Cet assembly contient un type NumericUpDown, qui est implémenté pour prendre en charge l’utilisation générale de XAML ainsi que l’utilisation d’un héritage de classe, autorisant son insertion à ce stade dans un modèle de contenu XAML WPF. Une instance de ce contrôle NumericUpDown est déclaré comme élément objet en utilisant le préfixe afin qu’un analyseur XAML identifie quel espace de noms XAML contient le type et par conséquent l’emplacement de l’assembly de stockage contenant la définition de type.
<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>
Pour plus d’informations sur les types personnalisés en XAML, consultez XAML et les classes personnalisées pour WPF.
Pour plus d’informations sur la façon dont les espaces de noms XML et les espaces de noms de code dans les assemblys sont associés, consultez Espaces de noms XAML et Mappage d’espaces de noms pour LE XAML WPF.
Événements et code-behind XAML
La plupart des applications WPF se composent à la fois de balisage XAML et de code-behind. Dans un projet, le code XAML est écrit en tant que .xaml fichier, et un langage CLR tel que Microsoft Visual Basic ou C# est utilisé pour écrire un fichier code-behind. Lors de la compilation du balisage d’un fichier XAML comme partie intégrante des modèles de programmation et d’application WPF, l’emplacement du fichier code-behind XAML pour un fichier XAML est identifié en spécifiant un espace de noms et une classe en tant qu’attribut x:Class de l’élément racine du XAML.
Jusqu’ici dans les exemples étudiés, vous avez vu plusieurs boutons, mais aucun d’eux n’avait encore de comportement logique qui lui était associé. Le mécanisme de niveau application principal permettant d’ajouter un comportement pour un élément objet consiste à utiliser un événement existant de la classe d’élément et à écrire un gestionnaire spécifique pour cet événement appelé lorsque cet événement est déclenché au moment de l’exécution. Le nom de l’événement et celui du gestionnaire à utiliser sont spécifiés dans le balisage, tandis que le code qui implémente le gestionnaire est défini dans le fichier code-behind.
<Window x:Class="index.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Height="450" Width="800">
<StackPanel>
<Button Click="Button_Click">Click me</Button>
</StackPanel>
</Window>
private void Button_Click(object sender, RoutedEventArgs e)
{
var buttonControl = (Button)e.Source;
buttonControl.Foreground = Brushes.Red;
}
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
Dim buttonControl = DirectCast(e.Source, Button)
buttonControl.Foreground = Brushes.Red
End Sub
Notez que le fichier code-behind utilise l’espace de noms CLR ExampleNamespace et déclare ExamplePage comme une classe partielle dans cet espace de noms. Cela correspond à la valeur d’attribut x:Class de ExampleNamespace.ExamplePage qui a été fourni dans la racine de balisage. Le compilateur de balisage WPF crée une classe partielle pour tout fichier XAML compilé, en dérivant une classe à partir du type d’élément racine. Lorsque vous fournissez du code-behind qui définit également la même classe partielle, le code résultant est combiné dans le même espace de noms et la même classe de l’application compilée.
Pour plus d’informations sur la configuration requise pour la programmation code-behind dans WPF, consultez Code-behind, Event Handler et Partial Class Requirements dans WPF.
Si vous ne souhaitez pas créer de fichier code-behind distinct, vous pouvez également inliner votre code dans un fichier XAML. Toutefois, le code incorporé est une technique moins flexible qui présente des limitations importantes. Pour plus d’informations, consultez Code-Behind et XAML dans WPF.
Événements routés
Une fonctionnalité d’événement particulière qui est fondamentale pour WPF est un événement routé. Les événements routés permettent à un élément de gérer un événement déclenché par un élément différent, tant que ces éléments sont connectés via une relation d’arborescence. Lors de la spécification de la gestion des événements avec un attribut XAML, l’événement routé peut être écouté et géré sur n’importe quel élément, y compris les éléments qui ne répertorient pas cet événement particulier dans la table des membres de la classe. Pour cela, vous devez qualifier l’attribut de nom d’événement avec le nom de la classe propriétaire. Par exemple, le parent StackPanel de l’exemple en cours StackPanel / Button peut inscrire un gestionnaire pour l’événement du bouton d’élément Click enfant en spécifiant l’attribut Button.Click sur l’élément StackPanel objet, avec le nom de votre gestionnaire comme valeur d’attribut. Pour plus d’informations, consultez Vue d’ensemble des événements routés.
Éléments nommés
Par défaut, l’instance d’objet créée dans un graphe d’objets en traitant un élément d’objet XAML n’a pas d’identificateur ou de référence d’objet unique. En revanche, si vous appelez un constructeur dans le code, vous utilisez presque toujours le résultat du constructeur pour définir une variable sur l’instance construite, afin de pouvoir référencer l’instance ultérieurement dans votre code. Pour fournir un accès normalisé aux objets créés par le biais d’une définition de balisage, XAML définit l’attribut x:Name. Vous pouvez définir la valeur de l’attribut x:Name sur n’importe quel élément objet. Dans votre code-behind, l’identificateur que vous choisissez équivaut à une variable d’instance qui fait référence à l’instance construite. Dans tous les cas, les éléments nommés fonctionnent comme s’ils étaient des instances d’objet (le nom référence cette instance), et votre code-behind peut référencer les éléments nommés pour gérer les interactions au moment de l’exécution dans l’application. Cette connexion entre les instances et les variables est effectuée par le compilateur de balisage XAML WPF, et implique plus particulièrement des fonctionnalités et des modèles tels que InitializeComponent ceux-ci ne seront pas abordés en détail dans cet article.
Les éléments XAML au niveau de l’infrastructure WPF héritent d’une Name propriété équivalente à l’attribut défini x:Name XAML. Certaines autres classes fournissent également des équivalents au niveau de la propriété pour x:Name, qui est également généralement défini comme une Name propriété. En règle générale, si vous ne trouvez pas de Name propriété dans la table membres de votre élément/type choisi, utilisez x:Name à la place. Les x:Name valeurs fournissent un identificateur à un élément XAML qui peut être utilisé au moment de l’exécution, soit par des sous-systèmes spécifiques, soit par des méthodes utilitaires telles que FindName.
L’exemple suivant définit Name sur un StackPanel élément. Ensuite, un gestionnaire sur un Button au sein de celui-ci StackPanel fait référence à StackPanel la référence buttonContainer par l’instance comme défini par Name.
<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
Tout comme une variable, le nom XAML d’une instance est régi par un concept de portée afin que les noms puissent être appliqués pour être uniques dans une certaine étendue qui est prévisible. La balisage principal qui définit une page désigne une portée de nom XAML unique, avec pour élément racine de cette page, les limites de portée de nom XAML. Toutefois, d’autres sources de balisage peuvent interagir avec une page au moment de l’exécution, telles que des styles ou des modèles dans des styles, et ces sources de balisage ont souvent leurs propres portées de noms XAML qui ne se connectent pas nécessairement avec la portée de noms XAML de la page. Pour plus d’informations sur x:Name les portées de noms XAML, consultez Name, x:Name Directive ou WPF XAML Namescopes.
Propriétés jointes et événements joints
XAML spécifie une fonctionnalité de langage qui permet à certains propriétés ou événements d’être spécifiés sur n’importe quel élément, même si la propriété ou l’événement n’existe pas dans les définitions du type pour l’élément sur lequel il est défini. La version des propriétés de cette fonctionnalité est appelée une propriété jointe, et la version des événements, un événement attaché. D’un point de vue conceptuel, vous pouvez considérer les propriétés jointes et les événements attachés comme des membres globaux pouvant être définis sur n’importe quelle instance d’élément ou d’objet XAML. Toutefois, cet élément/cette classe ou une infrastructure plus importante doit prendre en charge une banque de propriétés de stockage pour les valeurs attachées.
Les propriétés jointes en XAML sont généralement utilisées dans la syntaxe d’attributs. Dans la syntaxe d’attribut, vous spécifiez une propriété jointe dans le formulaire ownerType.propertyName.
De façon superficielle, cela ressemble à une utilisation d’élément de propriété, mais dans ce cas, le ownerType type que vous spécifiez est toujours différent de celui de l’élément objet où la propriété jointe est définie. ownerType est le type qui fournit les méthodes d’accesseur requises par un processeur XAML pour obtenir ou définir la valeur de propriété jointe.
Le scénario le plus courant pour les propriétés jointes consiste à permettre aux éléments enfants de signaler une valeur de propriété à leur élément parent.
L’exemple suivant illustre la DockPanel.Dock propriété jointe. La DockPanel classe définit les accesseurs pour DockPanel.Dock et possède la propriété jointe. La DockPanel classe inclut également la logique qui itère ses éléments enfants et vérifie spécifiquement chaque élément pour une valeur définie de DockPanel.Dock. Si une valeur est trouvée, cette valeur est utilisée au cours de la disposition pour positionner les éléments enfants. L’utilisation de la DockPanel.Dock propriété jointe et cette fonctionnalité de positionnement est en fait le scénario de motivation pour la DockPanel classe.
<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>
Dans WPF, la plupart ou toutes les propriétés jointes sont également implémentées en tant que propriétés de dépendance. Pour plus d’informations, consultez Vue d’ensemble des propriétés jointes.
Les événements attachés utilisent une forme similaire ownerType.eventName de syntaxe d’attribut. À l’instar des événements non attachés, la valeur d’attribut d’un événement attaché en XAML spécifie le nom de la méthode de gestionnaire qui est appelée lorsque l’événement est géré sur l’élément. Les utilisations d’événements attachés en XAML WPF sont moins courantes. Pour plus d’informations, consultez Vue d’ensemble des événements attachés.
Types de base
Le code XAML WPF sous-jacent et son espace de noms XAML sont une collection de types qui correspondent aux objets CLR et aux éléments de balisage pour XAML. Cela étant, toutes les classes ne peuvent pas être mappées aux éléments. Les classes abstraites, telles que ButtonBase, et certaines classes de base non abstraites, sont utilisées pour l’héritage dans le modèle d’objets CLR. Les classes de base, y compris abstraites, sont toujours importantes pour le développement en XAML, car chacun des éléments XAML concrets hérite de membres provenant d’une classe de base dans sa hiérarchie. Ces membres incluent souvent des propriétés qui peuvent être définies en tant qu’attributs sur l’élément, ou comme événements qui peuvent être gérés. FrameworkElement est la classe d’interface utilisateur de base concrète de WPF au niveau de l’infrastructure WPF. Lors de la conception de l’interface utilisateur, vous allez utiliser différentes classes de forme, de panneau, de décorateur ou de contrôle, qui dérivent tous de FrameworkElement. Une classe de base associée, FrameworkContentElementprend en charge les éléments orientés documents qui fonctionnent bien pour une présentation de disposition de flux, à l’aide d’API qui reflètent délibérément les API dans FrameworkElement. La combinaison d’attributs au niveau de l’élément et d’un modèle objet CLR vous fournit un ensemble de propriétés communes qui sont définies sur la plupart des éléments XAML concrets, quel que soit l’élément XAML spécifique et son type sous-jacent.
Sécurité
Le XAML est un langage de balisage qui représente directement l’instanciation d’objets et leur exécution. C’est pourquoi les éléments créés en XAML ont la même possibilité d’interagir avec les ressources système (accès réseau, E/S du système de fichiers, par exemple) que le code de votre application. XAML a également le même accès aux ressources système que l’application d’hébergement.
Sécurité de l’accès au code (CAS) dans WPF
Contrairement au .NET Framework, WPF pour .NET ne prend pas en charge le cas. Pour plus d’informations, consultez différences de sécurité d’accès au code.
Charger XAML à partir du code
XAML peut être utilisé pour définir l’ensemble de l’interface utilisateur, mais il est parfois également approprié de définir uniquement une partie de l’interface utilisateur en XAML. Cette fonctionnalité peut être utilisée pour :
- Activez la personnalisation partielle.
- Stockage local des informations d’interface utilisateur.
- Modélisez un objet métier.
La clé de ces scénarios est la XamlReader classe et sa Load méthode. L’entrée est un fichier XAML, et la sortie un objet représentant l’intégralité de l’arborescence d’exécution des objets qui a été créée à partir de ce balisage. Vous pouvez ensuite insérer l’objet comme propriété d’un autre objet qui existe déjà dans l’application. Tant que la propriété se trouve dans le modèle de contenu et dispose de fonctionnalités d’affichage qui avertiront le moteur d’exécution que le nouveau contenu a été ajouté à l’application, vous pouvez modifier facilement le contenu d’une application en cours d’exécution en charge dynamiquement en XAML.