Buenas tardes.
Necesito llenar 20 TextBox desde una tabla en MySQL en mas de una form.
Entonces hize una funcion, pero no se si sea la mejor forma de hacerlo.
Sub EscribirTextBox(ByVal fForm As Form, ByVal consulta As String)
Dim objeto As Object
Try
command = New MySqlCommand(consulta, con)
reader = command.ExecuteReader
If reader.Read Then
For Each objeto In fForm.Controls
If TypeOf objeto Is TextBox Then
CType(objeto, TextBox).Text = reader(CType(objeto, TextBox).Name.Substring(3))
End If
End If
Next
Else
MsgBox("Los datos no existen")
End If
reader.Close()
Catch ex As Exception
MsgBox("Error al escribir." + vbLf + ex.ToString)
End Try
End Sub
Por lo que he revisado no es recomendable usar Objet.
Yo le haría algunos cambios significativos. Prueba así:
<DebuggerStepThrough>
Friend Shared Sub PopulateTextBoxValues(ByVal controlCollection As Control.ControlCollection,
ByVal query As String, ByVal connection As MySqlConnection)
Dim owner As Control = controlCollection.Owner
Try
Using command As New MySqlCommand(query, connection),
reader As MySqlDataReader = command.ExecuteReader()
' Do While (reader.Read())
' ...
' Loop
If (reader.Read()) Then
For Each tb As TextBox In controlCollection.OfType(Of TextBox)
Dim value As String = reader.GetString(tb.Name.Substring(3))
tb.Text = value
Next tb
Else
MessageBox.Show(owner, "Los datos no existen.", owner.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End If
End Using
Catch ex As Exception
Dim errorString As String = String.Format("Error al escribir. {0}", ex.Message)
MessageBox.Show(owner, errorString, owner.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
O de forma asincrónica si lo prefieres:
<DebuggerStepThrough>
Friend Shared Async Sub PopulateTextBoxValuesAsync(ByVal controlCollection As Control.ControlCollection,
ByVal query As String, ByVal connection As MySqlConnection)
Dim owner As Control = controlCollection.Owner
owner.Invoke(Sub(ctrl As Control) ctrl.Enabled = False)
Try
Using command As New MySqlCommand(query, connection),
reader As DbDataReader = Await command.ExecuteReaderAsync()
' reader As MySqlDataReader = DirectCast(Await command.ExecuteReaderAsync(), MySqlDataReader)
' Do While Await (reader.ReadAsync())
' ...
' Loop
If Await (reader.ReadAsync()) Then
Dim lock As New Object()
SyncLock lock ' Safe thread synchronization.
For Each tb As TextBox In controlCollection.OfType(Of TextBox)
Dim value As String = CStr(reader(tb.Name.Substring(3)))
' If MySqlDataReader cast:
' Dim value As String = Await reader.GetFieldValueAsync(Of String)(Integer, Nothing)
tb.BeginInvoke(Sub(x As TextBox) x.Text = value)
Next tb
End SyncLock
Else
MessageBox.Show(owner, "Los datos no existen.", owner.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End If
End Using
Catch ex As Exception
Dim errorString As String = String.Format("Error al escribir. {0}", ex.Message)
MessageBox.Show(owner, errorString, owner.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
Finally
owner.Invoke(Sub(ctrl As Control) ctrl.Enabled = True)
End Try
End Sub
Por si no resulta evidente: a ambos métodos le pasarías la referencia del contenedor de controles, Form.Controls, en lugar de una referencia del Form.
PD: no he probado los códigos, los escribí al vuelo. En realidad no uso MySQL para nada, así que son códigos escritos/basados en pura intuición, en teoría deberían funcionar correctamente suponiendo que quieras que hagan lo mismo que el código original que compartiste (por si acaso dejé escrito y comentado un búcle Do-While que puedes adaptar).
Saludos
Bueno, olvidas lo más importante y es que dices que quieres escribir en más de un formulario (que se ve que contienen controles textbox del mismo nombre?)...
No voy a entrar demasiado en señalar en que no es la forma más óptima... creo que si varios textbox aparecen por igual en varios formularios, podrías crear un contenedor (control de usuario), que puedas poner a cada uno de los formularios. Esto haría innecesario recorrer la colección de controles de cada formulario, ese contenedor ya tendría esos controles...
...bueno, a lo que veníamos...
Cada formulario que lo precise, declara una coleccion, de nombre idéntico (por ejemplo txtBoxes as collection) en cada formulario...
Luego (desde donde se vaya a usar), creas una colección y metes en ella cada formulario que interese (esos que contiene copia de dichos textbox y que deben ser actualizados).
La llamada a la función (seguramente desde un botón) sería mñás o menos así...
dim colFrm = nueva coleccion
with colFrm
'si form1.txtBoxes.count>0) then
' esto no debe ser necesario si en efecto como dices todos tienen textbox del mismo nombre...
.Add(form1)
'end if
.Add(form7)
.Add(frmCuentas)
.Add(form12)
.Add(me) ' siendo el caso que este botón esté en este formulario...
end with
call ActualizarEstosForms(colFrm, query, conex, ...)
' activar-mostrar el form que prefieras, por ejemplo
colFrm.Item(0).show ' .BringToFront .Activate, .Visible=True . enable=true etc... según sea el caso estén cargados o no, visibles o no, etc...
Esto es rentable, porque la búsqueda de dichos controles solo debería hacerse una vez cuando se carga el proyecto (y si no hay cambios dinámicos de controles textbox, claro), y no cada vez que se requiera cargar datos desde la BD.
private sub Main
LlenarColTextboxFromformx(form1)
LlenarColTextboxFromformx(form7)
LlenarColTextboxFromformx(frmCuentas)
LlenarColTextboxFromformx(form12)
LlenarColTextboxFromformx(frmPrincipal)
end sub
declara en diseño en cada formulario una coleccion txtBoxes...
funcion LlenarColTextboxFromformx( byref f as form) as short
por cada ctrl in f.ControlCollection
si ctrl.getType.name = "TextBox" luego ' otra forma de preguntar...
f.txtBoxes.add(ctrl)
end if
siguiente
devolver f.txtBoxes.Count
fin funcion
Luego creas una función que reciba como parámetro esa colección de formularios...
que se recorre y de los cuales se van tomando sus textbox...
funcion ActualizarEstosForms( colF as coleccion, ....)
dim f as form
dim tb as textbox
dim txt as string
try
consulta a la BD
por cada f en colF
por cada tb en subf.txtBoxes
try
txt = Getstring(....)
tb.Text = txt
catch
messagebox.show "Nombre del textbox no hallado, corrige el nombre" ' el error más probable, para el caso...
end try
siguiente
siguiente
catch ex as exception
mesagebox.show (ex.message) ' algún problema con la base de datos...
finally
end try
fin funcion