Récupérer les datas entré dans des textbox créées dynamiquement.
PierLeca
Messages postés5Date d'inscriptiondimanche 2 décembre 2018StatutMembreDernière intervention19 décembre 2018
-
Modifié le 2 déc. 2018 à 13:37
PierLeca
Messages postés5Date d'inscriptiondimanche 2 décembre 2018StatutMembreDernière intervention19 décembre 2018
-
19 déc. 2018 à 11:07
Bonjour,
Mon problème est le suivant, je créé par l'appui sur un bouton, un certain nbre de textbox, dont le nbre dépend d'une valeur entrée dans une textbox existante.
ces textbox s'affichent sur 2 colonnes, la première colonne est rempli automatiquement par une formule lié a la valeur entrée dans la textbox existante, et la deuxième colonne devrait être rempli manuellement mais .....Pour ecrire le code désignant la variable des textbox, il me faut les noms de celles ci, et comme elles seront créees que quand j'appuierais sur le bouton.... les textbox n'existent pas encore !!!!, Le code ci dessous crée 2 colonnes de textbox et des labels en dessous, mais si je peux entrer des valeurs dans la deuxième colonne, je ne sais pas comment les recupérer en code !
Imports System.Data
Imports System.Data.OleDb
Imports System.ComponentModel
Imports System.Globalization
Imports System.Threading
Imports Microsoft.VisualBasic.PowerPacks
Imports Microsoft
Public Class Form1
Dim coef As Integer
Dim nbr As Single = 0
Dim coeff As Single
Dim vol As Double
Dim x As Double
Dim y As Double
Public Property KeyChar As Char
Public Property MyTextBox_v As Object
Dim v As Single
Dim result As Single
Private ReadOnly MyShape As Control
Public Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
coef = TextBox1.Text
coef = coef / 0.5
coeff = coef * 2
vol = 0.5
'****************** Textbox colonne 1 *************************
For i As Integer = 1 To coef
Dim MyTextBox As New TextBox
Dim loc_x As Single = 50
Dim loc_y As Single
MyTextBox.Name = "xxx"
MyTextBox.Size = New System.Drawing.Size(65, 22)
MyTextBox.Location = New System.Drawing.Point(loc_x, loc_y + 30)
MyTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center
Me.Controls.Add(MyTextBox)
MyTextBox.Text = vol
loc_y = loc_y + 30
vol = vol + 0.5
x = MyTextBox.Text
Next
' ***************** textbox colonne 2 ***********************
For q As Integer = 1 To coef
Dim a As Integer = 1
Dim TextBox(a) As TextBox
Dim MyTextBox As New TextBox
Dim loc_x As Single = 150
Dim loc_y As Single
Dim ax As Single
MyTextBox.Size = New System.Drawing.Size(65, 22)
MyTextBox.Location = New System.Drawing.Point(loc_x, loc_y + 30)
MyTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center
MyTextBox.Text = ax
loc_y = loc_y + 30
MyTextBox.AcceptsReturn = True
MyTextBox.Name = (a)
Controls.Add(MyTextBox)
' ax = ax + 1
a = a + 1
' result = TextBox(a).Text
Next
' ********************** Label axe des X ****************
For i As Integer = 1 To coef
Dim Mylabel As New Label
Dim lab_x As Single
Dim lab_y As Single = 250
Mylabel.AutoSize = True
Mylabel.Location = New System.Drawing.Point(lab_x + 20, lab_y)
Mylabel.Name = "xxx"
Mylabel.Text = "o"
lab_x = lab_x + 30
Me.Controls.Add(Mylabel)
Mylabel.AutoSize = True
Mylabel.Location = New System.Drawing.Point(lab_x + 20, lab_y + 10)
Mylabel.Name = "xxxx"
Mylabel.Text = vol
vol = vol - 0.5
lab_x = lab_x + 20
Me.Controls.Add(Mylabel)
Next
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Application.Exit()
End Sub
End Class
EDIT : Ajout des balises de code (la coloration syntaxique). Explications disponibles ici : ICI
Merci d'y penser dans tes prochains messages.
A voir également:
Récupérer les datas entré dans des textbox créées dynamiquement.
Whismeril
Messages postés19040Date d'inscriptionmardi 11 mars 2003StatutContributeurDernière intervention 9 mai 2024656 2 déc. 2018 à 12:46
Bonjour
en attendant qu'un modérateur édite ton message pour rendre ton code lisible (voir ce tutoriel pour tes prochains messages), voici quelques conseils.
VB.Net est un un langage tout objet. Tout est en italique, il ne plait pas à tout le monde, mais le fait est que chaque ligne de code utilise des objets, et que même un simple chiffre tapé dans le code dispose de méthodes.
dim un as String = 1.ToString()
ça fonctionne.
Utiliser une classe métier avec 2 propriétés (dont l'une dépend de l'autre), bindées sur tes textbox résoudrait ton problème. Cependant, il faut:
se forcer à penser objet
concevoir le programme dès le début dans cet optique
Mais une fois le pli pris, c'est bien plus simple que la programmation séquentielle ou événementielle, telle que semble être ton code.
Si tu veux plus d'infos sur le sujet, regarde mon profil, j'ai fait 2 tutos sur le binding et un sur l'objet. Ce ne sont certainement pas les meilleurs du net, mais je les ai fait exprès pour C# et VB.Net.
Si tu ne peux pas revoir ton programme depuis le début, l'association de 2 Textbox est il le plus simple à gérer?
Tu pourrais utiliser:
un DataGridView
une ListBox à colonne
une ListView
ou encore écrire un userControle, composé lui de 2 textbox, dans lequel tu fais tes calculs. C'est ce contrôle que tu ajouterais dynamique (et en plus c'est une approche plus objet, puisque tu crées un objet graphique)
Whismeril
Messages postés19040Date d'inscriptionmardi 11 mars 2003StatutContributeurDernière intervention 9 mai 2024656 2 déc. 2018 à 21:06
Maintenant que NHenry a rendu ton code lisible, merci à lui.
Pourquoi faire 3 boucles pour placer tes textBox, une seule suffit?
Un truc du genre
For i As Integer = 1 To coef
Dim textBoxGauche As New TextBox
textBoxGauche.Name = String.Format{"Gauche{0:00}", i)
Dim textBoxDroit As New TextBox
textBoxGauche.Name = String.Format{"Droit{0:00}", i)
Dim leLabel As New Label
textBoxGauche.Name = String.Format{"Label{0:00}", i)
'ect
Ainsi en une seule boucle tu génères tes 3 contrôles, tu leur donne un nom clair est unique.
Ici
For q As Integer = 1 To coef
Dim a As Integer = 1
Dim TextBox(a) As TextBox
Ton tableau ne sert à rien, il n'est pas réutilisé dans le for, et est réinitialisé à chaque boucle/
Tu gâches juste de la mémoire.
A quel moment veux tu que le textbox de gauche soit rempli:
à chaque frappe dans celui de droite?
quand on tape une touche spécifique (entrée par exemple) dans celui de droite?
quand le textbox de droite perd le focus?
à l'appui d'un bouton?
autre?
Par ce que la réponse dépend essentiellement de ça.
PierLeca
Messages postés5Date d'inscriptiondimanche 2 décembre 2018StatutMembreDernière intervention19 décembre 2018 18 déc. 2018 à 06:25
Merci pour vos réponses, en fin de compte j'ai trouvé, grâce à un ami,
dans une form1
Public Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
'on crée une liste de TB qui à ce stade est vide c'est juste un contenant
Public tblist As New List(Of TextBox)
Public imax As Byte 'quantité max de tb
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Remplissage de la liste avec des TB
imax = TextBox1.Text - 1
For i = 0 To imax
Dim tbtemp As New TextBox
'ici on peut personnaliser (taille...)
tblist.Add(tbtemp)
Next
' à la fin, on a Imax tb en réserves, prêts à être utilisés
' il reste à les ajouter sur la form
'Ajouts des TB sur la form
For i = 0 To imax
tblist(i).Location = New Point(20, 70 + i * 30)
Me.Controls.Add(tblist(i))
Next
'Voilà, les TB sont affichés, prêts pour la saisie
End Sub
'valide les saisies, et ouvre une deuxième form qui va lire le contenu des tb...
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Form2.Show()
End Sub
dans une form2
Public Class Form2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.Close()
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ListBox1.Items.Clear()
For i = 0 To Form1.imax
ListBox1.Items.Add(Form1.tblist(i).Text)
Next
End Sub
End Class
Un forum est animé par des bénévoles, si tu veux qu'ils aient envie de t'aider il faut leur faciliter la vie:
un code illisible -> on passe à la question d'un autres
un truc qu'on ne comprends, on lui demande, il répond pas-> tant pis pour lui
PierLeca
Messages postés5Date d'inscriptiondimanche 2 décembre 2018StatutMembreDernière intervention19 décembre 2018 18 déc. 2018 à 13:31
Bon, tout d'abord merci d'avoir bien voulu essayer de m'aider, et c'est vrai que je n'ai pas appliqué la procédure pour avoir un code correct, est ce que j'ai une excuse, j'aurai tendance à dire oui, je m'explique, car vous ne pouviez pas le deviner.
Pour mon boulot, je me trouve dans un trou perdu au fin fond de l'Afrique, sur l'ile de Pate "Pate island" au Kenya pour ceux qui connaisse, je suis déjà bien heureux d'avoir une connexion internet, même si celle çi est d'une lenteur .... escargotesque.
Quand j'ai posté mes deux messages, la fenêtre du site était presque en mode programmation,c.a.d. aucune balise, aucun graphique, que du texte, et bien sur rien sur la façon d'entrer du code, sinon je l'aurai fait, mais comme je disais vous ne pouviez pas le savoir.
Par contre j'aurai un petit reproche à faire, ne le prenez pas mal, ça n'a rien de personnel ça ne vise personne, et ça concerne bcp de forum de programmation.
Si on est ici et si on pose des questions "basiques" c'est que l'on ne sait pas !, alors j'aurai bien répondu à ta question, Whismeril, mais si j'ai fais comme ça c'est parce que je ne savais pas faire autrement !, pour les autres questions, j'avais expliqué dans la première message, mais dans l'élan de ma question je n'ai pas du être clair, j'avais un prof en école qui disait "quand on n'a pas compris c'est que ça a été mal expliqué". j'ai donc mal expliqué.
Pour essayer être plus clair, le programme est destiné à faire une courbe avec en X des volumes et en Y des pressions, je sais ce qu'on va me dire,
"on ne fait pas de courbe en vb.net !"
mais j'en ai fais, ca marche mais ça mouline pas mal !!!!, alors si vous pouvez me dire avec quoi faire des courbes ?
Sinon, une fois le test physique terminé, je connais le volume pompé, à quel débit (constant) et j'ai noté les pressions a chaque palier de débit.
par exemple, j'ai pompé 5 bbls à 0.5 bpm, j'ai noté la pression tous les 0.5 bpm.
Donc dans mon programme je rentre le volume pompé (5 bbls), et je voulais que le programme me crée deux colonnes de textbox, chaque colonne ayant le nbre de textbox correspondant au volume divisé par le débit (5/0.5=10) et qu'il remplisse la colonne de gauche automatiquement avec l'incrémentation des débits, 0.5, 1, 1.5, etc. afin qu'il ne me reste plus qu'a entrer les pressions dans les textbox de doites en face des vol. correspondant.
j'arrivais donc à créer mes deux colonnes et celle de gauche se remplissait toute seule, mais je ne savais pas comment récupérer les valeurs entrée dans les textbox de droite (pression), puisque elles étaient crées quand j'entrais le volume max, et donc je ne pouvais pas leur attribuer une fonction dans la mesure ou elles n'existaient pas lors de l'écriture du programme.
je suis ingé (c'est pas une référence !) mais pas en informatique loin de la !!!
j'espère avoir été plus clair, et si vous pouviez, vous les vrais informaticiens/programmateurs/etc vous mettre au niveau des pauvres béotiens que nous sommes, on apprécieris vraiment.
Dans tous les cas merci, et si mon code complet intéresse quelqu'un ?, je veux bien le partager ( création de courbe inclus).
Whismeril
Messages postés19040Date d'inscriptionmardi 11 mars 2003StatutContributeurDernière intervention 9 mai 2024656 Modifié le 18 déc. 2018 à 19:43
Bonsoir,
Je ne suis pas informaticien professionnel, je suis autodidacte, et j'ai appris entre autre grâce à ce forum.
Je ne suis même pas ingénieur.
Comme quoi tout est possible.
Dès mon premier message, j'ai énoncé des principes de base de .Net, supposant justement que tu étais plutôt débutant.
Mes questions n'étaient peut-être pas claires pour toi, mais j'essayais de mieux cerner ton besoin et la meilleure solution à appliquer.
Par exemple
Donc dans mon programme je rentre le volume pompé (5 bbls), et je voulais que le programme me crée deux colonnes de textbox, chaque colonne ayant le nbre de textbox correspondant au volume divisé par le débit (5/0.5=10) et qu'il remplisse la colonne de gauche automatiquement avec l'incrémentation des débits, 0.5, 1, 1.5, etc. afin qu'il ne me reste plus qu'a entrer les pressions dans les textbox de doites en face des vol. correspondant.
là je n'avais pas du tout compris ça, je pensais que la formule à appliquer était pour une ligne et pas pour une colonne.
Tu n'aurais dit que tu ne comprennais mes questions, j'aurais explicité mieux.
J'entends que ta connexion internet est problématique, mais elle ne t'a pas empêchée de faire une grande réponse aujourd'hui.
Avec cette explication plus détaillée, je confirme ce que je pensais au début:
tu n'as pas utilisé la meilleure solution, elle n'est pas la plus efficace et elle est sans doute la plus complexe à mettre en oeuvre.
Ensuite, dans le principe, un contrôle tel que le textbox n'est pas là pour en faire des calculs.
Il est là pour afficher ou recevoir du texte, et on ne fait pas de calcul avec du texte, on les fait avec des nombres.
En plus l'association de 2 textbox pour créer une collection relève de l'usine à gaz, il y a des contrôles déjà prévus pour faire ça:
le datagridview
la listbox
la listview
pour les 3 principaux.
Dans mon premier message, je t'ai conseillé de coder objet alors je te montre.
Soit l'objet Mesure, cet objet a 2 propriétés Volume et Pression. Il représente littéralement un point de mesure qui associe une pression à un volume.
1 ere version la plus simple
Public Class Mesure
Public Property Volume() As Double
Public Property Pression() As Double
End Class
Comme tu le voies écrire un objet peut être très simple.
Bon, pour facilité le dialogue avec l'affichage (binding, j'y reviens plus tard), on va appliquer un "modèle" qui signale quand une des propriétés change de valeur, ce modèle est une interface INotyfiPropertyChanged et le signal est un évèvement
Imports System.ComponentModel
Public Class Mesure
Implements INotifyPropertyChanged
Private leVolume As Double
''' <summary>
''' Le volume mesuré
''' </summary>
Public Property Volume() As Double
Get
Return leVolume
End Get
Set(ByVal value As Double)
If leVolume <> value Then
leVolume = value
GenerePropertyChanged("Volume")
End If
End Set
End Property
Private laPression As Double
''' <summary>
''' La Pression mesurée
''' </summary>
Public Property Pression() As Double
Get
Return laPression
End Get
Set(ByVal value As Double)
If laPression <> value Then
laPression = value
GenerePropertyChanged("Pression")
End If
End Set
End Property
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private Sub GenerePropertyChanged(ByVal Propriete As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(Propriete))
End Sub
End Class
C'est un peu plus compliqué. Le principe est que pour chaque propriété, il existe une variable interne. Quand on veut affecter une valeur à la propriété, cette valeur est comparée à la variable interne, si c'est différent, on met à jour et on déclenche l'évènement.
On va écrire un autre objet, SessionMesure, qui à 3 propriétés:
le volume final,
le débit,
une collection de Mesures,
et une méthode privée qui va initialiser la collection de mesures
Imports System.ComponentModel
Public Class SessionMesure
Implements INotifyPropertyChanged
Private leDebit As Double = 0
''' <summary>
''' Le débit de la session
''' </summary>
Public Property Debit() As Double
Get
Return leDebit
End Get
Set(ByVal value As Double)
If leDebit <> value Then
leDebit = value
GenerePropertyChanged("Debit")
Init()
End If
End Set
End Property
Private leVolumeFinal As Double = 0
''' <summary>
''' Le volume final de la session
''' </summary>
Public Property VolumeFinal() As Double
Get
Return leVolumeFinal
End Get
Set(ByVal value As Double)
If leVolumeFinal <> value Then
leVolumeFinal = value
GenerePropertyChanged("VolumeFinal")
Init()
End If
End Set
End Property
Private lesMesures As List(Of Mesure)
''' <summary>
''' Les mesures de la session
''' </summary>
Public Property Mesures() As List(Of Mesure)
Get
Return lesMesures
End Get
Set(ByVal value As List(Of Mesure))
If lesMesures IsNot value Then
lesMesures = value
GenerePropertyChanged("Mesures")
End If
End Set
End Property
''' <summary>
''' Initialisation de la session de mesure
''' </summary>
Private Sub Init()
If leDebit > 0 AndAlso leVolumeFinal > 0 Then
Dim resultat As New List(Of Mesure)()
For i As Double = leDebit To leVolumeFinal Step leDebit
resultat.Add(New Mesure With {.Volume = i})
Next i
Mesures = resultat
End If
End Sub
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private Sub GenerePropertyChanged(ByVal Propriete As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(Propriete))
End Sub
End Class
Enfin, dans ton interface il y a 2 textbox (txtDebit et txtVolumeFinal) et un datagriview (dgwMesures) et juste ce code.
Imports System.ComponentModel
Public Class frmPierLeca
Private session As New SessionMesure()
Private Sub frmPierLeca_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AddHandler session.PropertyChanged, AddressOf Session_PropertyChanged 'on s'abonne à l'évènement qui signale un changement de valeur de d'une propriété
End Sub
Private Sub Session_PropertyChanged(ByVal sender As Object, ByVal e As PropertyChangedEventArgs)
If (e.PropertyName = "Mesures") Then 'si la propriété est la collection de mesures, on la "binde" sur le datagridview
dgwMesures.DataSource = Nothing
dgwMesures.DataSource = session.Mesures
End If
End Sub
Private Sub txtDebit_TextChanged(sender As Object, e As EventArgs) Handles txtDebit.TextChanged
If (String.IsNullOrEmpty(txtDebit.Text)) Then Return
session.Debit = CDbl(txtDebit.Text)
End Sub
Private Sub txtVolumeFinal_TextChanged(sender As Object, e As EventArgs) Handles txtVolumeFinal.TextChanged
If (String.IsNullOrEmpty(txtVolumeFinal.Text)) Then Return
session.VolumeFinal = CDbl(txtVolumeFinal.Text)
End Sub
End Class
J'ai fait le plus basique, à chaque changement dans un textBox on converti en double et on transmet à la SessionMesure.
Quand la collection est crée, on la binde (liaison de données où t'as rien à faire) sur le datagridview.
Je n'ai pas géré si l'utilisateur ne tape pas un nombre ou le mauvais symbole décimal (chez moi c'est la virgule)
Résultat
Donc là, on a 2 objets "métier" qui modélisent ce que tu fais pour de vrai dans ton métier.
Les calculs sont faits avec des nombres.
L'interface ne sert qu'à afficher ou transmettre les valeurs.
Le binding sur le datagriview crée tout seul les colonnes, affiche les lignes est mettra à jour les items de la collection quand tu saisiras quelque chose (grâce à INotifyPropertyChanged).
Et à la fin tu as directement une collection de 2 nombres à fournir au contrôle Chart.
PierLeca
Messages postés5Date d'inscriptiondimanche 2 décembre 2018StatutMembreDernière intervention19 décembre 2018 19 déc. 2018 à 05:40
merci de ta réponse, je vais essayer des que j'ai 5 mn, pour ma connexion internet, elle n'est pas constante, et pour le texte, ca va a peu près, envoyer du texte c'est bon, recevoir autre chose que du texte est problématique.
Par contre, je ne fais pas de calcul avec les textbox !?, je ne m'en sert que pour entrer des datas parfois pour en afficher, quoique j'utilise de plus en plus les labels pour l'affichage des resultats.
Il arrive que je mette des calculs dans une textox, de façon a ce que quand la valeur de la textbox change, ça appelle une autre form ou autre.
Raisonner en objet, c'est une grande nouveauté pour moi, il va falloir que je m'adapte !! et que je comprenne, d'ailleurs ton code je risque de revenir te poser des questions dessus.
quand aux courbes, je l'ai fais, enfin pas vraiment une courbe, une suite de lab0le "x" ayant des coordonnées adéquates. le pbs vient du fait que je lui fais dessiner les axes et le quadrillage avec des lineshape, et la ca rame un peu.
avec tout ça j'ose plus mettre le code (qui marche) car j'imagine que je vais faire avec des attaques cardiaques aux lecteurs .... :)
Whismeril
Messages postés19040Date d'inscriptionmardi 11 mars 2003StatutContributeurDernière intervention 9 mai 2024656 19 déc. 2018 à 07:15
Ok je me suis mal exprimé, tu ne fais pas de calcul dans les textbox mais avec, ici par exemple
tu fais bien un calcul directement avec le texte contenu dans le textbox, tu ne prends même pas la peine de préciser au compilateur s'il doit en faire un Integer, un double, ou une chèvre.
Et quand on laisse faire le compilateur il ne fais pas toujours ce qu'on pensait.
Active Option Strict dans les options du projet et cette ligne deviendra une erreur,
PierLeca
Messages postés5Date d'inscriptiondimanche 2 décembre 2018StatutMembreDernière intervention19 décembre 2018 19 déc. 2018 à 11:07
je n'avais pas mis tout le code
Dim coef As Integer
Dim nbr As Single = 0
Dim coeff As Single
Public vol As Double
Dim vol1 As Double
Dim x As Double
Dim y As Double
Dim v As Single
'Dim lab_y As Single = 330
'on crée une liste de TB qui à ce stade est vide c'est juste un contenant
Public tblist As New List(Of TextBox)
Public imax As Byte 'quantité max de tb
j'ai déclaré la variable imax sinon il aurait couiné !
et comme je l'ai dit je suis un débutant occasionnel.