Un gridview que contenga en sí mismo todo lo necesario para la visualización de la base de datos, a saber: una conexión, una sentencia sql, un orden, y un Result, de forma que no necesite ser alimentado en cada formulario y que pueda ser manejada como objeto.
Para ello tengo esta nueva clase que llamo, por ejemplo, "migrid"
'' gambas class file
INHERITS GridView
PUBLIC consulta AS String
PUBLIC orden AS String
PUBLIC clave AS Integer
PUBLIC rsDatos AS Result
PUBLIC hconn AS conexion
PUBLIC hcon AS connection
'En creación recibimos todo lo necesario
PUBLIC PROCEDURE _new(elsql AS String, elorden AS String, lacolclave AS Integer, laconec AS Connection, elcontenedor AS Object)
ME.consulta = elsql
ME.orden = elorden
ME.clave = lacolclave
ME.hcon = laconec
ME.width = elcontenedor.width - 50
ME.Height = elcontenedor.height - 60
ME.Header = 3
ME.Resizable = TRUE
ME.ScrollBar = 3
ME.visible = TRUE
refrescar() 'efectuamos la consulta y rellenamos el griview
END
PUBLIC FUNCTION refrescar() AS Boolean
DIM lret AS Boolean
DIM oldtag AS NEW Variant[]
ME.consulta = If(InStr(LCase(ME.consulta), "select"), ME.consulta, "select * from " & ME.consulta)
ME.consulta = If(ME.orden, ME.consulta & " order by " & ME.orden, ME.consulta)
TRY ME.rsDatos = ME.hcon.Exec(ME.consulta) 'la forma de conectar es provisional, pero funciona de momento
IF ERROR THEN
TRY ME.hcon.Open
IF ERROR THEN
TRY ME.hcon.Close
TRY ME.hcon.Open
IF ERROR THEN
Message("Imposible conectar con la base de datos")
RETURN FALSE
ENDIF
ENDIF
TRY ME.rsDatos = ME.hcon.Edit(ME.consulta)
IF ERROR THEN
Message("Imposible efectuar la consulta")
RETURN FALSE
ENDIF
ENDIF
lret = ME.formatear() 'Creamos las columnas, los títulos, los anchos, etc.
RETURN lret
END
PUBLIC FUNCTION formatear() AS Boolean
DIM hTable AS Table
DIM hField AS ResultField
DIM sField AS String
DIM iInd AS Integer
DIM iLen, ileng, n, i AS Integer
DIM lret AS Boolean
INC Application.Busy
lret = TRUE
IF NOT ME.rsDatos THEN
DEC Application.Busy
RETURN lret
ENDIF
ME.Rows.Count = 0
ME.Columns.Count = ME.rsDatos.Fields.Count
FOR EACH hField IN ME.rsDatos.Fields
WITH hField
SUPER.Columns[iInd].Text = .Name
IF .Type <> 9 THEN
iLeng = .Length
ELSE
iLeng = Len(ME.rsDatos[.Name])
IF ileng > 0 THEN
n = (.Length / 3) - ileng
n = n / 2
ileng = Int(ileng + n)
ELSE
ileng = .Length
ENDIF
ENDIF
TRY SUPER.Columns[iInd].Width = ME.anchoportipo(.Type, iLeng, .Name)
IF ERROR THEN
Message(Error.Text)
ENDIF
END WITH
INC iInd
NEXT
' ODBC devuelve mal el total de registros
IF ME.rsDatos.Count = -1 THEN
SUPER.Rows.Count = SUPER.rowcount
ELSE
SUPER.Rows.Count = ME.rsDatos.Count
ENDIF
FINALLY
DEC Application.Busy
RETURN lret
CATCH
Message.Error("Imposible ejectuar la solicitud. Error: " & "\n\n" & DConv(Error.Text))
lret = FALSE
END
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Este es el evento que nunca se ejecuta y no sé dónde colocar
PUBLIC SUB Data(Row AS Integer, Column AS Integer)
ME.rellenar(Row, Column)
END
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PUBLIC SUB rellenar(Row AS Integer, Column AS Integer)
'tipico evento data de sincronización entre la tabla y el gridview
ME.rsDatos.MoveTo(Row)
ME[row, column].Text = Str(ME.rsDatos[ME.Columns[Column].Text])
IF (Row MOD 2) == 0 THEN
ME.Data.Background = Color.White
ELSE
ME.Data.Background = color.RGB(162, 209, 236)
ENDIF
ME.Data.Foreground = Color.black
END
PUBLIC FUNCTION anchoportipo(iType AS Integer, iLength AS Integer, sTitle AS String) AS Integer
'función pillada por ahí, pendiente de mejoras...
DIM iWidth AS Integer
SELECT CASE iType
CASE gb.Boolean
iWidth = SUPER.Font.Width(Str(FALSE)) + 32
CASE gb.Integer
' iWidth = hCtrl.Font.Width("1234567890") + 16
iWidth = SUPER.Font.Width("123456") + 16
CASE gb.Long
iWidth = SUPER.Font.Width("12345678901234567890") + 16
CASE gb.Float
' iWidth = hCtrl.Font.Width(CStr(Pi) & "E+999") + 16
iWidth = SUPER.Font.Width("12345678") + 16
CASE gb.Date
iWidth = SUPER.Font.Width(Str(Now)) + 16
CASE gb.String
IF iLength = 0 THEN iLength = 255
iLength = Min(32, iLength)
iWidth = SUPER.Font.Width("X") * iLength + 16
END SELECT
iWidth = Max(iWidth, SUPER.Font.Width(sTitle) + 8)
RETURN iWidth
END
PUBLIC FUNCTION rowcount() AS Integer
DIM rows AS Integer
rows = 0
DO
ME.rsDatos.MoveTo(rows)
INC rows
LOOP
CATCH
RETURN rows
END
PUBLIC SUB ordenar(Column AS Integer)
' para el evento column_click del gridview
DIM old_orden AS String
DIM n AS Integer
DIM new_orden AS String
INC Application.Busy
old_orden = ME.orden
new_orden = ME.columns[Column].Title
n = InStr(new_orden, ".")
IF n = 1 THEN
new_orden = "`" & Left(new_orden, n - 1) & "`.`" & Right(new_orden, - n) & "`"
ELSE
new_orden = "`" & new_orden & "`"
ENDIF
IF old_orden = new_orden
new_orden &= " DESC"
ENDIF
ME.orden = new_orden
ME.refrescar()
DEC Application.Busy
END
Luego creamos un formulario y le asignamos el siguiente código:
PUBLIC elgrid AS migrid
PUBLIC conec AS connection
PUBLIC SUB form_Open()
'también se podría hacer primero elgrid y luego alimentar las propiedades de la conexion... pero de momento así está
conec = NEW connection
conec.Host = "localhost"
conec.Type = "mysql"
conec.Name = "mitabla"
conec.User = "miusuario"
conec.Password = "mipassword"
'parametros: consulta,orden,columna clave,contenedor,creador
elgrid = NEW migrid("select *from mitabla", "nombre", 1, conec, ME, ME) 'Se repite dos veces el ME, una como contenedor y otra como creador de la clase
'poco elegante que hay que depurar... cuando funcione, claro.
END
PUBLIC SUB elgrid_Data(Row AS Integer, Column AS Integer) 'no funciona. He probado a llamarla Data a secas pero tampoco...
elgrid.rellenar(Row, Column)
END
PUBLIC SUB elgrid_ColumnClick(Column AS Integer)
elgrid.ordenar(Column)
END
Con esto teóricamente debería crearse el gridview, que se crea, con las columnas, que se crean, y sus datos que NO se crean por falta de evento Data...
¿Alguna idea? Me lleva loco el tema....
Suerte