Me.DesignMode o ¿podrías por favor no interpretar el código mientras sólo estoy diseñando? (Gracias)
VisualBasic.NET (supongo que todo el VisualStudio.NET) tiene un comportamiento que me desquicia. Bueno, tiene unos cuantos, pero hoy hablo de uno en particular. Imaginemos un caso muy habitual en el que tengo un control de usuario y un formulario. Primero diseño el control de usuario y luego en el formulario lo insertaré.
El control de usuario (ctrlDGV.vb) lo creo simplemente añadiéndole un objeto de tipo DataGridView (dgvMain) y el siguiente código:
'----------------------------------------------------------------
' Private attribute.
'----------------------------------------------------------------
Private DBC As DatabaseConnection
'----------------------------------------------------------------
' Setter for DBC.
'----------------------------------------------------------------
Public Sub LoadDBC(ByVal DBC As DatabaseConnection)
Me.DBC = DBC
End Sub
'----------------------------------------------------------------
' Event Me.Load.
'----------------------------------------------------------------
Private Sub ctrlDGV_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
Dim DT As DataTable
DT = Me.DBC.GetDataTable("SELECT field FROM table")
Me.dgvMain.DataSource = DT
End Sub
End Class
El objeto Me.DBC es un objeto de conexión a datos cuyo método GetDataTable me devolverá un DataTable a partir de una cadena SQL (es todo lo que necesitamos saber aceca de él en lo que a este post se refiere). La manera de crear ese objeto Me.DBC no atañe a este control, porque asumimos que siempre nos preocuparemos de llamar al método LoadDBC (y por tanto asegurarnos que Me.DBC ha dejado de ser Nothing) antes de que se dispare el evento Me.Load, así que no habrá problemas.
¿No habrá problemas? Sí, sí que los habrá... Los habrá simplemente cuando intentemos insertar este control en un formulario en vista diseño. En ese momento obtendremos el siguiente error...

...y no nos dejará insertarlo. ¿Por qué? Pues porque el código en el evento Me.Load se está interpretando y descubre que Me.DBC es todavía Nothing... No entiendo por qué narices tiene que interpretar código en tiempo de diseño, la verdad. Y lo curioso del caso es que si comentamos el código del evento Me.Load entonces nos deja insertar dicho control en un formulario sin problemas. Y si después volvemos a descomentar el código, aunque no podremos ver el formulario en modo diseño porque nos volverá a dar el error, sí que podremos ejecutar la aplicación y funcionará correctamente (si llamamos al método LoadDBC antes de que se lance el evento Me.Load, insisto). Y es normal que funcione porque el flujo es correcto en tiempo de ejecución...
El caso es que para solucionar este problema tenemos dos posibilidades. La primera es actuar a lo bestia y meterlo todo dentro de un Try-Catch y muerto el perro se acabó la rabia:
' Event Me.Load.
'----------------------------------------------------------------
Private Sub ctrlDGV_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
Try
Dim DT As DataTable
DT = Me.DBC.GetDataTable("SELECT field FROM table")
Me.dgvMain.DataSource = DT
Catch ex As Exception
'On error no nothing, it's just for design time.
End Try
End Sub
El segundo es ser un poco más sutil y hacer uso de la propiedad DesignMode del propio control para decirle algo así:
' Event Me.Load.
'----------------------------------------------------------------
Private Sub ctrlDGV_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
If Not Me.DesignMode Then
Dim DT As DataTable
DT = Me.DBC.GetDataTable("SELECT field FROM table")
Me.dgvMain.DataSource = DT
End If
End Sub
Es decir, si no estás en modo diseño ejecútame este código (si estás en modo diseño no hagas nada). Me parece algo surrealista, sinceramente. Para mí lo normal sería... si estás en modo diseño, no hagas nada, ni te mires el código, ni olerlo, dejámelo a mí... Y como mucho que la propiedad Me.DesignMode sirviera para lo contrario: para explícitamente solicitarle que hiciera una determinada cosa incluso en tiempo de diseño.
Pues hasta que descubrí esto... ufffff...
Tags: .NET, designmode, visual basic
Febrero 2nd, 2009 at 00:30
Pues sí, es bastante estúpido.
Además, sólo pensar que ese "if" se va a ejecutar en cualquier caso, me pone los pelos de punta.