Como manejan el refresh en un grid sin perder el registro actual

3,037 views
Skip to first unread message

Victor Espina

unread,
Jul 2, 2012, 1:10:25 PM7/2/12
to publice...@googlegroups.com
Amigos, este es un problema con el que he tenido que lidiar recurrentemente durante toda mi carrera y aun no he podido conseguir una solucion satisfactoria desde el punto de vista visual.

Yo trabajo mucho con listas para presentar datos y luego permitirle al usuario operar sobre esos datos seleccionando uno o mas filas en la lista y luego aplicando una accion sobre las filas seleccionadas.

Inicialmente usaba un control ListBox para esto, pero se complicaba mucho el tema de los titulos para las columnas y no soportaba el mostrar mas columnas de las que cabian en el ancho del control. Adicionalmente, el control no se volvia muy lento cuando la lista debia mostrar mas de unas pocas decenas de resultados.

Luego intente con el ListView, el cual me solucionaba el tema de las multiples columnas y los titulos de las mismas, y de paso me permitia aplicar coloreado dinamico a las filas, mostrar imagenes, etc.  Lamentablemente el ListView tampoco es apropiado cuando tienes que manejar varios centenares de filtas.

Finalmente termine creando un control personalizado basado en Grid, el cual se podia configurar en tiempo de ejecucion de manear muy sencilla, y que ya incluia funciones como busqueda incremental, autoordenamiento en las columnas, etc.

El problema que no he podido solucionar es como mantener seleccionado el registro actual en el grid luego de actualizar su contenido. Me explico mejor.  El usuario entra al editor y selecciona un filtro predefinido el cual determina los registros a mostrar en el grid.  Una vez mostrados los datos, el grid selecciona automaticamente la primera fila del mismo.  Luego digamos que el usuario selecciona el 5to registro y luego pulsa el boton de actualizar los datos en pantalla. Al hacer esto, el editor repite el query que devuelve los datos apropiados para el filtro actual y actualiza el grid en pantalla. El control, antes de actualizar, guarda el ID del registro que estaba seleccionado en el grid de modo que, luego de actualizarlo con los nuevos datos, hace un LOCATE para seleccionar de nuevo el registro que estaba activo antes del refresh.  Si ocurre que ese registro ya no existe (porque fue anulado o ya no forma parte de la vista actual), el grid selecciona automaticamente el primer registro.

Todo funciona bien, excepto por el hecho de que al hacer el LOCATE el grid desplaza las filas de modo que el registro seleccionado queda en la primera posicion, lo cual es confuso para el usuario pues no queda ninguna indicacion de que hay mas registros arriba de ese.

Como han hecho uds para manejar esta situacion?

Saludos

Victor Espina

Ricardo Pina

unread,
Jul 2, 2012, 1:36:32 PM7/2/12
to publice...@googlegroups.com
Hola Victor
 
Y si haces un GO TOP antes delo LOCATE ?
 
Saludos

--
            

                   Ricardo Pina

Desarrollo y Servicios Informáticos

                  Profesionales
               www.dsip.com.ar

 

 


Miguel Canchas

unread,
Jul 2, 2012, 1:43:21 PM7/2/12
to publice...@googlegroups.com

Efectivamente, con el GO TOP  se soluciona eso.

 

MK

             Imagen quitada por el remitente.

~WRD000.jpg

Luis Santander

unread,
Jul 2, 2012, 1:52:55 PM7/2/12
to publice...@googlegroups.com
Hola Victor

Ciertamente ese es un de los problemas que cada dia tenemos que afrontar con los grid,
bueno yo lo solucione de la siguiente manera (creo que de la manera mas arcaica pero me funciona).
Ya que tienes el conjunto de registros SELECIONADOS en el grid y lo que queremos es que se posicione
en el registro concurrente luego de hacer una operacion, guardo en una varible `variable1' el valor de la
llave de ordenamiento ejecuto la operacion sea y cuando regreso de esa operacion ejecuto una busqueda
de esa varible en el selec Tabla hasta que la encuentro (si no la encuetro ejecutamos otro algoritmo para pocisionarlo ates
o despues del registro selecionado, etc) y luego ejecuto un SETFOCUS sobre el grid.

atte.

ing. Luis J. Santander

saludos

Mario López

unread,
Jul 2, 2012, 1:53:39 PM7/2/12
to publice...@googlegroups.com
Víctor: 

lo que yo hago para tu caso es algo así como:

* guardar el ID del registro actual del grid en nID
* guardar el RelativeRow en nRows
* operar con los registros (llamando a una subpantalla, etc)
* actualizar el query que alimenta al grid según las modificaciones efectuadas en la subpantalla
* localizar nuevamente el registro con el nID guardado previamente
* hago un SKIP -nRows (o -nRows-1) para que me quede nuevamente en el mismo RelativeRow
* Refresh del Grid
* SKIP nRows para volver a posicionarme en el registro correcto

HTH
Mario
---

Victor Espina

unread,
Jul 2, 2012, 2:44:54 PM7/2/12
to publice...@googlegroups.com
Da igual; el efecto es el mismo.

Hugo C.

unread,
Jul 2, 2012, 4:41:59 PM7/2/12
to publice...@googlegroups.com
Intenta algo como esto ,

... << Consultar >> ...

SELECT MiCursor
LOCATE FOR ALLTRIM( MiCampo )  == ALLTRIM( lcCampo ) 
THISFORM.GRid1.RecordSource = "MiCursor"
IF FOUND()
    THISFORM.GRid1.DoScroll(2)
    THISFORM.GRid1.DoScroll(2)
ELSE
   GO TOP
ENDIF   
THISFORM.GRid1.SetFocus()

Saludos.

integral

unread,
Jul 2, 2012, 6:22:35 PM7/2/12
to publice...@googlegroups.com
Amigo Victor Espina :
 
Como posible solucion a su problema adjunto un pequeño codigo que utilizo en el GRID 
 
atte.,
 
Gabriel
(Lima - Perú)
Codigo.doc

Ricardo Pina

unread,
Jul 2, 2012, 7:42:02 PM7/2/12
to publice...@googlegroups.com
Hola Victor
 
Si todavía no encontraste la solución prueba con el siguiente orden en tu formulario
 
Thisform.Grid.Recordsource="Cursor" && o como enlaces los datos
go top in cursor
Thisform.Grid.Refresh
loca for condicion
 
Al hacer el refresh antes del locate creo que tendría que cambiar el comportamiento en la visualización del grid.
 
Saludos

Hugo C.

unread,
Jul 2, 2012, 8:16:48 PM7/2/12
to publice...@googlegroups.com

Este código de Ricardo Piña  funciona
en mi caso solo falta un Thisform.Grid.SetFocus
despues del Locate  for condicion.

Saludos 

Fox Learner *

unread,
Jul 2, 2012, 9:50:09 PM7/2/12
to publice...@googlegroups.com
Maestro Victor:

Segun entiendo el problema es este:

"Todo funciona bien, excepto por el hecho de que al hacer el LOCATE el grid desplaza las filas de modo que el registro seleccionado queda en la primera posicion, lo cual es confuso para el usuario pues no queda ninguna indicacion de que hay mas registros arriba de ese".

En mi caso hago lo que los compañeros dicen: go top. Pero obvio que esto nos lleva el puntero al primer registro del grid.

Segun entiendo, lo que ud. hace despues del go top es buscar otra vez el registro donde estaba posicionado el puntero antes de "actualizar" el grid. Es ahi donde el puntero se mueve al registro seleccionado provocando que en ocasiones el usuario "ya no vea" los registros que existen "arriba y antes de aquel donde esta posicionado".

Las posibles soluciones que veo son estas:

1. Una solución simple pero funcional: Si es un formulario tipo factura AGREGUE UNA COLUMNA PEQUEÑA AL LADO IZQUIERDO que indique el No. DE PARTIDA. 

De esa forma, el usuario sabe que esta en la partida 7 y que existen obviamente mas registros arriba (el1 al 6).

2. Copie la forma como lo solucione otro lenguaje. No lo sé, pero se me ocurre que pueda existir una propiedad o forma de "centrar los registros" pero de forma horizontal y dejar "la celda activa" del grid siempre "al centro". 

De esa forma, aunque el usuario se desplace por todos los registros del grid, podra ver el "registro o celda activa" siempre al centro de forma horizontal.

En su caso, maestro, ya que sabe .NET tal vez pueda "inventar" una clase que haga eso, de no existir la propiedad o método que "centre horizontalmente".

Se me ocurre lo siguiente para ello:

La clase debe "contar el numero total de registros" que se presentaran en la consulta (no estoy seguro si es reccount() o _tally.

Debe "dividir entre dos" el resultado de los registros y "obligar al VISUAL FOXPRO" a presentar los datos con el registro activo a "la mitad horizontalmente".

Disculpe mi ignorancia. Solo soy un novato en VISUAL FOXPRO.

Saludos!





Fox Learner

unread,
Jul 2, 2012, 10:01:26 PM7/2/12
to publice...@googlegroups.com
Ahora una duda relacionada con el tema: por qué usa locate?...

Según entiendo Locate solo sirve con campos NO indexados. Qué no debería usarse SEEK o la funcion SEEK().

Una vez que pregunté "medio mundo" me recomendó usar "indices" y rara vez no usarlos.

Otra vez me confunde el hecho de escuchar a un maestro de Fox usar LOCATE en un grid.

Umm..

Bueno, fuera de esa frustracion personal.. y volviendo a su tema.. Se me ocurre que descargue la version de prueba del sistema SAE de la compañia aspel y vea como ellos resolvieron el tema. Yo use el SAE algunos años tanto en su version DOS como en la Visual y no recuerdo haber tenido ese problema que menciona "como usuario".

De esa forma podrá ver como implementar esa característica en VISUAL FOX PRO

Saludos!

Daniel Sánchez

unread,
Jul 2, 2012, 11:14:45 PM7/2/12
to publice...@googlegroups.com
Lo que podrías hacer es capturar la posición de la fila en la grilla, con la propiedad relativerow, obviamente antes del requery, despues del requery haces la búsqueda con locate en tu tabla refrescas lo coloca al inicio de la lista de la grilla y luego como tienes la posición anterior haces uso del doscroll hasta colocarlo en la posición anterior, por ahi creo que vas ha obtener lo que deseas, haber prueba y nos comentas.

Saludos

--
Daniel Sánchez Escobar
Investigación y Desarrollo
Reset Software & Sistemas
Móvil +051-949398047
Trujillo - Perú

Victor Espina

unread,
Jul 3, 2012, 9:43:47 AM7/3/12
to publice...@googlegroups.com
Amigos gracias por sus multiples respuestas. El dia de hoy estare probando sus sugerencias a ver como va.  Hasta ahora, me gusto la idea de centrar el registro activo en el grid... creo que esto con la otra sugerencia del DoScroll() puede lograr el truco.

Luego les comento como me fue.

Saludos

Victor Espina

Marco Plaza

unread,
Jul 3, 2012, 10:21:26 AM7/3/12
to publice...@googlegroups.com

Hola Victor, este codigo colocará el resultado en la posicion en que se encuentre la celda activa para el momento de la busqueda:

*------------------------------------------------------

thisform.lockscreen=.t.

with thisform.grid1

    .SetFocus()

    pDeseada=thisform.grid1.RelativeRow
   
    locate for ....

    .setFocus()

    pActual=thisform.grid1.RelativeRow

    corr= pDeseada-pActual

    ds=iif( corr>0,0,1)

    for t = 1 to abs(corr)
        .doScroll(ds)
    endfor
   
    .refresh()

endwith

thisform.lockscreen=.f.


*----------------------------------------------------------------

Marco

Victor Espina

unread,
Jul 13, 2012, 4:35:26 PM7/13/12
to publice...@googlegroups.com
Amigos, no habia tenido tiempo hasta hoy de probar sus soluciones.  Al final, la solucion que funcion fue la de Ricardo, que consistia simplemente en colocar el LOCATE despues de la llamada a Refresh() y no antes.  Ese simple cambio soluciono el problema.

Muchas gracias a todos por sus aportes.


Saludos

Victor Espina


On Monday, July 2, 2012 1:10:25 PM UTC-4, Victor Espina wrote:

Jhonny Zambrana

unread,
Jul 17, 2012, 10:57:12 AM7/17/12
to publice...@googlegroups.com
Como dijo alguna vez LuisMa  "A veces la solucion esa en lo mas simple"
 
Me alegro por ti Vic.

Mario Oviedo

unread,
Aug 11, 2012, 10:28:48 PM8/11/12
to publice...@googlegroups.com
me llaga ricardo

--
 
 
 

Reply all
Reply to author
Forward
0 new messages