Programmation événementielle Actes V)
Comment : créer des gestionnaires d'événements dans l'éditeur de code de Visual C#
L'éditeur de code de Visual C# permet de créer facilement des gestionnaires d'événements pour vos Windows Forms lorsque vous travaillez en mode Design. L'alternative consiste à afficher le code en mode Source et d'ajouter le gestionnaire d'événements dans le code.
Remarque |
Les boîtes de dialogue et les commandes de menu qui s'affichent peuvent être différentes de celles qui sont décrites dans l'aide, en fonction de vos paramètres actifs ou de l'édition utilisée. Pour modifier vos paramètres, choisissez Importation et exportation de paramètres dans le menu Outils. Pour plus d'informations, consultez Paramétrage de Visual Studio. |
Pour créer un gestionnaire d'événements à l'aide de l'éditeur de code de Visual C#
1. Si la fenêtre Propriétés n'est pas visible, en mode Design, cliquez avec le bouton droit sur le formulaire ou le contrôle pour lequel vous souhaitez créer un gestionnaire d'événements et sélectionnez Propriétés.
2. Dans la partie supérieure de la fenêtre Propriétés, cliquez sur le bouton Événements.
3. Double-cliquez sur l'événement que vous voulez créer, par exemple l'événement Load.
Visual C# crée une méthode de gestionnaire d'événements vide et l'ajoute à votre code. Vous pouvez également ajouter à la main le code en mode Code. Par exemple, les lignes de code suivantes déclarent un gestionnaire d'événements de charge pour une classe Form appelée Form1.
private void Form1_Load(object sender, System.EventArgs e)
{
// Ajouter le code pour le gestionnaire d'événement du chargement du formulaire
}
Création d'une application MDI avec Visual C# |
Autre illustration de la mise en place des événements et délégués
Une question qui revient assez souvent dans les discussions au sujet des événements est
- Comment mettre en place une communication entre mes classes métiers et mes IHM ?
- Comment faire ça avec la philosophie .NET ?
Un exemple assez classique pour illustrer le propos reste la copie de fichier. L'idéal est de créer une classe métier qui va s'occuper de la copie du fichier puis de créer une IHM qui va consommer cette classe.
Cependant, si le fichier fait 10Mo, il peut être utile de présenter à l'utilisateur une gauge de progression pour le faire patienter. De plus, si il décide d'annuler la copie, il doit pouvoir le faire, ce qui veut dire que l'interface graphique ne doit pas être bloquée durant cette copie. A titre d'exemple, voici une classe "classique" (Librairie_CS.GestionFichiers ) permettant de réaliser cette opération de copie :
using System;
using System.IO;
namespace Librairie_CS {
public class GestionFichiers {
private string cheminFichier = string.Empty;
public string CheminFichier {
get {
return(this.cheminFichier);
}
}
public GestionFichiers(string cheminFichier) {
this.cheminFichier = cheminFichier;
}
public void CopieFichier(string cheminFichierDestination, bool ecrasement) {
// On vérifie si le fichier de destination n'existe pas déjà
if (File.Exists(cheminFichierDestination)) {
// Si demandé, on écrase le fichier de destination
if (ecrasement) {
File.Delete(cheminFichierDestination);
}
else {
throw new IOException(string.Format("Le fichier de destination '{0}' existe déjà.", cheminFichierDestination));
}
}
// On ouvre le fichier de destination en écriture
using (FileStream fileStreamDestination = new FileStream(cheminFichierDestination, FileMode.Create, FileAccess.Write)) {
// On ouvre le fichier d'origine en lecture
using (FileStream fileStreamOriginal = new FileStream(this.cheminFichier, FileMode.Open, FileAccess.Read)) {
// On lit le prochain octet
int octet = fileStreamOriginal.ReadByte();
while (octet != -1) {
// On écrit l'octet
fileStreamDestination.WriteByte((byte)octet);
octet = fileStreamOriginal.ReadByte();
}
fileStreamOriginal.Close();
}
fileStreamDestination.Close();
}
}
}
}
Ceci étant fait, il faudrait maintenant implémenter trois événements dans nos classes:
- CopieDemarrage : cet événement devra être émis juste avant le démarrage proprement dit de l'opération de copie. Il devra permettre notament d'informer le client de la taille du fichier à copier
- CopieEnCours : cet événement devra être émis à intervalle régulier de manière à indiquer la progression de la copie. Il devra également permettre au client d'annuler l'opération en cours
- CopieFin : cet événement devra être émis en fin de processus en indiquant le statut final de l'opération (Succès, Echec, Annulation)
Pou mettre en place ce genre de choses, il faut passer par des Delegates:
- CopieDemarrageEventHandler
- CopieEnCoursEventHandler
- CopieFinEventHandler
Notez que le plan de nommage utilisé en standard par le .NET Framework consiste à terminer le nom de ses Delegates par EventHandler. Une fois les Delegates déclarés, il faut ensuite déclarer les événements eux-mêmes. Les événements que nous allons déclarés auront pour type les Delegates précédents. Voici les déclarations que nous allons utiliser :
namespace Librairie_CS {
public delegate void CopieDemarrageEventHandler(object sender, CopieDemarrageEventArgs e);
public delegate void CopieEnCoursEventHandler(object sender, CopieEnCoursEventArgs e);
public delegate void CopieFinEventHandler(object sender, CopieFinEventArgs e);
public class GestionFichiers {
public event CopieDemarrageEventHandler CopieDemarrage = null;
public event CopieEnCoursEventHandler CopieEnCours = null;
public event CopieFinEventHandler CopieFin = null;
Imaginons que nous déclarions un Event comme suit :
public event Test(integer monParam )
L'introspection de la DLL générée grâce à ILDASM, nous permet de découvrir que le compilateur a effectivement bossé pour nous en créant le Delegate directement au niveau du code IL :
| | |___[CLS] TestEventHandler
| | | | .class nested public auto ansi sealed
| | | | extends [mscorlib]System.MulticastDelegate
puis
| | |___[FLD] TestEvent : private class Librairie_VB.GestionFichiers/TestEventHandler
Revenons maintenant à nos moutons. Vous avez certainement remarqué que la déclaration des signatures de mes Delegates (et donc de mes événements in fine) avait l'air de suivre une règle commune:
- (object sender, xxxEventArgs e)
--
Alain Lompo
Excelta - Conseils et services informatiques
MCT
MCSD For Microsoft .Net
MVP Windows Systems Server / Biztalk Server
Certifié ITIL et Microsoft Biztalk Server
Commentaires