Developpez.com

Une très vaste base de connaissances en informatique avec
plus de 100 FAQ et 10 000 réponses à vos questions

Développer un contrôle utilisateur (UserControl) en C#

Cet article vous apprendra comment créer et manipuler un contrôle utilisateur en C#.

N'hésitez pas à commenter cet article ! Commentez Donner une note à l'article (5)

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Le Framework .NET comporte un nombre important de contrôles utilisables dans vos applications. Cependant, il peut arriver que vous ayez besoin d'utiliser un contrôle qui est en fait, une combinaison de plusieurs contrôles de bases. Pour cela, vous pouvez utiliser des contrôles utilisateurs.
Les Contrôles Utilisateurs (UserControls) sont des contrôles Dotnet que vous avez développés et que vous voulez réutiliser dans vos applications. On peut donc les assimiler à des contrôles personnalisés
Dans cet article, je vous propose une vue d'ensemble de ce qu'ils sont exactement ainsi que de leurs fonctionnalités diverses.

Tous les exemples de cet article ont été réalisés avec Visual Studio 2005 Professionnal Edition, donc la version 2.0 du Framework .NET

II. Création du UserControl dans Visual Studio

II-A. Création du UserControl

Pour créer un UserControl, dans Visual Studio, vous avez 2 possibilités:

  • faîtes un clic droit sur le nom de votre projet, choisissez "Add New Item" puis sélectionnez "User Control"
  • ajoutez, à votre solution, un nouveau projet de type "Windows Control Library"


Voici ce que cela donne en image:

Ajout d'un UserControl au projet


Et:

Ajout d'un projet de type Windows Control Library à la solution


Vous vous retrouvez alors avec une fenêtre de ce type dans Visual Studio:

Interface de création d'un UserContrl


En fait, il s'agit d'une fenêtre Windows classique, mais sur laquelle il n'y a pas de bordures !
Sur ce formulaire, vous allez pouvoir utiliser toutes les capacités de Visual Studio, et en particulier le glisser/déposer de composants, pour créer votre composant personnalisé.

Tout au long de cet article, nous allons développer un contrôle d'authentification entièrement personnalisable: je vous laisse donc le soin d'architecturer l'interface graphique de celui-ci selon vos besoins et/ou idées, le tout étant d'avoir, si possible, quelque chose ressemblant à ceci:

Contrôle d'authentification


Et voila !
La première partie, création du contrôle, étant maintenant terminée, nous allons donc voir comment l'utiliser dans nos applications.

Une chose importante à savoir: bien que ce contrôle soit développé en C#, vous pouvez tout à fait l'utiliser avec n'importe quelle autre langage Dotnet (VB.NET, J#, etc...)

II-B. Utilisation des attributs

Si vous voulez pouvoir modifier certaines propriétés de vos UserControls dans la fenêtre "Properties" (Propriétés) de Visual Studio, vous devez utiliser les attributs.
Voici une liste, non exhaustive, des attributs qu'il vous est possible d'utiliser:

  • Category
  • Description
  • Browsable
  • DefaultValue
  • DefaultEvent


Je vais détailler ici un peu plus certains de ces attributs.

II-B-1. Attribut Category


Cet attribut (Category)vous permet de définir dans quelle catégorie vous voulez que votre propriété soit placée. En effet, par défaut, la catégorie utilisée est "Misc" mais vous pouvez tout à fait modifier cela:

Paramétrage de l'attribut Category
Sélectionnez

[Category("Configuration")]
public String Title
{
    get
	{
		return this.gbLoginUserControl.Text;
    }
    set
    {
    	this.gbLoginUserControl.Text = value;
	}
}

II-B-2. Attribut Description

L'attribut Description vous permet d'afficher, dans l'explorateur de propriétés, une petite description relative à la propriété (ou l'événement) sélectionné. Cela peut s'avérer très pratique si vous avez besoin de donner des informations, à l'utilisateur.

Paramétrage de l'attribut Description
Sélectionnez

[Description("Le texte à afficher pour le nom d'utilisateur")]
public String LoginText
{
	get
    {
    	return this.lblLogin.Text;
    }
	set
    {
    	this.lblLogin.Text = value;
    }
}

II-B-3. Attribut Browsable

Le dernier attribut dont je voulais vous parler est l'attribut Browsable. Celui-ci vous permet d'indiquer si, dans l'explorateur de propriétés, la propriété sélectionnée peut être modifiée. Dans le cas contraire, elle apparait comme grisée dans l'explorateur.
A noter que cet attribut prend en paramètre un booléen, et non pas une chaîne de caractère comme pour les autres attributs.

Paramétrage de l'attribut Browsable
Sélectionnez

[Browsable(true)]
public String PasswordText
{
	get
    {
    	return this.lblPassword.Text;
    }
    set
    {
    	this.lblPassword.Text = value;
    }
}


Voici le résultat que vous pouvez, par exemple, obtenir après avoir utilisé plusieurs de ces attributs:

Code avec tous les attributs réunis
Sélectionnez

[Category("Configuration"), Browsable(true), Description("Le titre que vous voulez afficher")]
public String Title
{
	get
    {
    	return this.gbLoginUserControl.Text;
    }
    set
    {
    	this.gbLoginUserControl.Text = value;
    }
}

[Category("Configuration"), Browsable(true), Description("Le texte à afficher pour le nom d'utilisateur")]
public String LoginText
{
	get
    {
    	return this.lblLogin.Text;
    }
    set
    {
    	this.lblLogin.Text = value;
    }
}

[Category("Configuration"), Browsable(true), Description("Le texte à afficher pour le mot de passe")]
public String PasswordText
{
	get
    {
    	return this.lblPassword.Text;
    }
    set
    {
    	this.lblPassword.Text = value;
    }
}


Ce qui donne:

Propriétés du UserControl dans Visual Studio


Bien sûr, je ne vous l'ai pas dit avant, mais vous pouvez tout à fait combiner les attributs !

II-B-4. Attribut DesignerSerializationVisibility

Il est possible que vous soyez amené à developper un contrôle utilisateur qui utilise une collection comme propriété, jusque là, pas de problème.
Cependant, lorsque vous utilisez votre contrôle sur un formulaire Windows, et que vous ajoutez des éléments à cette collection, rien ne change dans le Designer (et rien n'apparaît dans le code d'initialisation du formulaire).
Pour que votre contrôle garde les valeurs qui ont été saisies dans le Designer, vous devrez utiliser l'attribut DesignerSerializationVisibility sur votre propriété:

Attribut DesignerSerializationVisibility
Sélectionnez

List<String> list = new List<String>();

[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public DisplayList
{
	get
	{
		return list;
	}
}


Vous trouverez plus d'informations sur cet attribut à cette adresse.

II-C. Associer une image à votre UserControl

Vous avez la possibilité d'associer une image à votre UserControl, afin de le personnaliser encore plus et de le reconnaitre plus facilement dans la boite à outils.
Pour cela, commencez par inclure votre image à votre projet (clique droit sur le projet, puis sélectionner "Add" => "New Item") et, dans les propriétés, positionner "Build Action" sur "Embedded Ressource". Cela aura pour effet d'incorporer votre image dans la DLL de votre UserControl.
Ensuite, il ne vous reste plus qu'à ajouter un attribut à votre contrôle: l'attribut ToolboxBitmap.

L'attribut ToolboxBitmap permet d'associer une image à votre contrôle, image qui sera visible dans la boîte à outils. Voyons comment cela se passe:

Association d'une image au contrôle
Sélectionnez

[ToolboxBitmap(typeof(LoginuserControl), "favicon.ico")]
public partial class LoginuserControl : UserControl
{
	public LoginuserControl()
    {
		InitializeComponent();
	}
}


Le constructeur de ToolboxBitmap prend jusqu'à deux paramètres:

  • le type qui définit l'assemblage dans lequel rechercher l'image du contrôle
  • le nom de l'image


Le résultat est assez parlant de lui-même:

Association de l'image au UserControl

III. Utilisation du UserControl

Je vous l'ai dit un peu plus haut dans cet article, un UserControl, ce n'est qu'un simple contrôle personnalisé. Par conséquent, comme tous les contrôles que vous utilisez, il se trouve également dans votre boîte à outils.
S'il n'y apparait pas, vous devrez peut-être l'y ajouter vous-même. Pour cela, faites un clic droit sur votre boîte à outils, pius choisissez "Choose Items". Dans la boite de dialogue qui apparait, cliquez sur "Browse" puis allez chercher la DLL correspondant à votre UserControl:

Ajout d'un UserControl à votre barre d'outils


Il ne vous reste plus qu'à valider pour voir ensuite votre contrôle apparaitre dans la boîte à outils:

UserControl dans la boite à outils


faites maintenant un glisser/déposer de votre contrôle sur un formulaire: Visual Studio ajoutera automatiquement les dépendances nécessaires et placera le contrôle là où vous l'avez indiqué !

Votre contrôle sur un formulaire

IV. Un peu plus loin

Vous vous dîtes surement que pour le moment, c'est pas mal mais vous trouvez ça léger, je me trompe ?
Rassurez-vous, jusqu'à maintenant, nous avons les principales bases de développement d'un contrôle personnalisé en C#. Nous allons maintenant étudier des concepts plus poussés qui vous permettront d'améliorer votre contrôle.

IV-A. Les événements

Comme tout contrôle .NET, votre UserControl possède des évènements prédéfinis (Load, Paint, etc...), jusque là, rien de bien nouveau.
Mais dans le cadre de notre article, nous avons développé un UserControl avec 2 boutons: un bouton de validation et un bouton d'annulation. Or, lorsque vous faites un glisser/déposer de votre contrôle sur un formulaire Windows, vous vous rendez compte que vous ne pouvez pas sélectionner un des deux boutons pour changer la valeur de son événement Click.
Pour remédier à cela, vous devez créer un (ou plusieurs) événements personnalisés, ce que nous allons voir tout de suite.

Pour que votre UserControl puisse utiliser votre événement, vous devez avoir au moins deux choses:

  • un délégué pour l'événement
  • le UserControl qui contient la déclaration de l'événement


Vous pouvez également utiliser une classe qui dérive de System.EventArgs, qui sera utilisée pour contenir les données relatives à l'événement (état, etc...).
Voyons cela par l'exemple: On commence par déclarer les délégués:

Déclaration des délégués
Sélectionnez

// Déclaration des délégués
public delegate void ValidButtonClickHandler(object sender, EventArgs e);
public delegate void CancelButtonClickHandler(object sender, EventArgs e);


Maintenant, déclarez les événements qui utilisent ces délégués:

Déclaration des événements
Sélectionnez

// Déclaration des évènements qui utilisent ces délégués
[Category("Configuration"), Browsable(true), Description("Evènement associé au bouton de validation")]
public event ValidButtonClickHandler BoutonValidClick;

[Category("Configuration"), Browsable(true), Description("Evènement associé au bouton d'annulation")]
public event CancelButtonClickHandler BoutonCancelClick;


On créé ensuite les méthodes qui vont utiliser ces événements:

Méthodes
Sélectionnez

protected virtual void OnValidButtonClick(EventArgs e)
{
    if (BoutonValidClick != null)
	{
    	BoutonValidClick(this, e);
	}
}

protected virtual void OnCancelButtonClick(EventArgs e)
{
    if (BoutonCancelClick != null)
    {
    	BoutonCancelClick(this, e);
	}
}


Et voila, vous avez (presque) fini !
En effet, à partir de maintenant, tout ce qu'il vous reste à faire, c'est d'appeller vos méthodes dans l'événement Click (ou autre) de vos boutons:

Evénement Click des boutons
Sélectionnez

// On lance nos méthodes
private void btValid_Click(object sender, EventArgs e)
{
	OnValidButtonClick(e);
}

private void btCancel_Click(object sender, EventArgs e)
{
	OnCancelButtonClick(e);
}


Le résultat est directement visible lorsque vous utilisez votre UserControl sur un formulaire Windows:

Evénements d'un UserControl

IV-B. Les SmartTags

Les SmartTags sont une des nouveautés disponibles avec Visual Studio 2005 et le Framework .NET 2.0. Ils représentent une sorte de menu contextuel pour vos contrôles.
Et bien sachez que vous avez la possibilité de créer vos propres SmartTags pour votre contrôle.

Pour commencer, créer une classe UserControlActionList qui héritera de System.ComponentModel.Design.DesignerActionList: cette classe contiendra la liste des propriétés qui devront être ajoutées au SmartTag:

Classe UserControlActionList
Sélectionnez

public class UserControlActionList : System.ComponentModel.Design.DesignerActionList
{
	public UserControlActionList(IComponent component) : base(component)
    { }
 
 	// Liste des propriétés à ajouter au SmartTag
    public String Title
    {
    	get
        {
        	return ((LoginuserControl)this.Component).Title; 
        }
        set
        {
        	PropertyDescriptor property = TypeDescriptor.GetProperties(this.Component)["Title"];
        	property.SetValue(this.Component, value);
		}
	}

	public String LoginText
    {
	    get
	    {
	    	return ((LoginuserControl)this.Component).LoginText;
	    }
	    set
	    {
	    	PropertyDescriptor property = TypeDescriptor.GetProperties(this.Component)["LoginText"];
	    	property.SetValue(this.Component, value);
	    }
    }

    public String PasswordText
    {
    	get
        {
        	return ((LoginuserControl)this.Component).PasswordText;
        }
        set
        {
        	PropertyDescriptor property = TypeDescriptor.GetProperties(this.Component)["PasswordText"];
        	property.SetValue(this.Component, value);
		}
	}


Dans cette classe, redéfinissons la méthode GetSortedActionItems qui nous permet de récupérer les actions définies par l'utilisateur.

Redéfinition de GetSortedActionItems
Sélectionnez

public override System.ComponentModel.Design.DesignerActionItemCollection GetSortedActionItems()
{
System.ComponentModel.Design.DesignerActionItemCollection items = new System.ComponentModel.Design.DesignerActionItemCollection();

items.Add(new System.ComponentModel.Design.DesignerActionHeaderItem("Paramétrage"));

items.Add(new System.ComponentModel.Design.DesignerActionPropertyItem("Title", "Définissez le titre du groupe de contrôles: ",
 "Titre", "Titre du groupe de contrôle"));
    items.Add(new System.ComponentModel.Design.DesignerActionPropertyItem("LoginText", "Définissez le texte du champ Login: ",
	 "LoginText", "Texte du champ Login"));
    items.Add(new System.ComponentModel.Design.DesignerActionPropertyItem("PasswordText", "Définissez le texte du champ Password: ",
	 "PasswordText", "Texte du champ Password"));
    items.Add(new System.ComponentModel.Design.DesignerActionPropertyItem("LoginValue", "Définissez la valeur du champ Login: ",
	 "LoginValue", "Valeur du champ Login"));
    items.Add(new System.ComponentModel.Design.DesignerActionPropertyItem("PasswordValue", "Définissez la valeur du champ Password: ",
	 "PasswordValue", "Valeur du champ Password"));
    items.Add(new System.ComponentModel.Design.DesignerActionPropertyItem("PasswordChar",
	 "Définissez la caractère utilisé pour masquer le mot de passe: ", "PasswordChar", "Valeur du caractère pour le Password"));
    items.Add(new System.ComponentModel.Design.DesignerActionPropertyItem("TexteBoutonValid",
	"Définissez le texte du bouton de validation: ", "TexteBoutonValid", "Texte du bouton de Validation"));
    items.Add(new System.ComponentModel.Design.DesignerActionPropertyItem("TexteBoutonCancel",
	"Définissez le texte du bouton d'annulation: ", "TexteBoutonCancel", "Texte du bouton d'Annulation"));

	return items;
}


A noter que cette méthode vous renvoit une DesignerActionItemCollection (une collection de DesignerActionItem ) et que vous avez à votre disposition, les DesignerActionItem suivants:

  • DesignerActionHeaderItem: Permet d'afficher un nom de groupe de propriétés
  • DesignerActionMethodItem: Permet d'appeler une méthode de l'ActionList
  • DesignerActionPropertyItem: Permet d'afficher/éditer une propriété
  • DesignerActionTextItem: Permet d'afficher une ligne de texte


Une fois que vous avez fait cela, il ne vous reste plus qu'à créer le SmartTag. Cela se fait en créant une classe (par exemple DesignerUserControl), qui hérite de System.Windows.Forms.Design.ControlDesigner.
Dans cette classe, nous allons redéfinir une propriété, ActionLists, qui renvoit une System.ComponentModel.Design.DesignerActionListCollection et qui nous permet de récupérer la liste de tous les éléments qui seront affichés dans le SmartTag.

Redéfinition de ActionLists
Sélectionnez

public class DesignerUserControl : System.Windows.Forms.Design.ControlDesigner
{
	// On définit la liste des actions du SmartTag
    public override System.ComponentModel.Design.DesignerActionListCollection ActionLists
    {
    	get
        {
        	System.ComponentModel.Design.DesignerActionListCollection collectionAction = new 
			System.ComponentModel.Design.DesignerActionListCollection();
            UserControlActionList designerActionList = new UserControlActionList(this.Control);
            collectionAction.Add(designerActionList);

			return collectionAction;
        }
    }
}


Et voila, vous avez terminé la création de votre SmartTag. Pour l'utiliser, c'est très simple: il vous suffit simplement d'ajouter l'attribut Designer à votre UserControl:

Association du SmartTag au UserControl
Sélectionnez

[Designer(typeof(DesignerUserControl))]
public partial class LoginuserControl : UserControl
{
	public LoginuserControl()
    {
    	InitializeComponent();
    }
}


Et observez le résultat lorsque vous utiliser votre contrôle sur un formulaire Windows:

Création du SmartTag


Avant de passer à la suite, voici quelques conseils pour la création de SmartTag:

  • Ajouter l'attribut [Docking(DockingBehavior.Ask)] à votre UserControl vous permet d'afficher, dans le SmartTag, la commande "Dock in parent container"
  • Vous devez rajouter une référence au namespace System.Design
  • Vous devez ajouter les using correspondants à System.Windows.Forms.Design et System.ComponentModel.Design


Enfin, voici un lien vers un autre article traitant des SmartTags: http://odelmotte.developpez.com/tutoriels/dotnet/controlesavances/?page=SmartTag (par Olivier Delmotte)

IV-C. Les DesignerVerbs

Les DesignerVerbs sont des liens cliquables qui apparaissent dans l'explorateur de propriétés de Visual Studio, dans le menu contextuel du contrôle et dans le SmartTags.
Comme pour les SmartTags, pour créer un DesignerVerb, il faut créer une classe qui héritera de ControlDesigner. Là encore, nous allons surcharger une propriété, Verbs, qui renvoit une DesignerVerbCollection, et qui est utilisée pour avoir la liste de tous les DesignerVerb.

Création d'un DesignerVerb
Sélectionnez

public class DesignerUserControl : System.Windows.Forms.Design.ControlDesigner
{
	public override System.ComponentModel.Design.DesignerVerbCollection Verbs
    {
    	get
        {
        	// On définit une collection de DesignerVerbs
            DesignerVerbCollection collectionVerbs = new DesignerVerbCollection();

			// Ensuite, un à un, on ajoute des DesignerVerb à cette collection
            collectionVerbs.Add(new DesignerVerb("Afficher SmartTag",
			 new EventHandler(this.EventHandlerDisplaySmartTagVerbs)));
            collectionVerbs.Add(new DesignerVerb("Visiter le site Web de l'auteur",
			 new EventHandler(this.EventHandlerVisitWebsiteVerbs)));

			return collectionVerbs;
        }
    }
}


Comme vous pouvez le voir, la collection DesignerVerbCollection n'est qu'un ensemble de DesignerVerb. Le constructeur de la classe DesignerVerb prend en paramètre deux choses:

  • le texte du DesignerVerb, qui sera affiché dans le PropertyGrid, le menu contextuel et le SmartTag
  • l'événement qui est lié au DesignerVerb, et qui surviendra lorsque l'on cliquera dessus


Dans mon cas, les événements sont très simples:

Evénements liés aux DesignerVerb
Sélectionnez

private void EventHandlerDisplaySmartTagVerbs(object sender, EventArgs e)
{
	MessageBox.Show("Vous avez cliquer sur Afficher SmartTag");
}

private void EventHandlerVisitWebsiteVerbs(object sender, EventArgs e)
{
	System.Diagnostics.Process.Start("http://morpheus.developpez.com");
}


Mais libre à vous de faire des choses plus complexes ;)

Enfin, pensez aussi à marquer votre contrôle avec l'attribut Designer:

Association des DesignerVerbs au UserControl
Sélectionnez

[Designer(typeof(DesignerUserControl))]
public partial class LoginuserControl : UserControl
{
	public LoginuserControl()
    {
    	InitializeComponent();
    }
}


Voici le résultat en image:

Les DesignerVerbs


Si votre DesignerVerb n'apparaît pas dans le PropertyGrid, mais bien dans le menu contextuel et/ou le SmartTag, faites un clic droit sur le PropertyGrid et assurez vous que "Commands" est coché.

V. Conclusions

Grâce à cet article, vous avez pu vous rendre compte que développer un UserControl (Contrôle Utilisateur) s'avère extrèmement simple et rapide.
Vous avez également appris comment le personnaliser le plus possible, pour faire en sorte qu'il soit vraiment adapté à vos besoins, et le plus simple d'utilisation possible.

VI. Téléchargements

L'article au format PDF: Article
Les sources du contrôle d'authentification: Sources

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2006 LEBRUN Thomas. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.