jueves, 13 de marzo de 2008

Parámetros mútiples desde un GridView

Ciertamente la programación es una actividad en donde la inspiración va de la mano de la experiencia. Y hay días en donde “te baja la idea del cielo” y encuentras otra forma nueva, por lo menos para ti, de hacer las cosas.

Siempre me habían parecido espantosas las cadenas de parámetros que se envían desde un GridView para editar una fila (siempre que no uses programación visual). Por ejemplo, si tengo un grid como el de la imagen, y quiero mandar información a la ventana de al lado según la fila seleccionada tengo que hacer una “guarrería” como esta:
<asp:ImageButton ID="imgbImageButton" runat="server" CausesValidation="false" 
CommandArgument='<%# Eval("idVehiculo") & "@" & eval("Empleado").toString%>'
Para después con un string.split, cargar cada uno de los argumentos en un array y enviarlo al método adecuado.
Protected Sub gvDatosTabla_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles gvDatosTabla.RowCommand
Dim parametro() As String = Split(e.CommandArgument, "@")
lblDatosDni.Text = parametro(0)
lblDatosEmpleado.Text = parametro(1)
tbDatosImporte.Text = parametro(2)
End Sub
A causa de la lógica de negocio, me veo obligado a que esta ya larguísima cadena se me multiplique por tres y comienzo a comerme el tarro de cómo mejorar simplificar el código.
Y pienso… si tuviera un identificador único en la tabla no habría mayor problema.
A lo cual le he añadido, en la clase que recupera la tabla, un método que le añade una columna en donde almaceno un valor numérico incremental que se inicia en 1.
Private Function idToTable(ByVal tabla As DataTable) As DataTable
Dim id As Integer = 1
tabla.Columns.Add("IdTabla", Type.GetType("System.Int32"))
For Each filas As DataRow In tabla.Rows
filas("IdTabla") = id
id += 1
Next
Return tabla
End Function
Teniendo ya un identificador único, cargo la tabla en una propiedad que almacena en el gridView y ya tengo persistencia.
Public Property tabla() As DataTable
Get
Return ViewState("tabla")
End Get
Set(ByVal value As DataTable)
ViewState("tabla") = value
End Set
End Property
Y ya puedo cargarlo en el dataView para hacer el bind del GridView, teniendo cuidado de además de las columnas que se deben mostrar, incluir una columna oculta con el identificador único.
<asp:BoundField Visible="false" DataField="IdTabla" />
Ahora cuando selecciono una fila para editar ya no tengo que pasar los datos vía CommandArgument, simplemente envío el identificador único que he añadido. Y encuentro todos los valores de esa fila haciendo un select en la tabla.
Protected Sub gvDatosTabla_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles gvDatosTabla.RowCommand
Dim filas() As DataRow = tabla.Select("IdTabla=" & e.CommandArgument)
If filas.Length > 0 Then
Dim fila As DataRow = filas(0)
lblDatosDni.Text = fila("dni") lblDatosEmpleado.Text = fila("empleado")
lblDatosImporte.Text = fila("Importe")
Else
mensaje("No existe la fila seleccionada")
End If
End Sub
Otra enorme ventaja que tengo al usar este método es que puedo acceder a los datos de la fila seleccionada por medio del nombre del campo/columna, en vez del críptico y horroroso sistema de índices del Array.