Leblanc Livre - Librairie Eyrolles

publicité
25
Liaisons de données
Plusieurs composants visuels (zone d’édition, boîte de liste, etc.) présentent une
propriété DataSource qui permet d’associer directement une source de données au composant. Les données peuvent provenir d’une base de données (résultat d’une requête SQL
par exemple), d’un tableau ou d’un conteneur. La technique de liaison de données permet
d’associer une source de données à un composant ce qui consiste à introduire automatiquement ces données dans le composant.
Il est certes possible de lire une base de données comme nous l’avons fait au chapitre 24
et initialiser les composants visuels à partir de ces données (propriétés Text ou Items selon
le composant) mais les techniques de liaison de données présentent de nombreux avantages
et notamment celui de leur caractère automatique.
Ce chapitre sera aussi l’occasion d’introduire les grilles de données.
25.1 Liaison avec boîte de liste
À la section 16.1, nous avons appris à charger une boîte de liste en utilisant la méthode
Add appliquée à la propriété Items d’une boîte de liste.
Il est possible de remplir directement une boîte de liste à partir d’un tableau (la technique
s’applique aussi aux boîtes combo). Si lbNoms désigne le nom interne d’une boîte de liste,
on peut en effet écrire :
string[] tabNoms = {"Gaston", "Jeanne", "Prunelle"};
.....
lbNoms.DataSource = tabNoms;
Toutes les chaînes contenues dans le tableau tabNoms sont alors automatiquement insérées
dans la boîte de liste.
578
C# et .NET
Dans le cas d’un tableau où chaque cellule contient plusieurs champs (cas d’un tableau
d’objets), il faut initialiser les propriétés DataSource (pour le nom du tableau) et DisplayMember (pour le nom du champ) :
public class Pers
{
string nom;
int age;
public Pers(string N, int A) {nom = N; age = A;}
public string Nom {get {return nom;}}
}
.....
Pers[] tp = {new Pers("Gaston", 27), new Pers("Jeanne", 23),
new Pers("Prunelle", 35)};
.....
lbNoms.DataSource = tp;
lbNoms.DisplayMember = "Nom";
Comme chaque cellule du tableau tp contient plusieurs champs, la propriété DisplayMember de la boîte de liste sert à spécifier le champ à retenir pour l’insertion dans la boîte
de liste. Il doit s’agir d’une propriété de la classe.
Dans la propriété DataSource, nous aurions pu spécifier un objet conteneur de l’une des
classes étudiées au chapitre 4 (par exemple un tableau dynamique ArrayList).
Enfin, le contenu de la boîte de liste peut provenir d’une base de données. Par exemple du
champ Nom de la table Pers de la base de données Biblio.mdb (ici du répertoire courant de
l’application) :
using System.Data;
using System.Data.OleDb;
.....
string connStr = "Provider=Microsoft.Jet.OLEDB.4.0;"
+ "Data Source=Biblio.mdb";
string selStr = "SELECT Nom FROM Auteurs ";
OleDbDataAdapter oDA = new OleDbDataAdapter(selStr, connStr);
DataSet oDS = new DataSet();
oDA.Fill(oDS, "Noms");
lbNoms.DataSource = oDS.Tables[0];
lbNoms.DisplayMember = "Nom";
Dans une application ASP.NET, écrivez (généralement dans Page_Load, la fonction MapPath
étant membre de la classe Page, voir le chapitre 28) :
connStr = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source="
+ MapPath("Biblio.mdb");
Liaisons de données
CHAPITRE 25
579
25.2 Liaison avec zone d’édition
Des données en provenance d’une base de données (ici en provenance de la table Auteurs
de la base de données Biblio créée à la section 24.2) peuvent être associées à des zones
d’édition ou d’affichage et il est possible d’assurer une navigation dans la base de
données (les boutons < et > sont prévus à cet effet). Le programme affiche dans les zones
d’édition des données en provenance des champs Nom, AnnéeNaiss et AnnéeMort de la table
Auteurs de la base de données Biblio. Chaque clic sur un bouton fait afficher la donnée
suivante (bouton >) ou la précédente (bouton <).
La fenêtre comprend trois zones d’édition (voir figure 25-1) : zeNom, zeAnnéeNaiss et
zeAnnéeMort.
Figure 25-1
La boîte de liste (lbNoms) contient des noms d’auteurs et a été initialisée comme nous
venons de l’apprendre. La boîte de liste est automatiquement synchronisée avec les
contenus des zones d’édition.
Nous ne répéterons pas les opérations de création du dataset (voir le chapitre 24).
Pour effectuer la liaison entre les champs du dataset et les composants visuels (ici trois
zones d’édition), il faut utiliser la propriété DataBindings du composant visuel et lui ajouter les liaisons à effectuer :
zeNom.DataBindings.Add("Text", oDS.Tables[0], "Nom");
zeAnnéeNaiss.DataBindings.Add("Text", oDS.Tables[0], "AnnéeNaiss");
zeAnnéeMort.DataBindings.Add("Text", oDS.Tables[0], "AnnéeMort");
La méthode Add appliquée à la propriété DataBindings du composant visuel prend trois
arguments :
• la propriété du composant visuel à initialiser avec le champ de la donnée (propriété
Text puisqu’il s’agit d’une zone d’édition mais il pourrait s’agir de n’importe quelle
autre propriété) ;
• la table dans le dataset ;
• le nom du champ dans cette table du dataset.
580
C# et .NET
Pour assurer la navigation dans le dataset (suite à des clics sur les boutons étiquetés < et >),
il faut :
1. Déclarer une variable de type CurrencyManager, par exemple
CurrencyManager current;
en champ public de la classe de la fenêtre.
2. Initialiser cette variable pour signaler que current va contrôler le déplacement dans la
table :
current = (CurrencyManager)BindingContext(oDS.Tables[0]);
3. Incrémenter ou décrémenter le champ Position de la variable de type CurrencyManager :
current.Position++;
pour afficher dans les zones d’édition les données de la ligne suivante du dataset.
Dépasser la limite du nombre d’enregistrements (par exemple en cliquant sur > alors que
l’on est déjà sur le dernier enregistrement) n’a aucun effet. Il en va de même pour un clic
sur < alors que l’on est déjà positionné sur le premier enregistrement.
L’objet current contient le champ Count qui indique le nombre de lignes dans le dataset.
On pourrait tester (dans la fonction qui traite le clic sur le bouton >) :
if (current.Position < current.Count-1) current.Position++;
mais cela n’est même pas nécessaire puisque nous venons de voir qu’il n’y a aucun
danger à dépasser les limites.
La navigation par < et > dépend de la clause ORDER BY éventuellement spécifiée dans la
commande SQL de sélection (en l’absence de cette clause, il s’agit de l’ordre d’insertion
dans le dataset).
25.3 Liaison avec grille de données
La boîte à outils comprend l’outil DataGrid qui permet d’afficher des
données sous forme tabulaire.
Si dg est le nom interne de l’objet DataGrid (propriété Name), oDS le nom du dataset (voir le
chapitre 24) et Auteurs le nom d’une table dans ce dataset, on associe la grille aux
données du dataset en initialisant les propriétés de la grille :
• DataSource avec le nom du dataset ;
• DataMember avec le nom de la table dans le dataset.
Par exemple :
dg.DataSource = oDS;
dg.DataMember = "Auteurs";
La grille est alors automatiquement arrangée et les données provenant de la table dans le
dataset sont affichées dans la grille (voir figure 25-2).
Liaisons de données
CHAPITRE 25
581
Figure 25-2
Les données d’une grille peuvent provenir d’un dataset créé en mémoire :
DataTable dt;
DataColumn dc;
.....
dt = new DataTable("Pers");
// créer la table (objet DataTable)
// spécifier les colonnes de la table (nom + âge)
dt.Columns.Add("Nom", typeof(string));
dt.Columns.Add("Age", typeof(int));
// remplir la table de données
dt.Rows.Add(new Object[] {"Loulou", 33});
dt.Rows.Add(new Object[] {"Chouchou", 30});
dg.DataSource = dt;
Il n’est alors pas nécessaire d’initialiser la propriété DataMember de la grille car la propriété
DataSource a été initialisée avec un objet DataTable et celui-ci est limité à une seule table
(alors qu’un objet DataSet peut contenir plusieurs tables).
On pourrait écrire de manière tout à fait équivalente (il serait alors possible de spécifier
d’autre caractéristiques de colonne comme AllowNull, AutoIncrement, Caption, DefaultValue, ReadOnly et Unique, sans oublier que PrimaryKey est spécifié au niveau de la table) :
dt = new DataTable("Pers");
DataColum dc = new DataColumn("Nom", typeof(string));
dt.Columns.Add(dc);
dc = new DataColumn("Age", typeof(int)); dt.Columns.Add(dc);
DataRow dr = dt.NewRow();
dr["Nom"] = "Loulou"; dr["Age"] = 33;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["Nom"] = "Chouchou"; dr["Age"] = 30;
dt.Rows.Add(dr);
dg.DataSource = dt;
Au lieu d’initialiser la propriété DataSource, on peut écrire :
dg.SetDataBinding(dt, null);
Jusqu’à présent, notre grille affiche toutes les colonnes de la table et a un look tout à fait
standard. Nous allons améliorer cela progressivement.
582
C# et .NET
Intéressons-nous pour cela aux propriétés de la classe DataGrid.
Les propriétés de l’objet DataGrid sont nombreuses (voir figure 25-3). Elles permettent
de personnaliser la grille : titre de la grille, couleur d’arrière-plan, police d’affichage, etc.
Figure 25-3
Cliquer sur le lien Mise en forme automatique vous donne la possibilité de choisir parmi
plusieurs types de présentation de grilles. Vous trouverez ci-après les apparences générales pour les présentations dites par défaut, professionnelles, classiques, simples et 256
couleurs :
Personnalisation des grilles (Mise en forme automatique), figures 25-4 à 25-9.
Figure 25-4
Figure 25-5
Liaisons de données
CHAPITRE 25
583
Personnalisation des grilles (Mise en forme automatique), figures 25-4 à 25-9.
Figure 25-6
Figure 25-7
Figure 25-8
Figure 25-9
Plutôt que des manipulations de Visual Studio, envisageons des opérations par programme. Elles nous feront découvrir des propriétés de l’objet DataGrid.
Certaines propriétés s’appliquent à la grille dans son ensemble. Le nom de ces propriétés
indique clairement la fonction correspondante : AllowSorting (true par défaut), AlternatingBackColor, BackColor, BackgroundColor, BackgroundImage, BorderStyle, CaptionBackColor,
CaptionFont, CaptionForeColor, CaptionText, CaptionVisible, ColumnHeadersVisible, Font,
ForeColor, GridLineColor, GridLineStyle, HeaderBackColor, HeaderFont, HeaderForeColor,
SelectionBackColor et SelectionForeColor.
Si la propriété AllowSorting vaut true, un clic sur un en-tête de colonne provoque un tri,
alternativement de manière croissante et décroissante.
Par défaut, toutes les colonnes de la table sont affichées.
Pour personnaliser les colonnes, il faut créer une collection d’objets DataGridTableStyle.
Cette collection est accessible via la propriété TableStyles de la grille. DataGridTableStyle
est une classe qui représente les colonnes affichées. Un objet DataGridTableStyle doit être
584
C# et .NET
associé à une table (par exemple la table Auteurs de la base de données Librairie.mdb). En
créant plusieurs objets DataGridTableStyle et en modifiant la propriété TableStyles (de type
DataGridTableStyle) de la grille, on modifie complètement le contenu de la grille. Mais
aussi son apparence car la classe DataGridTableStyle contient également les propriétés
AllowSorting, AlternatingBackColor, BackColor, ForeColor, GridLineColor, GridLineStyle,
HeaderBackColor, HeaderFont, HeaderForeColor, RowHeaderVisible, SelectionBackColor et SelectionForeColor.
Dans l’exemple qui suit, nous ne reprenons que les colonnes Nom et Prénom de la table
Auteurs :
DataGridTableStyle dgts = new DataGridTableStyle();
dgts.MappingName = "Auteurs";
// nom de la table
DataGridColumnStyle dgcs = new DataGridTextBoxColumn();
dgcs.MappingName = "Nom";
// nom du champ
dgcs.HeaderText = "NOM";
// libellé de l’en-tête de colonne
dgcs.Width = 200;
// largeur de la colonne
dgts.GridColumnStyles.Add(dgcs);
dgcs = new DataGridTextBoxColumn();
// ajouter le champ Prénom
dgcs.MappingName = "Prénom";
dgcs.HeaderText = "Prénom";
dgcs.Width = 150;
dgts.GridColumnStyles.Add(dgcs);
dg.TableStyles.Add(dgts);
D’autres propriétés de DataGridColumnStyle sont :
Alignment
avec ses valeurs Left, Center et Right de l’énumération HorizontalAlignment.
NullText
texte à afficher quand le contenu du champ est nul.
ReadOnly
indique si le champ est en lecture seule.
Pour afficher une colonne de type date (champ DN de la table) dans laquelle on affiche le
mois (en abrégé) suivi de l’année, on écrit :
dgcs = new DataGridTextBoxColumn();
dgcs.MappingName = "DN";
dgcs.HeaderText = "Paru en";
dgcs.Format = "MMM yyyy";
dgcs.Width = 150;
dgts.GridColumnStyles.Add(dgcs);
25.4 Création de formulaires de données avec Visual Studio
Visual Studio.NET permet de créer des formulaires de données. Nous allons suivre les
différentes étapes de cette création. Pour insérer un formulaire de données dans le projet
de l’application, activez le menu (voir figure 25-10) Projet → Ajouter un nouvel élément.
Sélectionnez Assistant de formulaires de données. Une nouvelle classe de fenêtre est
créée. Par défaut, elle s’appelle DataForm1.
Liaisons de données
CHAPITRE 25
Figure 25-10
Un assistant va vous aider dans tout le processus de création (voir figure 25-11).
Figure 25-11
Commencez par donner un nom au dataset qui va être créé (voir figure 25-12).
585
586
C# et .NET
Figure 25-12
L’assistant va vous réclamer des informations concernant la base de données (voir figure
25-13). D’abord le pilote (il s’agit ici d’une base de données Access).
Figure 25-13
Liaisons de données
CHAPITRE 25
587
Spécifiez ensuite le nom de la base de données. Si la base de données doit se trouver dans
le répertoire de l’application, ne gardez que le nom relatif (voir figure 25-14).
Figure 25-14
Spécifiez enfin les modes d’accès et de partage (voir figure 25-15).
Figure 25-15
588
C# et .NET
Spécifiez les tables utilisées (voir figure 25-16).
Figure 25-16
Puis les champs à retenir dans chaque table (voir figure 25-17).
Figure 25-17
Liaisons de données
CHAPITRE 25
589
On spécifie ici la présentation générale : grille ou formulaire ainsi que les opérations
susceptibles d’être effectuées : ajout, suppression, annulation et navigation (voir figure
25-18).
Figure 25-18
Visual Studio.NET donne la présentation générale de la fenêtre. Vous pouvez retravailler
entièrement cette présentation et modifier toutes les propriétés. Vous pourriez aussi éliminer le bouton Charger et placer le code de cette fonction dans le constructeur de la classe
DataForm1, après le commentaire TODO (voir figure 25-19).
Figure 25-19
590
C# et .NET
Pour que cette fenêtre soit affichée au démarrage de l’application, modifiez Main dans
Form1.cs comme suit (remplacer Form1 par DataForm1) :
static void Main()
{
Application.Run(new DataForm1());
}
Téléchargement