• Aucun résultat trouvé

Créer ses propres collections par du code

Les collections

5. Créer ses propres collections par du code

Il y a la collection Controls, créée et gérée automatiquement par VB, avec toutes les limites que nous venons de découvrir. Mais il existe aussi la possibilité de créer ses propres collections par du code. Bien

que cela soit un peu fastidieux, c'est parfois le seul moyen de gérer correctement certains problèmes.

5.1 Déclarer une collection

La première chose à faire sera de déclarer la collection, en lui donnant un nom (exactement comme on déclare une variable, ou un tableau). Par exemple :

Dim Ensemble as New Collection()

5.2 Remplir et vider une collection

Ensuite, il va falloir entrer dans cette collection, un par un, tous les éléments qui devront en faire partie, via la méthode Add. Par exemple :

Ensemble.Add(Me.Textbox1) Ensemble.Add(Me.Textbox2) Ensemble.Add(Me.Label5)

etc.

Disons tout de suite qu'on peut, de même, retirer un contrôle d'une collection par la méthode Remove : Ensemble.Remove(Me.Label5)

Arrivés à ce stade, nous savons donc gérer comme bon nous semble les membres d'une collection. Cela nous permet notamment de pouvoir procéder sans problèmes à des balayages systématiques (par exemple pour initialiser les valeurs de toute une série de contrôles, pour les rendre visibles ou invisibles, etc.). Cela nous permet également de désigner chaque contrôle membre de notre collection par son indice dans cette

collection, exactement comme nous le faisions avec la collection prédéfinie Controls. Enfin... presque !

Remarque bonne pour la santé mentale :

Les concepteurs de Visual Basic .Net ont décidé que si les indices des collections prédéfinies, telle Controls, commençaient en toute logique à zéro, les indices des collections créées par le programmeur

commenceraient quant à eux à 1 !

Si le gars de chez Microsoft dont j'ai parlé tout à l'heure m'appelle, tant qu'il y est, qu'il prépare aussi un argumentaire pour m'expliquer cela. Et qu'il fasse preuve d'imagination...

5.3 "Brancher" les événements sur une procédure unique

Passons. Un autre avantage considérable de disposer de tableaux de contrôles, était de pouvoir traiter un même événement survenant aux différents membres du tableau avec une seule procédure. Dans l'état

actuel de nos connaissances, c'est certes possible, via l'instruction Handles qui figure dans les titres des procédures : il suffit de faire suivre cette instruction Handles de la liste complète des membres de la

collection. C'est d'ailleurs cette technique que nous avons déjà eu l'occasion d'utiliser dans plusieurs exercices, sans même pour autant avoir créé de collection. Toutefois, cette combine a des limites :

dans le cas d'un ensemble formé de très nombreux contrôles, il va s'avérer infernal de devoir énumérer à la main tous ces contrôles après l'instruction Handles (pensez au démineur de Windows,

dont le plateau de jeu est formé d'un damier de boutons pouvant compter plusieurs centaines d'exemplaires !)

même si nous n'avons pas encore étudié cette situation, les contrôles ne sont pas toujours créés au départ du programme, via la fenêtre Design. Dans bien des cas, on va souhaiter créer des contrôles par du code, en cours d'exécution. Dès lors, comment rattacher les événements survenant à

ces contrôles - qui n'existent pas encore - à telle ou telle procédure événementielle, lorsqu'on écrit celle-ci ?

La parade à ces problèmes tient dans la possibilité de rattacher par du code, donc en cours d'exécution, tel événement survenant à tel contrôle, à telle procédure existante. C'est le sens de l'instruction

AddHandler, qui donnera par exemple : AddHandler Button2.Click AddressOf MiseAJour

Dans cet exemple, MiseAJour est le nom de la procédure sur laquelle nous programmons le "branchement" de l'événement Button2.Click.

Nous sommes presque au bout de nos peines. Nous savons à présent :

regrouper les contrôles de notre choix dans une collection parcourir cette collection pour la traiter de manière systématique

associer l'ensemble des contrôles d'une collection à une seule procédure événementielle, afin d'en simplifier la gestion.

5.4 Indentifier le contrôle qui a déclenché l'événement

Il ne nous reste plus qu'un seul souci, mais de taille. Imaginons que nous ayons 125 boutons sur notre Form, sur lequel un clic mène infailliblement à une procédure unique. Comment faire pour récupérer, au sein

de cette procédure, le bouton précis qui a provoqué l'événement (ce qui est souvent indispensable) ? Nous disposons certes du paramètre Sender, que nous avons déjà utilisé lors d'exercices précédents. Sender est

Il y a alors de fortes chances pour que nous ayons besoin de savoir à quel indice dans la collection correspond le contrôle désigné par cette variable Sender. Pour cela, nous pouvons utiliser la méthode

IndexOf, qui renvoie l'indice de n'importe quel contrôle au sein de n'importe quelle collection... enfin, presque. J'y reviens dans un instant. Ainsi, imaginons que nous ayons créé un Panel comprenant une série de

100 boutons, pour lesquels une boucle a habilement renvoyé l'événement Click vers une procédure Yaclic. Supposons enfin que nous souhaitions afficher en titre de la Form l'indice du bouton sur lequel l'utilisateur

vient de cliquer. La procédure Yaclic aurait alors la tête suivante :

Private Sub Yaclic(ByVal sender As System.Object, ByVal e As System.EventArgs) Dim i As Integer

i = Panel1.Controls.IndexOf(sender) Me.Text = i

End Sub

Cette technique, simple et efficace, ne fonctionnera toutefois pas au sein des collections que nous aurons créées et remplies par du code, les collections créées par le programmeur ignorant la méthode

IndexOf ! Pour celles-ci, il faudra avoir recours à une voie détournée : programmer une boucle qui compare, par exemple, la propriété Name de chaque membre de la collection Macollec avec celui du sender, sur le

modèle suivant :

Private Sub Yaclic(ByVal sender As System.Object, ByVal e As System.EventArgs) Dim i As Integer

For i = 1 to Macollec.Count

If Macollec.Item(i).Name = sender.Name Then Me.Text = i

Endif Next i

End Sub

En conclusion : VB.Net permet de faire tout ce que nous permettaient les tableaux de contrôles des versions précédentes de VB, mais au prix d'un code nettement plus compliqué. Et par-dessus le marché, au

lieu d'établir une règle simple fonctionnant dans toutes les situations, les gars de chez Microsoft se sont amusés à multiplier les exceptions. Comme quoi, les Shadoks ont incontestablement inspiré Bill Gates lorsqu'ils proclamaient solennellement : "En essayant continuellement, on finit par réussir. Donc : plus ça

rate, plus on a de chance que ça marche"