Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. PowerShell et WPF
  3. PowerShell et XAML
Extrait - PowerShell et WPF Développez des interfaces graphiques modernes et robustes
Extraits du livre
PowerShell et WPF Développez des interfaces graphiques modernes et robustes
1 avis
Revenir à la page d'achat du livre

PowerShell et XAML

Introduction

Dans le deuxième chapitre, nous avons vu ce qu’était le cœur de notre interface, XAML.

Nous avons également vu comment créer et éditer un fichier XAML.

Dans ce chapitre, nous allons voir comment lier notre interface avec notre code PowerShell.

Nous allons également voir comment ajouter des actions sur nos Controls afin de créer une interactivité avec l’utilisateur.

Il est important de bien comprendre le rôle de chaque partie dans son projet WPF et PowerShell.

Ce projet est composé de deux parties :

  • PowerShell

  • XAML

Rôles des fichiers

1. XAML pour notre interface

La partie XAML, comme mentionné au chapitre XAML, le cœur de notre interface, représentera la partie graphique, et uniquement graphique, de notre projet.

Nous intégrerons dans cette partie tous nos Controls et aspects graphiques.

2. PS1 pour notre code

La partie PowerShell quant à elle représentera la partie code de notre projet. C’est la partie qui permettra de gérer toutes les actions sur les Controls liées à notre interface.

3. Comment organiser son projet ?

Les deux parties XAML et PS1 peuvent s’utiliser de deux façons :

  • Deux fichiers distincts (méthode que je recommande pour une meilleure lisibilité et davantage de maniabilité).

  • Tout inclure dans le fichier PowerShell.

Ces deux méthodes seront traitées dans ce chapitre.

4. Notre projet dans ce chapitre

Le projet qui servira d’exemple dans ce chapitre aura pour nom MonProjet.

L’interface sera telle que ci-dessous :

images/04EP01.png

Cette interface est représentée par le code XAML ci-dessous :

<Window 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="Interface WPF - Chapitre 4" Width="380" Height="200"> 
<Grid> 
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" ...

Première méthode : deux fichiers distincts

Notre projet sera composé de deux fichiers tels que ci-dessous :

  • MonProjet.xaml : notre interface

  • MonProjet.ps1 : notre code

1. Lier PowerShell et XAML

Ouvrons donc le fichier PowerShell et ajoutons-y le code suivant afin de charger notre fichier MonProjet.xaml :

[xml]$MonXAML = get-content -path "MonProjet.xaml" 
$Reader=(New-Object System.Xml.XmlNodeReader $MonXAML) 
$Interface = [Windows.Markup.XamlReader]::Load($Reader) 
$Interface.ShowDialog() | Out-Null 

Que fait ce code ?

  • Nous allons d’abord transformer notre XAML en un objet XML en utilisant System.Xml.XmlNodeReader.

  • Ensuite, nous chargeons ce dernier en utilisant [Windows.Markup.XamlReader]::Load.

  • Enfin, nous affichons notre interface en utilisant $Interface.ShowDialog().

Si nous lançons le fichier PowerShell, nous obtenons l’erreur suivante :

images/04EP02N.PNG

Pourquoi ?

La raison est simple, il nous manque l’assembly permettant le fonctionnement de WPF.

Présentation des assemblies

L’assembly à utiliser ici est l’assembly presentationframework et se présente sous la forme d’un fichier .dll.

C’est cette assembly qui contiendra tous les Controls que nous voulons utiliser.

C’est également par elle que notre interface WPF pourra s’afficher.

Dans le chapitre XAML, le cœur de notre interface, nous avons retrouvé une référence à cette assembly à deux reprises.

En effet, lors de la création d’un projet WPF via Visual Studio, en cliquant sur [F12] sur un Control, par exemple un TextBox, nous obtenons l’information ci-dessous :

images/04EP03.PNG

Si vous cherchez des informations sur un Control sur le site de Microsoft, par exemple un Button, vous obtiendrez l’information ci-dessous.

images/04EP04.png

Vous trouverez également une explication sur ces assemblies au chapitre Interface graphique et PowerShell.

Ce qui nous amène donc à notre seconde étape qui en réalité est donc la première.

2. Chargement de l’assembly

a. Comment charger l’assembly ?

Pour charger l’assembly presentationframework, nous utiliserons la ligne ci-dessous :

[System.Reflection.Assembly]::LoadWithPartialName 
('presentationframework') 

En exécutant cette ligne dans une console PowerShell, nous obtenons le résultat suivant :...

Deuxième méthode : Tout dans le PS1

Dans cette seconde méthode, notre fichier XAML sera intégré dans le fichier PS1.

La seule chose qui changera par rapport à la méthode 1 sera la partie chargement du XAML.

Concernant les étapes ci-dessous, elles sont identiques à la première méthode :

  • Déclaration de l’assembly

  • Déclaration des Controls

  • Affichage de l’interface

Comment charger le XAML dans le PS1 ?

Pour cela, nous allons intégrer notre contenu XAML dans une variable en utilisant ce modèle :

[xml]$Form = @" 
MON CODE XAML 
"@ 

Notre fichier PowerShell MonProjet.ps1 sera alors tel que ci-dessous :

[System.Reflection.Assembly]::LoadWithPartialName 
('presentationframework') | out-null 
[xml]$MonXAML = @" 
<Window 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="Interface WPF - Chapitre 4" Width="380" Height="200"> 
<Grid> 
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" 
Margin="0,10,0,0"> 
<Label Content="Notre interface WPF" FontSize="20" 
HorizontalAlignment="Center"/> 
<GroupBox Header="Chargement du dossier"...

Déclarations de nos Controls

Nous pouvons à présent lancer notre interface depuis notre fichier PowerShell.

Cependant, si nous cliquons sur un Control, aucune action ne sera exécutée.

Pourquoi ?

La raison est simple, il faut déclarer les Controls situés dans le fichier XAML, dans notre fichier PS1.

Pour cela, nous allons utiliser le modèle ci-dessous :

$MonControl = $MonInterface.FindName("MonControl") 

Déclarons donc nos Controls en suivant ce modèle.

Quels Controls avons-nous ?

Comme mentionné dans le chapitre XAML, le cœur de notre interface, afin de pouvoir exécuter une action sur un Control, il faut nommer ce Control en utilisant l’attribut Name suivi du nom à lui donner.

Il faut donc déterminer les Controls sur lesquels nous voulons ajouter une action. 

Dans le fichier XAML, nous avons les Controls ci-dessous :

<Button Name="MonBouton" Content="Browse" Width="80" Height="20"/> 
<TextBox Name="MonTextBox" Width="200" Height="20"/> 

Nous avons deux Controls à déclarer en utilisant l’attribut Name.

Chaque nom devra donc être déclaré dans le fichier PowerShell.

Voici le code déclarant nos Controls :

$MonBouton = $MonInterface.FindName("MonBouton") 
$MonTextBox = $MonInterface.FindName("MonTextBox")...

Des actions sur les Controls

Jusqu’à présent, nous avons construit notre interface puis lié celle-ci à notre fichier PowerShell.

Ce fichier servira pour notre partie code.

Cependant, il manque une dernière étape afin de pouvoir ajouter une action sur nos Controls.

Il s’agit de l’ajout des blocs d’évènements (events) sur ces Controls.

Ce bloc d’évènement permettra de contenir le code exécutant l’action souhaitée, par exemple la copie d’un fichier lors d’un clic sur un bouton.

Pour rappel, notre interface est la suivante :

images/04EP01.png

Ce que nous voulons dans notre interface :

  • Lorsque nous cliquons, ou passons le curseur de la souris sur le bouton Browse, cela doit afficher une fenêtre permettant de charger le contenu d’un dossier local sur un dossier localisé sur votre PC.

  • Une fois que nous avons choisi le dossier, le chemin sera affiché dans le TextBox.

  • Un clic droit ou un double clic dans le TextBox devra permettre d’en effacer le contenu.

Comme vu précédemment, nous avons donc les deux Controls :

  • Notre bouton Browse : $MonBouton

  • Notre TextBox : $MonTextBox

Nous avons parlé d’évènements, mais comment les traduire ?

Lorsque l’utilisateur clique sur le bouton Browse, cela va ouvrir une fenêtre permettant de charger le contenu d’un dossier local...

Controls et Events

Comme mentionné précédemment, les actions effectuées sur des Controls sont appelées évènements ou events.

Il existe différents évènements disponibles pour un même Control.

Tous ces évènements sont inclus dans l’assembly presentationframework.dll.

Pour chaque action que vous souhaitez exécuter, par exemple sur un bouton, il existe un évènement.

On peut parfois trouver différents évènements pour une même action.

Vous trouverez dans cette section une liste des évènements les plus souvent utilisés ou qui peuvent être utiles dans vos projets.

Ces évènements seront définis par rapport à une action que nous voulons effectuer. 

1. Events les plus courants

a. Action après un simple clic (gauche) sur un Control

Pour cela, il existe l’évènement Click, qui s’utilise de la manière suivante dans PowerShell :

$MonBouton.Add_Click({ 
# CODE POUR MON ACTION 
}) 

b. Action après avoir effectué un clic droit sur un Control

Pour cela, il existe l’évènement MouseRightButtonDown, qui s’utilise de la manière suivante dans PowerShell :

$MonBouton.Add_MouseRightButtonDown({ 
# CODE POUR MON ACTION 
}) 

c. Action après avoir relâché...

Cycle de vie d’une interface

Une interface WPF est divisée en deux parties :

  • Une partie cliente

  • Une partie non-cliente

La partie non-cliente est la partie commune à la plupart des applications existantes. Celle-ci comprend les éléments suivants :

  • Des bordures

  • Un titre

  • Une icône

  • Différents boutons : minimiser, redimensionner, agrandir, fermer

La partie cliente, quant à elle, constitue la zone que nous modifions, celle où nous ajoutons notre contenu, bouton, zone de saisie, texte…

Nous allons maintenant étudier le cycle de vie de notre interface et comment celle-ci évolue à partir de son chargement et jusqu’à sa fermeture.

Ce point est important à comprendre.

En effet, une fois que vous aurez maîtrisé cela, vous pourrez gérer aisément le moment où une action doit s’effectuer.

Un exemple concret serait : je veux que telle ou telle action soit exécutée lors de la fermeture de l’interface, c’est-à-dire au moment où l’on clique sur le bouton de fermeture.

Comme nous l’avons déjà vu, notre interface est représentée par la classe Window.

C’est en effet à l’intérieur de cette même balise <Window> que l’on intègre tout le contenu de notre interface.

Comme chaque Control, notre Window possède des attributs et des évènements.

Comme pour les Controls, ces évènements permettent d’interagir avec l’objet en question, ici donc notre interface principale.

Ces évènements constituent le cycle de vie de la fenêtre.

Nous pouvons en avoir un aperçu en reprenant le code de la section Lier PowerShell et XAML, ci-dessous :

[xml]$MonXAML = get-content -path "MonProjet.xaml" 
$Reader=(New-Object System.Xml.XmlNodeReader $MonXAML) 
$Interface = [Windows.Markup.XamlReader]::Load($Reader) 
$Interface.ShowDialog() | Out-Null 

Nous allons simplement enlever la partie $Interface.ShowDialog afin d’afficher les évènements contenus dans notre interface.

Pour cela, nous allons effectuer un get-member sur l’objet de notre interface, tel que ci-dessous :

$Interface | gm | where {$_.MemberType -eq "Event"} | 
select Name, MemberType 

Nous obtenons alors...

Minimiser et afficher depuis le PowerShell

Il peut être intéressant dans votre code de minimiser votre interface, c’est-à-dire ne plus l’afficher. Cela peut par exemple être utile si vous souhaitez exécuter une action qui prend du temps. L’interface va alors disparaître après avoir cliqué sur un bouton spécifique puis être affichée de nouveau à la fin de l’exécution du code.

Ci-dessous le code pour minimiser l’interface :

$Form.WindowState = [System.Windows.Forms.FormWindowState]::Minimized 

Ci-dessous le code pour afficher l’interface :

$Form.WindowState = [System.Windows.Forms.FormWindowState]::Normal 

Il est également possible d’afficher ou non la possibilité d’afficher l’interface, depuis la barre des tâches.

Pour cela, il faut utiliser la ligne suivante :

$Form.ShowInTaskbar = $true 
$Form.WindowState = [System.Windows.Forms.FormWindowState]::Minimized