La clase EventArgs, o cómo obtener información del objeto emisor del evento

La clase EventArgs, o cómo obtener información del objeto emisor del evento

En los ejemplos sobre captura de eventos realizados hasta ahora con la clase Empleado, dentro de los procedimientos manipuladores de evento, no disponemos de acceso a los miembros del objeto que ha originado el evento.

El único modo de los vistos hasta ahora de conseguir tal acceso, es declarar el objeto en la zona de declaraciones del módulo y, en ese caso, al tener visibilidad sobre la variable del objeto en todos los procedimientos del módulo, sí podríamos manejar el objeto.

Sin embargo, ¿qué ocurre cuando instanciamos un objeto Empleado con ámbito local en Main( ), y asociamos sus manipuladores de evento con AddHandler?. Simplemente, que desde dichos procedimientos manipuladores de evento, no podemos obtener información del objeto Empleado para, por ejemplo, recuperar el valor de la propiedad Nombre.

Una solución simple, pero no eficaz, consistiría en pasar la/s propiedad/es como parámetro cuando lanzamos el evento, es decir, al llamar a RaiseEvent( ) en la clase Empleado. Ver Código fuente 346.

Public Class Empleado '....

RaiseEvent LimiteSueldo(Value,Me.Nombre) '.... End Class

Código fuente 346

© Grupo EIDOS 22. Delegación de código y eventos

Pero seguiríamos limitados, en el caso de que necesitáramos pasar cualquier otro tipo de información que no estuviera directamente relacionada con el objeto.

Para solucionar este problema, podemos utilizar la técnica empleada por la propia plataforma .NET en la retransmisión de eventos, y que explicamos a continuación.

La jerarquía de clases de .NET dispone de la clase EventArgs, diseñada para guardar la información adicional que pasamos a un procedimiento manipulador de evento.

Podemos crear una clase que herede de EventArgs, y adaptarla, en este caso, para que contenga la información adicional sobre un evento que se ha producido en la clase Empleado, de modo que cuando se ejecute su manipulador asociado, pasemos a dicho manipulador, como primer parámetro, el propio objeto Empleado, y como segundo, un objeto de nuestra clase EventArgs personalizada, con datos adicionales sobre el evento generado. Este es el esquema general de trabajo con los eventos en .NET.

Escribiremos por lo tanto la clase EmpleadoEventArgs, que hereda de EventArgs, y que servirá para que cuando a un objeto Empleado se le intente asignar un sueldo incorrecto, se almacene en ella dicho valor erróneo. Ver Código fuente 347.

' clase para guardar información sobre ' los eventos lanzados por la clase Empleado; ' esta clase en concreto, guardará el valor del sueldo ' erróneo que se ha intentado asignar a un empleado Public Class EmpleadoEventArgs

Inherits EventArgs

Private mdbSueldoIntentadoAsig As Double

Public Property SueldoIntentadoAsig() As Double Get SueldoIntentadoAsig = mdbSueldoIntentadoAsig End Get Set(ByVal Value As Double)

mdbSueldoIntentadoAsig = Value End Set End Property End Class

Código fuente 347

Seguidamente retocaremos el código de la clase Empleado, cambiando la declaración del evento LimiteSueldo, y la sección Set de su procedimiento Property Sueldo, tal y como se muestra en el Código fuente 348.

Public Class Empleado ' declaramos el evento LimiteSueldo, ' el primer parámetro será la instancia y objeto ' Empleado actualmente en ejecución; ' el segundo parámetro será un objeto EmpleadoEventArgs, ' con la información adicional del evento producido Public Event LimiteSueldo(ByVal sender As Empleado, _

ByVal e As EmpleadoEventArgs) '.... '....

Public Property Sueldo() As Double Get

Programación con Visual Basic .NET © Grupo EIDOS

Return mdbSueldo End Get Set(ByVal Value As Double)

' si el valor que intentamos asignar ' al sueldo supera el permitido... If Value > 1000 Then

' ...creamos un objeto EmpleadoEventArgs ' y le pasamos a sus propiedades la ' información sobre el evento; en este ' caso sólo pasamos el valor incorrecto ' que se intentó asignar a la propiedad Sueldo Dim loEvArgs As New EmpleadoEventArgs() loEvArgs.SueldoIntentadoAsig = Value

' después lanzamos el evento y le pasamos ' como parámetro el propio objeto Empleado actual ' y el objeto con la información del evento RaiseEvent LimiteSueldo(Me, loEvArgs)

Else ' si el sueldo es correcto, se asigna mdbSueldo = Value

End If End Set End Property '.... '....

End Class

Código fuente 348

Los nombres empleados en la declaración del evento de esta clase: sender, para designar al emisor del evento; y e, para designar los argumentos del evento, no son en absoluto obligatorios, pudiendo el lector utilizar los nombres que estime oportunos. El haber utilizado estas denominaciones se debe a seguir la misma convención que utiliza la plataforma. En los temas dedicados a formularios y controles Windows, el lector podrá comprobar que los procedimientos manipuladores de evento, usan estos mismos nombres.

Para terminar, escribimos en el módulo un procedimiento manipulador para el evento LimiteSueldo, y en Main( ) instanciamos un objeto Empleado, asociando el evento del objeto al manipulador de evento que acabamos de escribir. Ver el Código fuente 349.

Module Module1 Sub Main() ' declarar e instanciar un objeto Empleado Dim loEmpleado As Empleado loEmpleado = New Empleado()

' añadir un manipulador de evento para el evento LimiteSueldo AddHandler loEmpleado.LimiteSueldo, AddressOf SobreAsignacionSueldo

loEmpleado.Nombre = "ANA" loEmpleado.Sueldo = 5000 ' esto provoca el evento

Console.ReadLine() End Sub

' procedimiento manipulador del evento LimiteSueldo; ' del parámetro sender obtenemos el nombre del Empleado, ' del parámetro e obtenermos el importe incorrecto ' que intentábamos asignar al sueldo del empleado

© Grupo EIDOS 22. Delegación de código y eventos

Public Sub SobreAsignacionSueldo(ByVal sender As Empleado, _ ByVal e As EmpleadoEventArgs)

Console.WriteLine("Se intentó asignar al empleado {0}, el sueldo {1}" & _ ControlChars.CrLf & "¡ESTO ES INCORRECTO!", _ sender.Nombre, _ e.SueldoIntentadoAsig)

End Sub

End Module

Código fuente 349

Aunque este modo de trabajo suponga un esfuerzo adicional por nuestra parte en cuanto a que tengamos que escribir algo más de código, los eventos de nuestras clases tendrán una estructura de llamada más acorde con el resto de eventos de las clases pertenecientes a la plataforma.

Arrays