Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Highlighting the same row in Grid after a Refresh

Status
Not open for further replies.

Rajesh Karunakaran

Programmer
Sep 29, 2016
549
MU
Hi All,

I have a form. It has 1 grid and 1 Editbox. I have row HighLightStyle = 2 in grid. The record source is a Cursor. That cursor is updated from a timer. There may be new records coming in or existing ones removed during the update. Then, the user selects one record from grid. Then the ID from the cursor is SEEK in another base table and then the user can modify a field of that table through the Editbox.

1. But, when the grid is updated, the highlight goes away. Also, if the user has already selected a record to work and then after the grid got updated, I want that same record to be shown as highlighted.
What is the best approach for this ?

2. Suppose the user had selected the 3rd record in the grid and is working on that. Then, when the grid is updated, that record goes to the first visible row in the grid (making the 2 records above it go beyond grid display area). Is there any way to retain the display of records (I mean the order in which they were shown top to bottom in the grid rows) the same even after the record source refresh.

Thanks in advance
Rajesh
 
Hello,

I would store the ID of the last selected report (maybe in afterrowcolchange) in a form property.
After edit and cursor rebuild seek this ID and refresh grid.
Maybe you handle specially if found=.f. because ID was deleted or do not match filter / where anymore.

Trying to make it look exactly the same is not so easy if you have to handle edit (change in sort order) , new (maybe one more above) , delete.
if you like have a look on activerow and doscroll()

or something I do in some programs
Code:
With Thisform.mygrid1 &&Parent.Parent
     lnh=.Height
     .Height = .HeaderHeight + .RowHeight
     .SetFocus()
     .Height = lnh
Endwith



Regards
tom
 
Hi Tom,

Thank you for your time.

1. I am already doing the resetting of the record pointer after a refresh thereby landing on the same record where I was earlier.
But my problem is that visually it is not shown as highlighted.

Or, in other words,
the query is how do we show a row as highlighted programmatically (ie, without clicking on the grid row)

2. Yes, that's difficult I know. Let me try to figure out something based on your idea along with activeRow and doScroll.

Thanks
Rajesh
 
A first step should be to set the HighLightStyle to 3 to have visual persistence, meaning the highlight also is shown when the grid hasn't focus (but the Editbox becomes it, for example).

I wonder why an update of the cursor has an effect on the grid, when you finally return to the same record. Do you zap and refill it or do you do updates or replaces? In all cases the record pointer will move, but the grid should only eventually care. Setting Lockscreen on and off during the cursor update should help with it.

Tom surely is right in the most general case when the grid cursor has a new number of records and the same id finally isn't in the same recno of it, then the grid will change. Take the case of the active ID to be removed separately, I'd maybe locate to the top row, then. But if it's still in the data ideally it should stay in the same record. If you can't manage that, then you have grid.activerow. This has to be preserved when the grid has focus and the record is within the displayed range. Then finally after you seek/locate/goto the same id it will usually show up in activeRow=1 and you can use the grid.DoScroll() to get it back to what it was before.

I'd look for a grid class that has ActiveRow and/or DoScroll in its description, someone surely has done this already.

Edit: I see, you're already having the right ideea about ActiveRow and DoScroll.

Chriss
 
It is also useufl to look at the RelativeRow property. This tells you which row is highlighted relative to the top-most row currently visible (rather than the first row in the cursor). You could note the value before you do the update, and then DoScroll to restore it.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Tom mentioned about storing the ID, perhaps the way I do it is similar but using the RECNO()

When a user updates a record in a GRID, the highlighted records RECNO() is stored to variable or if not updated, the variable mjobrecno is set to 0 (zero). I'm not sure if I am going along the right lines for what you are trying to achieve, but as a relatively new user of VFP9, it works for me. Here's my contribution:

Code:
IF mjobrecno>0
  SET ORDER TO JOBNUMB DESC
  GO TOP
  thisform.grdMyGrid.Refresh
  GO mjobrecno
  thisform.grdMyGrid.SetFocus
ELSE
  SET ORDER TO JOBNUMB DESC
  GO TOP
  thisform.grdMyGrid.Refresh
  thisform.grdMyGrid.SetFocus
ENDIF

I hope that makes some sense and good luck.

Thank you

Steve Williams
VFP9, SP2, Windows 10
 
Dear Chriss & Steve,

Yeah! By 'update' of the cursor of the grid, I mean, it's a refill as Chriss asked.
I am already doing most of what you suggested I believe.

Suppose the user is editing the Editbox.
At this time the timer triggers and it does...

1. Store the existing grid cursor record Id (it's a field value in fact)
2. Latest data is fetched into a temporary cursor
3. ZAP the grid cursor
4. Append from temp cursor
5. Remove the temp cursor (as a clean up process only)
6. If I have a value for the Id (from step 1), seek that in the grid cursor

Now, I have updated the grid cursor and I am in the same record where I was before the update.
But, that record in the grid is not shown highlighted.
(However, if I click manually, then it's okay. I can see the current row in blue background.)

Dear Mike,

I think, you're referring to point 2 of my queries. What you suggested can certainly be useful. I need to figure out a way using those properties.
I have ActiveRow & RelativeRow. Let me play with those.
If I manage to get it done, will come back and post details here.

Thanks
Rajesh



 
Rajesh said:
But, that record in the grid is not shown highlighted.
(However, if I click manually, then it's okay. I can see the current row in blue background.)

If you set HighlightStyle to 3 that will highlight the current row, so that doesn't need a click.

RelativeRow should do the rest, ie scroll it to the place it was before.

ZAP and APPEND is fine, but you could also use this (using gridcursor and tempcursor as alias name placeholders):
Code:
Select tempcursor
SET DELETED ON && if it isn't already
Index On Id Tag Id && if you didn't already when querying data.
Select gridcursor
SET RELATION TO Id INTO tempcursor
Scan
   If Eof('tempcursor')
      Delete
   Else
      Select tempcursor
      Scatter Memo Name oUpdatedRecord
      Delete
      Select gridcursor
      Gather Name oUpdatedRecord Memo
   Endif
Endscan
Append From DBF("tempcursor")
Use In tempcursor

I tested with
Code:
* emulating a gridcuror refresh()
Create Cursor gridcursor (Id Int, otherdata M)
Insert Into gridcursor Values(1, "foo")
Insert Into gridcursor Values(2, "bar")

* lets say the tempcursor is about the same data
Select * From gridcursor Into Cursor tempcursor Readwrite
* except it has one deleted row
Delete
* and a new one
Insert Into tempcursor Values (1000,"new")




Chriss
 
If there's any possibility to know if records did change, then you could also spare a lot of scatter/gather that effectively does nothing.
You could compute a checksum of both gridcursor and tempcursor, but I guess that takes longer than just scatter/gather an unmodified record.

With ZAP you also accept to reinsert same records, it's even throwing out all data and doesn't care for details.
But if you have a lastupdate datetime field or a version field, you could compare these and only scatter/gather when necessary.

The APPEND step that cares for all tempcursor records that were not visited by the relation could also recall deleted records and gather new ones, but that would only be memory optimization. This won't spare time, but you will only need to go back to the last id and the grid won't change. It could spare time, if you can optimize the query process to only need to fetch changed or new data since last fetch.

In a usual case with few records in the grid it won't matter that this record by record refresh is much slower than ZAP/APPEND, but the major time waste with that is in the tempcursor query fetching a lot of unchanged data again, not so much copying that over into the gridcursor, which is just happening in local memory, unless the tempcursor is large. But then this whole concept should be mended into the direction of not fetching all data multiple times.


Chriss
 
But, that record in the grid is not shown highlighted.
(However, if I click manually, then it's okay. I can see the current row in blue background.)

To avoid having to click manually, you could call the grid's SetFocus.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Chriss said:
If you set HighlightStyle to 3 that will highlight the current row, so that doesn't need a click.
Mike said:
To avoid having to click manually, you could call the grid's SetFocus.

Chriss/Mike, let me check both and finalise between them.

Then Chriss, I am currently doing somewhat same thing you suggest, say, removing those records from temp cursor which exist in Grid cursor and also deleting from Grid cursor records that are not in temp cursor. That works fine it appears.

Rajesh


 
Hi All,

This seems solved. I changed a bit in my approach.

Now, I am not refilling the base cursor of the grid. Instead, I am fetching the latest data into a temporay cursor.
Then I remove all recs from temp cursor which are already there in base cursor. Also, I am removing from base cursor
those which are not in temp cursor (that's a business rule anyway)

Then, in base cursor, I simply append from the temp cursor.
The base cursor has a field SL which is auto inc and an index on that. The new recs will already be at the bottom.
So, my selected record position and highlighting is intact.

Anyway, I am checking for different scenarios.

Thanks to all,
Rajesh

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top