VB.NET: Que s'est-il passé pour contrôler les tableaux

L'omission des tableaux de contrôle de VB.NET est un défi pour ceux qui enseignent les tableaux.

  • Il n'est plus possible de copier simplement un contrôle, tel qu'une zone de texte, puis de le coller (une ou plusieurs fois) pour créer un tableau de contrôles.
  • Le code VB.NET pour créer une structure similaire à un tableau de contrôle a été, dans tous les livres sur VB.NET que j'ai achetés et en ligne, beaucoup plus long et beaucoup plus complexe. Il manque la simplicité du codage d'un tableau de contrôle que l'on trouve dans VB6.

Si vous référencez la bibliothèque de compatibilité VB6, il y a des objets qui agissent à peu près comme des tableaux de contrôle. Pour voir ce que je veux dire, utilisez simplement l'assistant de mise à niveau VB.NET avec un programme qui contient un tableau de contrôle. Le code est à nouveau laid, mais cela fonctionne. La mauvaise nouvelle est que Microsoft ne garantit pas que les composants de compatibilité continueront d'être pris en charge et que vous n'êtes pas censé les utiliser.

instagram viewer

Le code VB.NET pour créer et utiliser des "tableaux de contrôle" est beaucoup plus long et beaucoup plus complexe.

Selon Microsoft, pour faire quelque chose de même proche de ce que vous pouvez faire dans VB 6, il faut créer un "composant simple qui duplique la fonctionnalité de la baie de contrôle".

Vous avez besoin à la fois d'une nouvelle classe et d'un formulaire d'hébergement pour illustrer cela. La classe crée et détruit en fait de nouvelles étiquettes. Le code de classe complet est le suivant:

LabelArray de classe publique
Hérite du système. Collections. CollectionBase
Private ReadOnly HostForm As _
Système. Les fenêtres. Formes. Forme
Fonction publique AddNewLabel () _
En tant que système. Les fenêtres. Formes. Étiquette
'Créez une nouvelle instance de la classe Label.
Dim aLabel As New System. Les fenêtres. Formes. Étiquette
'Ajoutez l'étiquette à la collection
'liste interne.
Moi. Liste. Ajouter (aLabel)
'Ajouter l'étiquette à la collection Controls
'du formulaire référencé par le champ HostForm.
HostForm. Contrôles. Ajouter (aLabel)
'Définissez les propriétés initiales de l'objet Label.
une marque. Haut = Nombre * 25
une marque. Largeur = 50
une marque. Gauche = 140
une marque. Tag = moi. Compter
une marque. Text = "Label" & Moi. Compter. ToString
Renvoyer une étiquette
Fonction de fin
Public Sub New (_
Hôte ByVal en tant que système. Les fenêtres. Formes. Forme)
HostForm = hôte
Moi. AddNewLabel ()
End Sub
Propriété publique en lecture seule par défaut _
Élément (indice ByVal en tant qu'entier) en tant que _
Système. Les fenêtres. Formes. Étiquette
Avoir
Retournez CType (Me. List. Élément (Index), _
Système. Les fenêtres. Formes. Étiquette)
Fin Get
Propriété de fin
Sous-public Supprimer ()
'Assurez-vous qu'il y a une étiquette à retirer.
Si moi. Compter> 0 Alors
'Supprimer la dernière étiquette ajoutée au tableau
»de la collection de contrôles du formulaire hôte.
'Notez l'utilisation de la propriété par défaut dans
'accéder au tableau.
HostForm. Contrôles. Supprimer (Moi (Me. Count - 1))
Moi. Liste. RemoveAt (Me. Count - 1)
Fin si
End Sub
Fin de classe

Pour illustrer comment ce code de classe serait utilisé, vous pouvez créer un formulaire qui l'appelle. Vous devrez utiliser le code ci-dessous dans le formulaire:

Formulaire de classe publique 1. Hérite du système. Les fenêtres. Formes. Forme. #Region "Code généré par Windows Form Designer" 'Vous devez également ajouter l'instruction:' MyControlArray = New LabelArray (Me) 'après l'appel InitializeComponent () dans le. 'code de région caché. 'Déclarez un nouvel objet ButtonArray. Dim MyControlArray As LabelArray. Sous privé btnLabelAdd_Click (_. Expéditeur ByVal en tant que système. Objet, _. ByVal e As System. EventArgs) _. Gère btnLabelAdd. Cliquez sur. 'Appelez la méthode AddNewLabel. 'de MyControlArray. MyControlArray. AddNewLabel () 'Modifiez la propriété BackColor. 'du bouton 0. MyControlArray (0) .BackColor = _. Système. Dessin. Couleur. Rouge. End Sub. Sous privé btnLabelRemove_Click (_. Expéditeur ByVal en tant que système. Objet, _. ByVal e As System. EventArgs) _. Gère btnLabelRemove. Cliquez sur. 'Appelez la méthode Remove de MyControlArray. MyControlArray. Retirer() End Sub. Fin de classe

Tout d'abord, cela ne fait même pas le travail au Design Time comme nous le faisions dans VB 6! Et deuxièmement, ils ne sont pas dans un tableau, ils sont dans une collection VB.NET - une chose très différente d'un tableau.

La raison pour laquelle VB.NET ne prend pas en charge le "tableau de contrôle" VB 6 est qu'il n'existe pas de "tableau" de "contrôle" (notez le changement de guillemets). VB 6 crée une collection en arrière-plan et la fait apparaître comme un tableau pour le développeur. Mais ce n'est pas un tableau et vous avez peu de contrôle sur lui au-delà des fonctions fournies par l'EDI.

VB.NET, d'autre part, l'appelle ce qu'il est: une collection d'objets. Et ils remettent les clés du royaume au développeur en créant le tout à découvert.

Comme exemple du type d'avantages que cela donne au développeur, dans VB 6, les contrôles devaient être du même type, et ils devaient avoir le même nom. Comme ce ne sont que des objets dans VB.NET, vous pouvez leur donner différents types et leur donner des noms différents tout en les gérant dans la même collection d'objets.

Dans cet exemple, le même événement Click gère deux boutons et une case à cocher et affiche celui sur lequel vous avez cliqué. Faites cela en une seule ligne de code avec VB 6!

Private Sub MixedControls_Click (_
Expéditeur ByVal en tant que système. Objet, _
ByVal e As System. EventArgs) _
Poignées Button1.Click, _
Button2.Click, _
CheckBox1.Click
«La déclaration ci-dessous doit être une longue déclaration!
«Il est sur quatre lignes ici pour le garder étroit
'assez pour tenir sur une page web
Label2.Text =
Microsoft. Visual Basic. Droite (expéditeur. GetType. ToString,
Len (expéditeur. GetType. ToString) -
(InStr (expéditeur. GetType. ToString, "Formulaires") + 5))
End Sub

Le calcul de la sous-chaîne est assez complexe, mais ce n'est pas vraiment ce dont nous parlons ici. Vous pouvez faire n'importe quoi dans l'événement Click. Vous pouvez, par exemple, utiliser le Type du contrôle dans une instruction If pour faire différentes choses pour différents contrôles.

Commentaires du Frank's Computing Studies Group sur les tableaux

Le groupe d'étude de Frank a fourni un exemple avec un formulaire qui a 4 étiquettes et 2 boutons. Le bouton 1 efface les étiquettes et le bouton 2 les remplit. C'est une bonne idée de relire la question originale de Frank et de remarquer que l'exemple qu'il a utilisé était une boucle qui est utilisée pour effacer la propriété Caption d'un tableau de composants Label. Voici l'équivalent VB.NET de ce code VB 6. Ce code fait ce que Frank avait demandé à l'origine!

Formulaire de classe publique 1. Hérite du système. Les fenêtres. Formes. Forme. #Region "Code généré par Windows Form Designer" Dim LabelArray (4) As Label. 'déclare un tableau d'étiquettes. Sous-formulaire privé1_Load (_. Expéditeur ByVal en tant que système. Objet, _. ByVal e As System. EventArgs) _. Gère MyBase. Charge. SetControlArray () End Sub. Sub SetControlArray () LabelArray (1) = Label1. LabelArray (2) = Label2. LabelArray (3) = Label3. LabelArray (4) = Label4. End Sub. Sous-bouton privé1_Cliquez (_. Expéditeur ByVal en tant que système. Objet, _. ByVal e As System. EventArgs) _. Poignées Button1.Click. 'Button 1 Clear Array. Dim a As Integer. Pour a = 1 à 4. LabelArray (a) .Text = "" Prochain. End Sub. Sous-bouton privé2_Click (_. Expéditeur ByVal en tant que système. Objet, _. ByVal e As System. EventArgs) _. Poignées Button2.Click. 'Button 2 Fill Array. Dim a As Integer. Pour a = 1 à 4. LabelArray (a) .Text = _. "Control Array" et CStr (a) Prochain. End Sub. Fin de classe

Si vous expérimentez ce code, vous découvrirez qu'en plus de définir les propriétés des étiquettes, vous pouvez également appeler des méthodes. Alors pourquoi ai-je (et Microsoft) fait tout ce qui était en mon pouvoir pour créer le code "laid" dans la première partie de l'article?

Je ne suis pas d'accord pour dire que c'est vraiment un "Control Array" au sens classique du VB. Le tableau de contrôle VB 6 est une partie prise en charge de la syntaxe VB 6, pas seulement une technique. En fait, peut-être que la façon de décrire cet exemple est qu'il s'agit d'un tableau de contrôles, et non d'un tableau de contrôles.

Dans la partie I, je me plaignais que l'exemple de Microsoft fonctionnait UNIQUEMENT au moment de l'exécution et non au moment de la conception. Vous pouvez ajouter et supprimer des contrôles d'un formulaire dynamiquement, mais le tout doit être implémenté dans le code. Vous ne pouvez pas faire glisser et déposer des contrôles pour les créer comme vous le pouvez dans VB 6. Cet exemple fonctionne principalement au moment de la conception et non au moment de l'exécution. Vous ne pouvez pas ajouter et supprimer des contrôles dynamiquement au moment de l'exécution. D'une certaine manière, c'est l'opposé complet de l'exemple de la partie I.

L'exemple classique de tableau de contrôle VB 6 est le même qui est implémenté dans le code VB .NET. Ici dans le code VB 6 (ceci est tiré de Mezick & Hillier, Guide d'examen de certification Visual Basic 6, p 206 - légèrement modifié, car l'exemple du livre entraîne des contrôles invisibles):

Dim MyTextBox comme VB.TextBox. IntNumber statique comme entier. intNumber = intNumber + 1. Définissez MyTextBox = _. Moi. Contrôles. Ajouter ("VB.TextBox", _. "Text" & intNumber) MyTextBox. Text = MyTextBox. Nom. MyTextBox. Visible = Vrai. MyTextBox. Gauche = _. (intNumber - 1) * 1200

Mais comme Microsoft (et moi) sommes d'accord, les tableaux de contrôle VB 6 ne sont pas possibles dans VB.NET. Donc, le mieux que vous puissiez faire est de dupliquer la fonctionnalité. Mon article a dupliqué la fonctionnalité trouvée dans l'exemple Mezick & Hillier. Le code de la Commission d'études fait double emploi avec la possibilité de définir des propriétés et des méthodes d'appel.

Donc, l'essentiel est que cela dépend vraiment de ce que vous voulez faire. VB.NET n'a pas le tout enveloppé dans le langage - Pourtant - mais en fin de compte, il est beaucoup plus flexible.

Prise en charge des baies de contrôle par John Fannon

John a écrit: J'avais besoin de tableaux de contrôle parce que je voulais mettre un simple tableau de nombres sur un formulaire au moment de l'exécution. Je ne voulais pas avoir la nausée de les placer tous individuellement et je voulais utiliser VB.NET. Microsoft offre une solution très détaillée à un problème simple, mais c'est un très gros marteau pour casser un très petit écrou. Après quelques expérimentations, j'ai finalement trouvé une solution. Voici comment je l'ai fait.

L'exemple À propos de Visual Basic ci-dessus montre comment vous pouvez créer un TextBox sur un formulaire en créant une instance de l'objet, en définissant des propriétés et en l'ajoutant à la collection Controls qui fait partie du formulaire objet.

Dim txtDataShow comme nouveau TextBox
txtDataShow. Hauteur = 19
txtDataShow. Largeur = 80
txtDataShow. Emplacement = Nouveau point (X, Y)
Moi. Contrôles. Ajouter (txtDataShow)
Bien que la solution Microsoft crée une classe, j'ai pensé qu'il serait possible d'envelopper tout cela dans un sous-programme à la place. Chaque fois que vous appelez ce sous-programme, vous créez une nouvelle instance de la zone de texte sur le formulaire. Voici le code complet:

Formule de classe publique1
Hérite du système. Les fenêtres. Formes. Forme

#Region "Code généré par Windows Form Designer"

Private Sub BtnStart_Click (_
Expéditeur ByVal en tant que système. Objet, _
ByVal e As System. EventArgs) _
Gère btnStart. Cliquez sur

Dim I as Integer
Dim sData As String
Pour I = 1 à 5
sData = CStr (I)
Appelez AddDataShow (sData, I)
Prochain
End Sub
Sub AddDataShow (_
ByVal sText As String, _
ByVal I en tant que nombre entier)

Dim txtDataShow comme nouveau TextBox
Dim UserLft, UserTop As Integer
Dim X, Y comme entier
UserLft = 20
UserTop = 20
txtDataShow. Hauteur = 19
txtDataShow. Largeur = 25
txtDataShow. TextAlign = _
Alignement horizontal. Centre
txtDataShow. BorderStyle = _
Style de bordure. FixedSingle
txtDataShow. Text = sText
X = UserLft
Y = UserTop + (I - 1) * txtDataShow. la taille
txtDataShow. Emplacement = Nouveau point (X, Y)
Moi. Contrôles. Ajouter (txtDataShow)
End Sub
Fin de classe
Très bon point, John. C'est certainement beaucoup plus simple que le code Microsoft... alors je me demande pourquoi ils ont insisté pour le faire de cette façon?

Pour commencer notre enquête, essayons de changer l'une des affectations de propriété dans le code. Changeons

txtDataShow. Hauteur = 19
à

txtDataShow. Hauteur = 100
juste pour s'assurer qu'il y a une différence notable.

Lorsque nous exécutons à nouveau le code, nous obtenons... Whaaaat??? ... la même chose. Aucun changement du tout. En fait, vous pouvez afficher la valeur avec une instruction comme MsgBox (txtDataShow. Hauteur) et vous obtenez toujours 20 comme valeur de la propriété, peu importe ce que vous lui affectez. Pourquoi cela se produit-il?

La réponse est que nous ne dérivons pas notre propre classe pour créer les objets, nous ajoutons simplement des choses à une autre classe, nous devons donc suivre les règles de l'autre classe. Et ces règles stipulent que vous ne pouvez pas modifier la propriété Height. (Eh bien... vous pouvez. Si vous modifiez la propriété Multiline sur True, vous pouvez modifier la hauteur.)

Pourquoi VB.NET va de l'avant et exécute le code sans même gémir qu'il pourrait y avoir quelque chose de mal alors qu'en fait, il ignore totalement votre déclaration est un tout autre reproche. Je pourrais suggérer au moins un avertissement dans la compilation, cependant. (Allusion! Allusion! Allusion! Microsoft écoute-t-il?)

L'exemple de la partie I hérite d'une autre classe, ce qui rend les propriétés disponibles pour le code de la classe héritée. La modification de la propriété Height à 100 dans cet exemple nous donne les résultats attendus. (Encore... une clause de non-responsabilité: lorsqu'une nouvelle instance d'un grand composant Label est créée, elle recouvre l'ancienne. Pour voir réellement les nouveaux composants Label, vous devez ajouter la méthode appelée aLabel. Mettre au premier plan().)

Cet exemple simple montre que, bien que nous puissions simplement ajouter des objets à une autre classe (et parfois c'est la bonne chose à faire), la programmation du contrôle sur les objets nécessite que nous les dérivions dans une classe et la manière la plus organisée (oserais-je dire, "la manière .NET" ??) est de créer des propriétés et des méthodes dans la nouvelle classe dérivée pour changer des choses. John n'était pas convaincu au début. Il a dit que sa nouvelle approche convenait à son objectif même s'il y avait des limites à ne pas être "COO" (Correctly Object Oriented). Plus récemment, cependant, John a écrit:

"... après avoir écrit un ensemble de 5 zones de texte à l'exécution, je voulais mettre à jour les données dans une partie ultérieure du programme - mais rien n'a changé - les données d'origine étaient toujours là.

J'ai trouvé que je pouvais contourner le problème en écrivant du code pour enlever les anciennes boîtes et les remettre à nouveau avec de nouvelles données. Une meilleure façon de le faire serait de m'utiliser. Rafraîchir. Mais ce problème a attiré mon attention sur la nécessité de fournir une méthode pour soustraire les zones de texte et les ajouter. "

Le code de John a utilisé une variable globale pour garder une trace du nombre de contrôles ajoutés au formulaire, donc une méthode ...

Sous-formulaire privé1_Load (_
Expéditeur ByVal en tant que système. Objet, _
ByVal e As System. EventArgs) _
Gère MyBase. Charge
CntlCnt0 = Moi. Contrôles. Compter
End Sub

Ensuite, le "dernier" contrôle pourrait être supprimé ...

N = moi. Contrôles. Nombre - 1
Moi. Contrôles. RemoveAt (N)
John a noté que "c'est peut-être un peu maladroit".

C'est la façon dont Microsoft garde la trace des objets dans COM ET dans leur exemple de code "laid" ci-dessus.

Je suis maintenant revenu au problème de la création dynamique de contrôles sur un formulaire au moment de l'exécution et j'ai relu les articles "What Happened to Control Arrays".

J'ai créé les classes et je peux maintenant placer les contrôles sur le formulaire comme je le souhaite.

John a montré comment contrôler le placement des contrôles dans une zone de groupe en utilisant les nouvelles classes qu'il a commencé à utiliser. Peut-être que Microsoft avait raison dans leur solution "laide" après tout!

instagram story viewer