Portal    Foro    Buscar    FAQ    Registrarse    Conectarse


Publicar nuevo tema  Responder al tema 
Página 1 de 1
 
 
Mas Sobre GridView Heredado Y Su Evento Data
Autor Mensaje
Responder citando   Descargar mensaje  
Mensaje Mas Sobre GridView Heredado Y Su Evento Data 
 
Esto es lo que intento hacer:

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
 




===================
No podemos regresar
 
shordi - Ver perfil del usuarioEnviar mensaje privado 
Volver arribaPágina inferior
Responder citando   Descargar mensaje  
Mensaje Re: Mas Sobre GridView Heredado Y Su Evento Data 
 
Shordi, creo que ya te lo habían dicho, pero no sé si lo probaste: para capturar el evento deberías crear un objeto observer en el constructor (_new)

Creo que algo así debería funcionar:

PRIVATE  $hObserver AS Observer

...

PUBLIC PROCEDURE _New()
  $hObserver = NEW Observer(ME) AS "myGridView"
  ....
END

PUBLIC PROCEDURE myGridView_Data(Row AS Integer, Column AS Integer)
  ME.rellenar(Row, Column)
END
 


De todos modos creo que deberías ordenar un poco el código y seguir fielmente algunas pautas de POO:

  • Tu código no respeta el principio de encapsulamiento. Deberías cambiar las variables públicas por propiedades.
  • Veo que usas algunas abreviaturas para nombrar las variables. Si quieres que alguien más que tú mismo entienda tu código sin problemas, no deberías usar abreviaturas.
  • Aunque no lo analicé detenidamente me parece que posiblemente tu clase "migrid" no respete el principio de responsabilidad única (viene a ser lo mismo que con las funciones: deben hacer una única cosa). Deberías tener en cuenta que tu proyecto es un control que puede componerse de varias clases, no necesarimente de una sola. Encontrar cuáles deberían ser esas clases debe ser el primer paso.
  • Hay métodos que me parece no deberían ser públicos: esos también estarían rompiendo el encapsulamiento.

Un consejo Shordi, refactoriza antes de seguir, es decir, intenta hacer lo siguiente.

  • Crea un nuevo proyecto.
  • Escribe primero la interfaz de la clase (propiedades y nombres y argumentos de los métodos que los usuarios de tu control deberían ver) sin su implementación. Así podrás definir cómo quieres que tu control sea usado, sin preocuparte de cómo lo implementarás.
  • Crea un módulo para probar la clase (si ya sé que aún no hace nada, por eso es el momento justo para empezar a probarla). En ese módulo deberás empezar a escribir procedimientos que creen un objeto, establezcan sus propiedades y prueben sus métodos, siempre comparando si los resultados son iguales que los valores esperados.
  • Define las variables y métodos que usará internamente la clase (que deben ser privados), sin su implementación.
  • Analiza un poco el diseño de la/s clase/s, para ver si la interfaz que definiste es adecuada o si le faltan métodos públicos o propiedades.
  • Implementa primero las propiedades y métodos públicos en términos de variables y métodos privados. Es decir, si observas que un método público necesita, por ejemplo, calcular la longitud de una vaca adulta, pon una llamada a un método "PRIVATE FUNCTION getLongAdultCow() AS Float" que implementarás después (la primera implementación de "getLongAdultCow" debería ser algo como Return 2,07 para permitir que puedas ejecutar las pruebas de entrada nomás).
  • Del punto anterior puede surgir evidencia de que necesitas variables o métodos privados adicionales: defíne su interfaz pero no su implementación.
  • Cada vez que implementas un método o propiedad, escribe en un módulo algunas pruebas que podrían hacer fallar ese método o propiedad. Ejecuta el módulo de pruebas y corrige las fallas que vayan surgiendo.
  • Completa la implementación de cada método, ejecutando las pruebas luego de cada modificación importante para asegurarte que no introduces nuevos fallos.


Un proceso así es lo que generalmente se recomienda para lograr un buen diseño y una buena modularización. Es el proceso lo que ayuda a disminuir la cantidad de errores que uno comete; se mejora la comprensión sobre qué se debe hacer en cada momento al definir primero las interfaces y al escribir pruebas y ejecutarlas cada vez que se introducen modificaciones importantes.

Si quieres seguir mi consejo y necesitas ayuda para hacerlo no dudes en avisarme, en el proceso yo aprenderé mucho
 




===================
Cómo programar con Gambas

Speed Books: informática libre.
 
fabianfv - Ver perfil del usuarioEnviar mensaje privadoVisitar sitio web del usuario 
Volver arribaPágina inferior
Responder citando   Descargar mensaje  
Mensaje Re: Mas Sobre GridView Heredado Y Su Evento Data 
 
¿Ves como sí eres el interlocutor adecuado? jeje.
Mil gracias.
Efectivamente, ese código no es más que un primer intento de convertir un puñado de funciones que tenía agrupadas en un módulo, y que portaba de aplicación en aplicación prácticamente intactas, en un objeto.  Tiempo empleado en el análisis: 13 segundos (más o menos).
No podía emplearme más sin saber si era posible hacerlo (nunca he heredado un control gráfico) y ahí me estrellé.

Por otra parte no sabía que se podía declarar un observador vía código, que eso lo dijo Jesús y no me enteré de la copla, me temo.
Una respuesta orientadora como la tuya es lo que esperaba y te estoy super agradecido. Dame unos días para que le dé vueltas al tema y subiré lo que vaya consiguiendo, código o problemas. Posiblemente más de lo segundo que de lo primero... jejeje

Gracias otra vez. Este es el mejo foro del mundo mundial.

Suerte


Edito: otografía, ortografía...
 




===================
No podemos regresar
 
última edición por shordi el Miercoles, 11 Agosto 2010, 18:32; editado 2 veces 
shordi - Ver perfil del usuarioEnviar mensaje privado 
Volver arribaPágina inferior
Responder citando   Descargar mensaje  
Mensaje Re: Mas Sobre GridView Heredado Y Su Evento Data 
 
Hola Shordi, creo que en el hilo en que empezaste esta consulta, ya te dije lo que me paso a mi. La clase creada por mi no era gráfica pero lo de los observer debe de ser igual.
Por defecto un objeto es su propio observador. Yo uso los observer cuando quiero interceptar el funcionamiento de algunos controles (no todos) y responder a ciertos eventos de la misma forma para ese grupo.
Como todos queremos ahorrarnos código escrito, te vuelvo a decir que lo que haría sería, al instanciar tu grid personalizado declararlo con su propio observador.

DIM  arrtable AS String[5]
DIM elGrid AS miGrid

elGrid = NEW miGrid AS "observaMiGrid"

'Debería funcionar ahora en este Form desde el que instancias, el evento Data

PUBLIC SUB observaMiGrid_Data(Row AS Integer, Column AS Integer)

  'un array con los nombre de los campos aquí pon los tuyos y sácalo de aquí y ponlo en Form_Open()
  arrtable[0]="cod"
  arrtable[1]="fecha"
  arrtable[2]="concepto"
  arrtable[3]="cantidad"
  arrtable[4]="origen"

  ResultDeDatos.MoveTo(Row)
  TVultGastos.data.Text = Str(ResultDeDatos[arrtable[Column]])

END

Perdón por volver con lo mismo pero creo que lo fácil es mejor, no se

Antonio
 



 
ahtonio - Ver perfil del usuarioEnviar mensaje privado 
Volver arribaPágina inferior
Responder citando   Descargar mensaje  
Mensaje Re: Mas Sobre GridView Heredado Y Su Evento Data 
 
Disculpa ahtonio, atribuí más arriba tu respuestas en el otro hilo a Jesús.
En el otro como que no lo entendí. Ahora, juntando todas vuestras ayudas, como que lo entiendo.
Me pongo a probarlo (sin prisas, que es agosto...) y cuando tenga algo que contar ipsofactamente os lo comunico.
Gracias a todos.

Suerte
 




===================
No podemos regresar
 
shordi - Ver perfil del usuarioEnviar mensaje privado 
Volver arribaPágina inferior
Responder citando   Descargar mensaje  
Mensaje Re: Mas Sobre GridView Heredado Y Su Evento Data 
 
Hola Shordi, como te comente en privado, intento adjuntarte el fuente por si quieres probarlo y/o verlo.

gesper-0.0.4.tar.gz
Descripción:  
Descargar
Nombre del archivo: gesper-0.0.4.tar.gz
Tamaño: 44.53 KB
Descargado: 93 veces
gesper-0.0.4.tar.gz
Descripción:  
Descargar
Nombre del archivo: gesper-0.0.4.tar.gz
Tamaño: 44.53 KB
Descargado: 93 veces
gesper-0.0.4.tar.gz
Descripción:  
Descargar
Nombre del archivo: gesper-0.0.4.tar.gz
Tamaño: 44.53 KB
Descargado: 93 veces

 



 
ahtonio - Ver perfil del usuarioEnviar mensaje privado 
Volver arribaPágina inferior
Responder citando   Descargar mensaje  
Mensaje Re: Mas Sobre GridView Heredado Y Su Evento Data 
 
Recibido. Ya te cuento... y mil gracias.
 




===================
No podemos regresar
 
shordi - Ver perfil del usuarioEnviar mensaje privado 
Volver arribaPágina inferior
Mostrar mensajes anteriores:    
 
OcultarTemas parecidos
Tema Autor Foro Respuestas último mensaje
No hay nuevos mensajes Sobre Control Heredado De GridView (para F... shordi Controles/Librerías/Componentes 7 Martes, 10 Agosto 2010, 20:04 Ver último mensaje
shordi
No hay nuevos mensajes Problema Con El Evento Data De GridView. D... Shell General 15 Sabado, 22 Noviembre 2014, 00:21 Ver último mensaje
Shell
No hay nuevos mensajes Como Controlar El Evento Data De Gridview? vr_rv Bases de Datos 6 Jueves, 23 Junio 2016, 22:34 Ver último mensaje
jguardon
No hay nuevos mensajes Evento Data imagomundi Controles/Librerías/Componentes 2 Lunes, 06 Abril 2020, 02:04 Ver último mensaje
tincho
 

Publicar nuevo tema  Responder al tema  Página 1 de 1
 

Usuarios navegando en este tema: 0 registrados, 0 ocultos y 0 invitados
Usuarios registrados conectados: Ninguno


 
Lista de permisos
No puede crear mensajes
No puede responder temas
No puede editar sus mensajes
No puede borrar sus mensajes
No puede votar en encuestas
No puede adjuntar archivos
Puede descargar archivos
No puede publicar eventos en el calendario



  

 

cron