Utilisation du Binding au travers de l'objet DataBindingSource

Description

De nombreuses questions sur le forum portent sur l'affichage simultané d'une même source de données par le biais de contrôles différents en Windows Form. L'utilisation du Binding avec l'objet DataBindingSource est une solution assez simple de mise en oeuvre et efficace.
Ce tutoriel se propose d'expliquer l'utilisation de cet objet.
Voir ici la source exemple pour ce tutoriel.

Edit: Ça marche aussi en VB.Net, voir la source ici.

J'ai utilisé une classe Personne issue d'exercices que j'ai fait lors d'un stage à la Défense en novembre 2011, ainsi qu'une méthode d'extension de classe.
D4rkTiger avait présenté les extensions de classe dans cette source.

Introduction

Nous allons afficher les informations relatives à une liste de contacts dans un DataGridView, une ListBox et deux TextBox. Nous montrerons ensuite comment formater spécifiquement une information, une date longue dans l'exemple.

Binder des contrôles avec une source de données

J'ai créé un projet avec la classe Personne et celle d'extension.

Commençons par poser un DataGridView sur la Form.

Cette fenêtre s'ouvre, elle sera accessible plus tard en cliquant sur la petite flèche en haut à droite du DataGridView

Ouvrons la liste déroulante Choisir la source de données pour ajouter une source qui représentera notre classe Personne



Ensuite personnalisons le DataGridView (entête, ordres des colonnes, etc...)

On constate qu'un objet DataBindingSource a été ajouté au projet.

Ajoutons une ListBox et un TextBox

Lions ces contrôles avec l'objet personneBindingSource




Il ne reste plus qu'a initialiser notre liste de contacts, de l'affecter au DataSource de personneBindingSource et à l'exécution l'affichage est automatique.

Code C#

List<Personne> mesPersonnes = new List<Personne>();

//Je crée une instance avec le contructeur par défaut, et j'ajoute cette instance
Personne quelque1 = new Personne();
mesPersonnes.Add(quelque1);

//J'ajoute une instance avec le deuxième constructeur
mesPersonnes.Add(new Personne("LeBienNommé"));

//J'ajoute une instance avec le troisième constructeur
mesPersonnes.Add(new Personne("Sors", "Jean", "01/01/2012".ToDate()));

//Je crée une instance par conversion implicite depuis une string et je l'ajoute.
Personne quelque1dAutre = "Marc, Assin (02/01/2012)";
mesPersonnes.Add(quelque1dAutre);

//J'affecte ma liste à l'objet databingsource
personneBindingSource.DataSource = mesPersonnes;

Code VB.Net

'             * Je remplis ma liste de personnes de 4 façons différentes, pour l'exemple
'             

   'Je crée une instance avec le contructeur par défaut, et j'ajoute cette instance
   Dim quelque1 As New Personne()
   mesPersonnes.Add(quelque1)

   'J'ajoute une instance avec le deuxième constructeur
   mesPersonnes.Add(New Personne("LeBienNommé"))

   'J'ajoute une instance avec le troisième constructeur
   mesPersonnes.Add(New Personne("Sors", "Jean", "01/01/2012".ToDate()))

   'Je crée une instance par conversion implicite depuis une string et je l'ajoute.
   Dim quelque1dAutre As Personne = "Marc, Assin (02/01/2012)"
   mesPersonnes.Add(quelque1dAutre)

   'J'affecte ma liste à l'objet databingsource
   personneBindingSource.DataSource = mesPersonnes

Formatage personnalisé de données bindées

Maintenant nous souhaitons afficher la date de naissance au format long dans un TextBox, il va falloir imposer au Binding ce formatage.

Regardons le code généré par Visual Studio pour les contrôles déjà présents.


Code C#

....
this.dataGridView1.DataSource = this.personneBindingSource;
.....
this.nomDataGridViewTextBoxColumn.DataPropertyName = "Nom";
.....
this.prenomDataGridViewTextBoxColumn.DataPropertyName = "Prenom";
....
this.naissanceDataGridViewTextBoxColumn.DataPropertyName = "Naissance";
....
this.listBox1.DataSource = this.personneBindingSource;
....
this.textBox1.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.personneBindingSource, "Prenom", true));
.....

On voit que selon le type de contrôle la syntaxe diffère, et que dans notre cas pour un TextBox il faut créer un objet Binding permettant le formatage voulu.

Code C#

//J'affecte le binding de la date de naissance au textbox en mettant la date longue
Binding monBinding = new Binding("Text", personneBindingSource, "Naissance");
txtNaissance.DataBindings.Add(monBinding);

A ce moment, le format de la date est celui par défaut. Il existe deux événement de l'objet Binding que nous allons utiliser : Format et Parse :
Code C#

//J'affecte le binding de la date de naissance au textbox en mettant la date longue
Binding monBinding = new Binding("Text", personneBindingSource, "Naissance");
monBinding.Format += new ConvertEventHandler(FormatDeDateLongue);//on abonne la méthode de formatage à l'événement Format

monBinding.Parse += new ConvertEventHandler(ParseUneDate);//on abonne la méthode de parsing à l'évènement Parse
txtNaissance.DataBindings.Add(monBinding);

Code VB.Net

   'J'affecte le binding de la date de naissance au textbox en mettant la date longue
   Dim monBinding As New Binding("Text", personneBindingSource, "Naissance")
   AddHandler monBinding.Format, AddressOf FormatDeDateLongue 'on abonne la méthode de formatage à l'événement Format
   AddHandler monBinding.Parse, AddressOf ParseUneDate 'on abonne la méthode de parsing à l'évènement Parse
   txtNaissance.DataBindings.Add(monBinding)

En C#, à l'écriture de += l'environnement nous invite à taper la touche Tab pour générer tout seul les méthodes utiles, laissons le faire (en prenant éventuellement soin de renommer les méthodes) ce que j'ai fait).

Voici la méthode Parse générée automatiquement:
Code C#

void monBinding_Parse(object sender, ConvertEventArgs e)
{
throw new NotImplementedException();
}

Il faut maintenant modifier ces deux méthodes :
Code C#

private void ParseUneDate(object sender, ConvertEventArgs e)
{
e.Value = e.Value.ToString().ToDate();//Parse la valeur en datetime avec l'extension de classe
}

private void FormatDeDateLongue(object sender, ConvertEventArgs e)
{
DateTime maDate = Convert.ToDateTime(e.Value);//recupération la date à partir de la valeur à afficher
e.Value = maDate.ToString("D");
}

Code VB.Net

  Private Sub ParseUneDate(ByVal sender As Object, ByVal e As ConvertEventArgs)
   e.Value = e.Value.ToString().ToDate() 'Parse la valeur en date time avec l'extension de classe
  End Sub

  Private Sub FormatDeDateLongue(ByVal sender As Object, ByVal e As ConvertEventArgs)

   Dim maDate As Date = Convert.ToDateTime(e.Value) 'recupération la date à partir de la valeur à afficher
   e.Value = maDate.ToString("D")
  End Sub

Pour info, le code de l'extension classe qui converti une chaîne de caractères en DateTime

Code C#

public static DateTime ToDate(this string chaine)
{
/*exemple
* "01/01/2012 08:32".ToDate()
* string date = "01/01/2012 08:32";
* date.ToDate();
*/
DateTime Date = Convert.ToDateTime(chaine);
return Date;
}
        ''' Retourne un DateTime à partir d'un objet de type string ou String
        <System.Runtime.CompilerServices.Extension()> _
        Public Function ToDate(ByVal chaine As String) As Date
            '            exemple
            '             * "01/01/2012 08:32".ToDate()
            '             * string date = "01/01/2012 08:32";
            '             * date.ToDate();
            '             
            Dim [Date] As Date = Convert.ToDateTime(chaine)
            Return [Date]
Ce document intitulé « Utilisation du Binding au travers de l'objet DataBindingSource » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous