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.

2 comentarios:

Anónimo dijo...

Hooola

De hecho, como intentes borrar de un datatable que no tenga clave, te da error. No es exactamente lo que planteas, pero mira esto:

Private Sub AutoresPonerPK()
'// Es necesario que el DataTable tenga primary key
' para que pueda funcionar la opción de Eliminar
If Me.Datos.Tables(MiLISTAAUTORES) IsNot Nothing Then
Dim dcColPK(0) As DataColumn

dcColPK(0) = Me.Datos.Tables(MiLISTAAUTORES).Columns(Col_Id)

Me.Datos.Tables(MiLISTAAUTORES).PrimaryKey = dcColPK
End If
End Sub

Por cierto, como vea más código tuyo en el que creas un DataView para ordenar un grid, me presento en Rivas y te capo:

Private Sub AsignarDatosAutores()
If Me.Datos.Tables(MiLISTAAUTORES) IsNot Nothing Then
'// Es necesario que el DataTable tenga primary key
' para que se puedan eliminar filas
AutoresPonerPK()

With Me.Datos.Tables(MiLISTAAUTORES)
'// Aplicamos la ordenación por defecto
.DefaultView.Sort = String.Concat(Me.SortCampo, _
ctesLiterales.EspacioBlanco, _
Me.SortDir)
End With
'// Enlazar el grid al DataTable
With grdAutores
.DataSource = Me.Datos.Tables(MiLISTAAUTORES).DefaultView
.DataBind()

'.PageIndex = General.PrimerElemento
End With
Else
'// Enlazar el grid a la plantilla (DataTable) vacía
With grdAutores
.DataSource = GridAutoresVacio().DefaultView
.DataBind()
End With
End If
End Sub

Besillos on the morrillos (Julio)

Juan Quijano dijo...

Interesante lo del DefaultView de un datatable. Le voy a dedicar una entrada porque lo merece.

Gracias por lo de la clave...