Agregar eventos en tiempo de ejecución (addHandler)

Quiero mostrarles varias cosas con este ejemplo… pero la principal es como agregar eventos a un grupo de controles en tiempo de ejecución en visual basic .net.

Para el ejemplo necesitaremos un formulario con muchos controles textBox’s (no importa como se llamen). Puedes hacer algo parecido a lo que hice yo.

Cada vez que en el diseñador de visual studio le damos doble clic a un control se crea una sub rutina que será la encargada de manejar ese evento. En el caso de un cuadro de texto el evento por defecto es TextChanged y el diseñador de visual studio creará una subrutina llamada TextBox1_TextChanged pero en realidad el nombre no es importante, podríamos cambiarlo y nada pasaría. Lo importante es lo que está al final de la linea: ” Handles TextBox1.TextChanged”. Esto indica que esta rutina “manejará” el evento TextBox1.TextChanged.

Nosotros podemos asignar estos “manejadores” en tiempo de ejecución y, como en el presente ejemplo, podemos hacerlo utilizando la misma función para varios controles.

La sintaxis para gregar un manejador es:

AddHandler Objeto.Evento, AddressOf MiRutina

y para quitar un manejador:

RemoveHandler Objeto.Evento, AddressOf MiRutina

Veramos ahora el ejemplo en cuestion: en este ejemplo lo que aremos es agregar dos eventos a cada control textBox que tengamos en el formulario. Estos eventos serán GotFocus (que ocurre cuando el control toma foco) y lostFocus (que ocurre cuando el control pierde el foco). Cuando el control tiene el foco queremos que cambie su color de fondo, en este caso, a un amarillo. Y cuando lo pierde que regrese a su color normal.
Lo primero que aremos es agregar esas dos rutinas.

Private Sub conFoco(ByVal sender As Object, ByVal e As System.EventArgs)
    DirectCast(sender, TextBox).BackColor = Color.Yellow
End Sub

Private Sub sinFoco(ByVal sender As Object, ByVal e As System.EventArgs)
    DirectCast(sender, TextBox).BackColor = Color.White
End Sub

Listo, ya tenemos las dos rutinas, pero… nadie las llama aún. Para eso necesitamos agregar a cada control textBox del formulario un manejador que llame a estasd funciones.

En el evento Load del formulario agregamos el siguiente código:

For Each c As Object In Me.Controls
    If c.GetType Is GetType(TextBox) Then
        AddHandler DirectCast(c, TextBox).GotFocus, AddressOf conFoco
        AddHandler DirectCast(c, TextBox).LostFocus, AddressOf sinFoco
    End If
Next

Y listo, podemos probar el programa y no necesitamos nada más. Todos los textBox cambiarán su color de fondo al tomar el foco. No importa cuantos sean ni como se llamen.

en la imagen siguiente se ve el formulario en funcionamiento:

Creo que vale la pena explicar un poco el último código.
El For each recorre todos los



36 Responses to “Agregar eventos en tiempo de ejecución (addHandler)”

  1. Información Bitacoras.com…

    Valora en Bitacoras.com: Quiero mostrarles varias cosas con este ejemplo? pero la principal es como agregar eventos a un grupo de controles en tiempo de ejecución en visual basic .net. Para el ejemplo necesitaremos un formulario con muchos controles ….

  2. Jose Antonio dice:

    ¡Gracias! Codigo limpio, sencillo y funcional. Eres un fenomeno. Yo usaba los arrays de controles en VB6 para estas cosas (como las echo de menos…), pero con este truquillo queda elegantemente solucionado.

  3. Eduardo Hernandez Saenz dice:

    Gracias por este excelente aporte, Yo he desarrollado en VB6 hace 8 años y no habia encontrado la manera de hacer en .Net lo que hacia en VB6 con los Array de Controles, como escribir un solo Evento para todos los TexBox de un Formulario e identificar cada uno por en Index. Con tu aporte supero esta gan dificultad. GRACIAS

  4. fernando dice:

    Hola, muy buena la explicacion. El addHandler me parece una herramienta interesante; pero tengo una duda al respecto. Yo lo utilizo en asp.net y funciona muy bien, le agrego eventos a los links que genero dinamicamente; pero solo funciona si el addHandler esta en el Load. ¿Hay alguna forma de que funcione no estando en el Load?
    Gracias por todo

  5. Jose dice:

    súper bueno este código ahorra muchas lineas, y tiempo.

  6. Jose dice:

    Se puede hacer algo similar pero para validar el KeyPress con solo números, etc, pero de alguna forma identificando cada textbox para sabe a quien aplicarle el formato o cual debe ser de solo números, texto etc. espero haberme hecho entender.

  7. facundo dice:

    Hola, me gusta tu pagina y admiro tu dedicacion en los post. Actualmente estoy estudiando en la universidad y ayuda bastante.

    Saludos!

  8. Shocksue dice:

    Hola excelente codigo, lo estoy aplicando pero para otro control y con otro evento, y sucede que cuando cuando le digo:
    AddHandler miObjeto.evento, AddressOf miRutina
    me dice que el metodo “mirutina” no tiene la misma firma que el delegado.
    En tu ejemplo tu no le envias parametros en el delegado y te funciona, que puede estar pasando en mi caso ?
    De antemano gracias por tu ayuda..

    • Eliseo dice:

      Es cierto, no le envío parámetros porque no hay que enviarle nada (se los enviará el control que dispare el evento), pero si hay que definirlos en el procedimiento que llamará. Por ejemplo: Private Sub MiRutina(ByVal sender As Object, ByVal e As System.EventArgs).

      Suerte

  9. PreguntadorVB dice:

    Hola, este es un buen ejemplo de utilizacion de AddHandler con controles ya añadidos al formulario.

    Es por eso que quiero aportar mi granito de arena añadiendo un código para agregar eventos a controles creados en tiempo de ejecución.

    Un saludo.

    ————————————————

    Private Sub PulsadoDobleClick(ByVal sender As Object, ByVal e As System.EventArgs)
    MsgBox(“Has pulsado Doble Click”)
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim MiCajaDeTexto As New TextBox()
    MiCajaDeTexto.Name = “CajaDeTexto”
    Me.Controls.Add(MiCajaDeTexto)
    AddHandler Me.Controls(MiCajaDeTexto.Name).DoubleClick, AddressOf Me.PulsadoDobleClick
    End Sub

  10. Fernando dice:

    Gracias por tu ayuda, Me sacaste de apuros. Vengo de VB6 y es muy diferente, leí por ahi que Microsoft pretende incluir de nuevo los arrays de controles en sus nuevas versiones de VB.NET de la misma forma que se manejaban en VB6. Eso nos facilitaria la vida a los que venimos del viejo VB6.

  11. Alejandro Contreras dice:

    Excelente, yo tan solo agregaría un comentario sobre la posibilidad de asignar una función que tenga parámetros.

  12. Wilden dice:

    Excelente rutina, de gran ayuda para los que aun migramos de vb6 a .net, Gracias
    ‘** Uso la propiedad readonly para editar los textbox en un determinado Groupbox **’

    Ejemplo en mi proyecto:

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    ‘ Busca en un GroupBox los textbox
    For Each c As Control In Me.grpDatosPasajero.Controls

    If c.GetType Is GetType(TextBox) Then

    AddHandler DirectCast(c, TextBox).Enter, AddressOf conFoco
    AddHandler DirectCast(c, TextBox).Leave, AddressOf sinFoco

    End If

    Next

    End Sub

    ‘ Rutinas
    Private Sub conFoco(ByVal sender As Object, ByVal e As System.EventArgs)

    If Not DirectCast(sender,TextBox).ReadOnly Then

    DirectCast(sender, TextBox).BackColor = Color.PaleGoldenrod
    End If

    End Sub

    Private Sub sinFoco(ByVal sender As Object, ByVal e As System.EventArgs)

    If Not DirectCast(sender,TextBox).ReadOnly Then
    DirectCast(sender, TextBox).BackColor = Color.White
    End If

    End Sub

    wav

  13. Mik vb dice:

    Exelentes codigos amigos tengo que admitirlo jejej. en hora buena garacias . saludos a todos

  14. Ale dice:

    Comparto este codigo que relize con la ayuda de sus notas, esto me ayudara acrear todos lo botones que necesite y mandar llamar una funcion con condiciones ligadas a el boton presionado, claro a partir de un solo evento

    Public Class Form1
    Dim lbls() As Button
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim loc As Integer = 25
    For m As Integer = 0 To 4
    ReDim Preserve lbls(m)
    lbls(m) = New Button
    With lbls(m)
    .Text = (“Boton ” & m)
    .Location = New Point(0, loc)
    .Size() = New System.Drawing.Size(75, 23)
    End With
    lbls(m).Name = m
    Me.Controls.Add(lbls(m))
    AddHandler Me.Controls(lbls(m).Name).Click, AddressOf Me.Click
    loc += 25
    Next
    End Sub

    Private Sub Click(ByVal sender As Object, ByVal e As System.EventArgs)
    Dim j As Button = sender
    MsgBox(“Presionaste el Boton ” & j.Name)
    End Sub
    End Class

    espero y les sirva de algo

  15. Julio Lopez dice:

    Quiero crear un tabpage y dentro de este un datagridview en tiempo de ejecucion, y q tambien agregue estos controles en tiempo de diseno, si alguien sabe como hacerlo, agradezco su ayuda.

  16. Julio Lopez dice:

    Quiero crear un tabpage y dentro de este un datagridview en tiempo de ejecución, y que tambien agregue estos controles a la pantalla de diseño en visual basic.net, si alguien sabe como hacerlo, agradezco su ayuda.

  17. pepelepu dice:

    Holas! a todos! lo que pasa es que aca le dan propiedad a todos los textbox con:
    For Each c As Object In Me.Controls
    pero si kiero dar excepciones a algunos controles como los hago…por ejemplo con un boton kiero llenar mi formulario con unos txtbox para notas de alumnos pero ya hay otros txtbox como por ejemplo codigo, nombre y apellidos luego kiero promediar las notas utlizo
    Dim Suma(n) As Double
    Dim c As Control
    For Each c In Me.Controls
    If TypeOf c Is TextBox Then
    Suma(Val(c.Tag)) += Val(c.Text)
    End If
    Next
    For Each c In Me.Controls
    Dim i As Integer
    If TypeOf c Is Label Then
    If c.Tag >= 0 Then
    If Val(c.Tag) = i Then
    c.Text = Suma(i) / Val(txtnn.Text)
    i += 1
    End If
    End If
    End If
    pero me toma todos los txtbox y el promedio sale mal

  18. mekano dice:

    pepelepu, intenta exluir asi :


    For Each c In Me.Controls
    select case c.Name
    ‘ Controles a excluir
    case “nameControl1″, “nameControl2″, “nameControl3″
    loop
    case else
    ‘ Controles que quiero controlar
    Suma(Val(c.Tag)) += Val(c.Text)
    end select
    next

  19. JR Motta dice:

    Saludos, muy interesante código.

    Tengo una consulta para ustedes, he elaborado un menustrip que lee los elementos desde una base de datos, no que no logro aun es asignar un handler o procedimiento de evento a cada control o elemento del menustrip recuperando los nombres del procedimiento de la bbdd tambien, alguna sugenrencia? yo utilice como base el ejemplo que pueden encontrar en el siguient url: http://www.dotnethelp.co.uk/es/vb/108413/menu_strip_vbnet
    gracias por las sugerencias

  20. Daniel dice:

    Me estaba volviendo loco al no poder disparar los eventos hasta que entre aquí y leí

    “En el evento Load del formulario agregamos el siguiente código:”

    Solo me faltaba eso, a veces me pierdo en cosas obvias, gracias xD

  21. Edgar dice:

    Acabo de empezar con los eventos y manejadores y creo que es algo complejo(para mi), pero que bueno que haya gente que aporte su conocimiento para nosotros los que principiamos… se te agradece Eliseo y a todos los que han incluido su granito de arena.

    Saludos!!

  22. Jesus dice:

    soy nuevo en esto y Me parece interesante y muy bueno tu ejemplo, como podria hacerlo publico y poderlo llamar desde cualquier formulario… gracias

  23. romina dice:

    oye una consulta no se si me puedes ayudar.
    tengo que hacer un programa que controle a un juego con las teclas de movimiento y me gustaria saber como asignarle las teclas a los botones que puse; arriba abajo,izquierda,derecha y cuando presione la tecla el boton haga la simulacion de presionado.

  24. Cesar dice:

    Estimado, una consulta, como le puedo pasar parametros a la funcion que le indico en el addessOf, la funcion tiene un parametro (ej. IDBOTON), y para cada boton que voy creando debo buscar en BD información con el IDBOTON.

    Muchas gracias por tu ayuda.

  25. poncianux dice:

    esto lo aprendí hace no mucho (1 dia) jejeje aunque pareciera tarea complicada es realmente sencillo, incluso llame la caracteristica de intervalo desde una SQLCE saludos!

  26. Luis dice:

    Hola, muy interesante, quisiera que pudieran decirme como aplicar ese codigo para agregar eventos en tiempo de ejecución, en C#.
    Gracias, tambien es para agregar el evento Click a los picturebox que he creado en tiempo de ejecución.
    Gracias

  27. Javier dice:

    Muy sencillo pero muy práctico. Muchas gracias

  28. Haider dice:

    Hola, excelente. Tengo una pregunta, este código funciona para los controles que están directamente colocados en el formulario. Pero como hacer para que funcione para los contenedores sin necesidad de colocar en el Load del formulario un código para cada contenedor?

    • Eliseo dice:

      puedes crear una funcion recursiva para que si el control tiene controles se vuelva a llamar.
      A continuación te dejo un ejemplo y quiero aclararte que no lo he probado por falta de tiempo, pero como quería contestarte aqui te lo dejo.
      Usalo como base para crear tu función. Suerte.

      Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
      recorrerContenedores(Me)
      End Sub

      Sub recorrerContenedores(ByVal c As Control)
      If c.Controls.Count > 0 Then
      recorrerContenedores(c)
      Else
      ‘agregar Handles
      End If
      End Sub

  29. Heber dice:

    Hola Estimado, queria saber si te falto una parte del documento porque al final, mientras estaba leyendo parece que ibas a explicar un poco el código y queda algo asi:

    Creo que vale la pena explicar un poco el último código.
    El For each recorre todos los …

    Falta algo? lo podrias completar si es asi? Gracias y te felicito por el aporte que haces a la comunidad VB

  30. Juan Carlos dice:

    hola estubo buenaso eso pero tengo un problema si te das cuenta tu proyecto funciona al cargar el form….bueno es mi problema yo no lo quiero asi yo kiero que al presionar mi boton agregar recien se empieze a funcionar lo del lost y got focus por cada textbox..porfa ayudame en eso sip reponde cuanto antes gracias…
    saludosss….

    • Eliseo dice:

      No necesariamente el addHandler debe estar en el Load… puedes ponerlo donde tu quieras. Ademas de esto puedes usar (si lo necesitas) la instrucción RemoveHandler para la asociación del evento al control.

  31. Mario dice:

    Wooow! Este ejemplo me ha sido de muchísima ayuda, te lo agradezco, de verdad. Mas claro creo que no se puede ^^ Saludos!!

Comentar