Llenar mas de un TextBox desde Base de Datos

Iniciado por SilverLycan68, 1 Junio 2018, 00:12 AM

0 Miembros y 1 Visitante están viendo este tema.

SilverLycan68

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.

Código (vbnet) [Seleccionar]

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.

Eleкtro

#1
Yo le haría algunos cambios significativos. Prueba así:

Código (vbnet) [Seleccionar]
<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:
Código (vbnet) [Seleccionar]
<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








Serapis

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