none
Como Asignar registros de bases de datos a un botón creado en tiempo de ejecución RRS feed

  • Pregunta

  • Muy buenas noches, tardes o días, mi consulta es si me pueden ayudar con un problema en cuestión que tengo, el problema es que al crear los botones en tiempo de ejecución y asignarle los valores mandados a leer a dichos botones, los botones cargados o creados (se crean en base a un conteo que hago primero),solo o todos me cargan el primer registro de la consulta y ese primer registro se los asigna a todos los botones creados, no como deberia de ser de un registro asignado a cada boton. este e el codigo en cuestion que uso:

     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''CONTEO DE FILAS'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            Dim Conteo As String = "SELECT NombreCategoria FROM Categoria where IdEmpresa=@IdEmpresa"
            Dim cmdConteo As New SqlCommand(Conteo, Cadena)
            cmdConteo.Parameters.AddWithValue("@IdEmpresa", 1)
            Cadena.Close()

            Dim Filas As Integer = 0
            Dim da As New SqlDataAdapter(cmdConteo)
            Dim dt As New DataTable
            da.Fill(dt)
            Filas = dt.Rows.Count
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''FIN DEL CONTEO DE FILAS''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            '   Using conn As New SqlConnection(My.Settings.CadenaCon)

            Dim I As Integer
            For I = 1 To Filas
                Dim b As New System.Windows.Forms.Button
                Dim query As String = "SELECT NombreCategoria FROM Categoria where IdEmpresa=@IdEmpresa"
                Dim cmd As New SqlCommand(query, Cadena)
                cmd.Parameters.AddWithValue("@IdEmpresa", 1)
                Cadena.Close()
                Cadena.Open()
                Dim Reader As SqlDataReader = cmd.ExecuteReader()
                Reader.Read()
                b.Text = Reader("NombreCategoria").ToString
                b.Height = FlowLayoutPanel1.Height / 7 - 3
                b.Width = 100
                b.Height = 70
                b.Visible = True
                b.BackColor = Color.Lavender
                b.TextAlign = ContentAlignment.MiddleCenter
                b.ForeColor = Color.Black
                b.Font = New Font(b.Font, FontStyle.Bold)
                b.Left = 10
                'b.Width = FlowLayoutPanel1.Width - 20
                'b.Top = (I - 1) * (b.Height + 3)
                FlowLayoutPanel1.Controls.Add(b)
                '''''Opcional, conectar el evento click:
                AddHandler b.Click, AddressOf boton1_click
                '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
                '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            Next I
    viernes, 23 de agosto de 2019 5:47

Todas las respuestas

  • Bueno, es lógico que todos tus botones muestren el mismo valor, porque todos los cargas con la misma consulta:

    Dim query As String = "SELECT NombreCategoria FROM Categoria where IdEmpresa=@IdEmpresa"
    ...
    cmd.Parameters.AddWithValue("@IdEmpresa", 1)

    Fíjate que siempre, en todas las iteraciones del bucle, pones 1 en el IdEmpresa, por lo que siempre en todos los botones estás mostrando el NombreCategoria de la empresa 1.

    Así que algo falla en la lógica del programa. Tehdrías que ir cambiando el parámetro para que a cada iteración se consulte un dato distinto..


    viernes, 23 de agosto de 2019 9:11
  • Bueno si algo esta faltando en la lógica en eso estamos de acuerdo, es uno porque ese es el identificador de la empresa en cuestión o la llave que me permite mostrar todos los productos de esa empresa y de echo solo esa empresa existe, el punto seria en la consulta pues crea un botón para cada producto, pero a todos los botones les asigna el primer producto de la consulta y la idea es que a cada boton un producto, para explicarme mejor ese id-empresa es un parámetro que toma de una variable puede ser 1, 2, 3, o 100, en este caso como ya se que la empresa tiene en numero 1 asignado por eso lo deje fijo, el que me determina el numero de botones es el conteo que hago al inicio y ese valor lo almaceno en la variable filas que ese es el que comparo en el ciclo for, EL PUNTO SERIA QUE EJECUTE LA CONSULTA Y ALMACENE EN CADA BOTON EL NOMBRE DE UN PRODUCTO.
    PARA SER MAS GRAFICOS LA TABLA EN CUESTION SERIA A SI:

    IdCategoria     NombreCategoria      IdEmpresa
    1                    Platos Fuertes               1
    2                    ComidaRapida               1
    3                    Refrescos                      1
    4                    Complementos               1


    QUISIERA QUE EN CADA BOTÓN ME CARGUE CADA NOMBRE DE CATEGORÍA, PERO EN TODOS LOS BOTONES ME ASIGNA EL NOMBRE DE LA PRIMERA CATEGORÍA.

    • Editado JaimeSalgado07 viernes, 23 de agosto de 2019 15:03
    • Propuesto como respuesta Pablo Rubio viernes, 23 de agosto de 2019 17:10
    viernes, 23 de agosto de 2019 14:50
  • Ah, claro, tal como lo tienes está bien que el parámetro sea un 1 para la empresa. El problema ahora es que no tienes NINGUNA OTRA COSA en la consulta que permita sacar los otros registros. Es decir, por cada botón (tal como lo tienes ahora) siempre vuelves a ejecutar LA MISMA consulta, y solo lees el primer registro devuelto por la consulta. Así que todos los registros muestran lo mismo. Fíjate que después de enviar la consulta, haces  Reader.Read() para tomar el primer registro y luego no vuelves a usar ese Reader para nada. En resumidas cuentas, tienes mal anidadas las sentencias. En lugar de hacer un bucle y luego dentro del bucle repetir a cada iteración la misma consulta, tendrías que hacer al contrario: primero enviar la consulta y luego hacer un bucle que recorra los resultados.

    Más o menos sería algo parecido a lo siguiente (pero está escrito de memoria y seguramente tendrá algún que otro error -- no lo copies literalmente, úsalo solo como inspiración para escribir tu propio código):

    Dim Conteo As String = "SELECT NombreCategoria FROM Categoria where IdEmpresa=@IdEmpresa"
    Dim cmdConteo As New SqlCommand(Conteo, Cadena)
    cmdConteo.Parameters.AddWithValue("@IdEmpresa", 1)
    Dim da As New SqlDataAdapter(cmdConteo)
    Dim dt As New DataTable()
    da.Fill(dt)
    For Each dr as DataRow In dt.Rows
        Dim b As New System.Windows.Forms.Button
        b.Text = dr("NombreCategoria").ToString()
        b.Height = FlowLayoutPanel1.Height / 7 - 3
        b.Width = 100
        b.Height = 70
        b.Visible = True
        b.BackColor = Color.Lavender
        b.TextAlign = ContentAlignment.MiddleCenter
        b.ForeColor = Color.Black
        b.Font = New Font(b.Font, FontStyle.Bold)
        b.Left = 10
        FlowLayoutPanel1.Controls.Add(b)
        AddHandler b.Click, AddressOf boton1_click
    Next

    Fíjate que te he simplificado unas cuantas cosas. Solo hacemos una única consulta a la BD, y eso ya trae las filas a una tabla que te da las dos cosas: el conteo y el contenido de las filas. No hace falta cerrar y abrir la conexión porque el método Fill ya detecta internamente si es necesario y lo hace de forma automática.


    viernes, 23 de agosto de 2019 16:46
  • jejejeje jejejejeje cuanta razón tienes no volvi a usar el read y en el código simplificado pues no se me ocurrió hacerlo en el mismo read mandando a leer las filas jejejejjejejeje CUANTA RAZÓN, Muchas gracias hermano eres un Crack. éxitos siempre.
    sábado, 24 de agosto de 2019 1:37
  • Ahora esto me genera una gran duda, asumo que tendría que hacer lo mismo para cargar los productos asignados a cada una de esas categorías en un evento clic, pero el parámetro seria el nombre de la categoría que es el que tengo por a si decirlo a mano en los botones creados en tiempo de ejecución, La PREGUNTA SERIA, COMO HAGO PARA ALMACENAR ESE NOMBRE EN UNA VARIABLE Y PONERLO COMO CONDICIÓN EN EL EVENTO CLIC DE LAS CATEGORÍAS PARA QUE ME CARGUE ÚNICAMENTE LOS PRODUCTOS ASIGNADOS A LA CATEGORIA QUE LE DE CLIC.
    domingo, 25 de agosto de 2019 6:13
  • Al evento Click le llega el parámetro "Sender" que representa el botón sobre el que hicieron click. Casteando Sender para convertirlo en Button puedes leer todas sus propiedades, entre ellas el Text que es donde tienes metido el nombre de categoría.

    Private Sub boton1_click(Sender As Object, e As EventArgs)
        Dim b as Button = CType(Sender, Button)
        Dim categoria as String = b.Text
        '....
    End Sub

    • Propuesto como respuesta Pablo Rubio miércoles, 28 de agosto de 2019 17:09
    domingo, 25 de agosto de 2019 10:45
  • Muchas Gracias Hermano. éxitos siempre
    domingo, 25 de agosto de 2019 23:52
  • Yo Abusando a estas alturas de tu conocimiento hermano, si no es mucha molestia tus respuestas la verdad son muy acertadas y bien eficientes por lo que e podido ver, Mi duda ahora es la siguiente, de la creación de las categorías al dar clic muestro los productos asignados a esa categoría en otros botones,(en la consulta para mostrar los botones jalo en la misma consulta otros datos como el id, código, Nombre que es el que muestro en el botón en la propiedad text, existencias, entre otros, el punto en cuestión es el siguiente, al dar clic en este caso sobre los Productos quisiera mostrar los otros valores Pero mostrarlos o almacenarlos en variables o algo por el estilo para poder ejecutar otros procesos, pero este e el caso que se me dificulta pues entiendo que cuando creo el boton producto le asigno la propiedad text al nombre y los otros valores digamos que quedan en el aire, como podre hacer para mostrar esos valores digamos en label o en cajas de texto pues ya digamos que los tengo en la consulta o habrá la necesidad de hacer otra consulta en base al nombre y la empresa ya cargados, pues esto consumiría un poco mas de recursos innecesariamente.

    de antemano muchas gracias por toda tu ayuda ya aportada.

    martes, 27 de agosto de 2019 2:07
  •  cuando creo el boton producto le asigno la propiedad text al nombre y los otros valores digamos que quedan en el aire

    Hay varias soluciones para guardar más valores en el botón. La primera es crear una clase hija de Button y meter ahí las propiedades que quieras para almacenar más valores. Después utilizas esa clase hija en lugar de Button al crear tus botones dinámicos. Si haces esto, acuérdate de almacenar esas nuevas propiedades en el ViewState, de lo contrario sus valores se pierden durante el postback.

    Otra alternativa es asignarle al button un ID conocido, y guardar tus datos asociados a ese ID. Por ejemplo, podrías usar un Dictionary(of string, miClase) y en el primer string metes el ID que le hayas asignado al botón en el momento de crearlo, y en miClase metes un objeto que hayas definido para guardar toda la información que desees asociarle al botón. Una vez más, recuerda salvar este dictionary en el ViewState (o el Session) para que no se pierda durante el postback.

    • Propuesto como respuesta Pablo Rubio miércoles, 28 de agosto de 2019 17:09
    martes, 27 de agosto de 2019 6:41