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!

Grid Navigation 1

Status
Not open for further replies.

Scott24x7

Programmer
Jul 12, 2001
2,826
JP
Hi All,
Having a very odd issue with a grid I use for navigation. I recently came out of "Developer Retirement" and haven't worked in VFP in around 10 years. Some of it has come back quickly, but other parts are a bit more sluggish, as I try to work out the best way to troubleshoot things.

Anyway, here is my issue. On one form I have 4 grids which basically show child records from other tables, and allow you to navigate to the record (and takes you to the detail tab for that table) when you double click on them (a simple ThisForm.Basepageframe1.ActivePage = <number> in the double click method).

The problem is, one of the grids does not allow me to click items within it. There are 3 records visible, but when I put the mouse over them to click the record, the record pointer doesn't move, and the grid doesn't update. Double click will take me to the tab (as the code above), but only on the first record, where I can then navigate them using next/previous buttons on the screen. Of the 4 grids on the main parent form, only this one has this behavior. Now, the one difference of this data vs the others, this is data from a relationship with a child already (so a grandchild). I can't figure out why that would make a difference, but the other 3 tables/grids are all from direct relationships with the parent.

Any idea why I can't select records in the grid that is the "grandchild" grid?

P.S. I even rebuilt the grid using one of the "working" ones so it wasn't some strange enable/disable or Focus issue, the result was exactly the same, which lead me to think that it's something to do with this grandchild relationship...



Best Regards,
Scott
ATS, CDCE, CTIA, CTDC

"Everything should be made as simple as possible, and no simpler."[hammer]
 
The record pointer in grids, which show grandchild or child data are controlled by parent tables/grids, obviously, but you can move within in the records.
The question is what settings differ. Did you set relations or used the grid properties linkmaster, childorder and relationalexpr? Or what builder did you use and what did you set there?
If you do both the grid properties and reltaions you can get unpredictable results. Also, if relations come from several parents.

What I tended to is not use both of these techniques, but do the navigation "manually" within the RowColChange event of parents, by doing seeks or locates in child tables. This way the movement there is free, even to records not related to parents. You may lock that via SET KEY, though, or locate the correct parent again in the RowColchange. One big advantage is, you are free to sort by other indexes than you'd need for the relations, especially if you also don't make use of SET KEY or FILTER.

Overall, there are many ways to solve a problem and so if one doesn't work as expected step back from the automatisms not working for you and get more elaborate. It's not all that much to program.

Bye, Olaf.

 
Scott, this might be totally unrelated to the cause of the problem, but I would take a moment to check the grid's AllowCellSelection property. If, for any reason, it is .F., that would explain the behaviour you are seeing.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Olaf,
Good to see you are still around old friend.
What I have done is, I have the Data Environment manage the tables in the form.
In this case, I have: Company (big parent), Facility (Child), Room (Grand Child). I have some other Parent:Child relationships, but this is the only "Grandchild" relationship. So company has CompanyID (Integer) as it's primary key. Facility has Facility ID (Integer) as Candidate Key, and CompanyID as regular (foreign key). That relationship is fine. I use the Data Environment to set the relationship.
Room has 3 index, CompanID (regular) FacilityID (regular - foreign key) and RoomID (Integer) (Candidate Key). The relationship established in the Data Environment thing is:
Company ->(companyID) Facility -> (facilityID) -> Room then Room is set to RoomID order, though it's relationship is FacilityID to FacilityID. There is NO direct relationship set to Company, it is just a cascading relationship.

I tried Mike's suggestion, but that just makes the field I click on "enabled" but it still only picks the first record in whatever column I'm in, so I turned that back off, as it wasn't the result. I'm not setting any other relationships.

What I find interesting as well when I go to the "Room" tab (I put these in tabs), I have navigation there in a grid for moving easily about the records, and there, the navigation works fine... I have utilized SET FILTER in other applications in the past, but I'm not doing that in this case. Though maybe that's a flawed strategy?


Best Regards,
Scott
ATS, CDCE, CTIA, CTDC

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Oh, and I should have mentioned:
Using VFP9 with SP1, SP2, SP2 Hotfix and Sedna applied.
Running on Win10, though I know there is no issue here, just letting you know.


Best Regards,
Scott
ATS, CDCE, CTIA, CTDC

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Well, you didn't tell how you created the grids.
If you make relations in the Data environment you are indirectly doing SET RELATIONS.
If you then use the builder to create 1:n related grids, you are indirectly making use of The grid properties, and that combination didn't work well for me, too.

I'm not advertising SET FILTER, I would rather just LOCATE a record matching and let the user go from there, you only need SET FILTER, if you want to only show direct children (or grand children) and want to keep navigation of the parent (or grand parent) separate. SET KEY is better suited, but takes the possibility to order by anything.

Don't do too much and don't use all the wizards and builders, this isn't giving good results anyway.

Bye, Olaf.
 
Hi Olaf,
No, I'm not using any wizards or builders. I have a defined class (gridbase) with grid as the base class. This object is dropped onto my form, and then I set the columns and data sources from there.
I only set control source at the column level, not in the text box (or whatever item I'm showing in the grid, but for now, I'm keeping it all to text box, just to make it easy to see which record you are choosing). So there are no relationships created with the grid, only display content, and only at the column level.

What I just can't explain is on another tab, same relationship is still persistent, as I haven't changed the Data Environment between tabs, and there, a similar data grid allows the navigation, so that seems really confusing. (I copied the grid from that tab onto the main tab, and there, I get the same result of can't navigate the grandchildren relationship... so very odd.)

Hmmm, I'm now looking in my gridbase click event... I may have a confusion there that doesn't happen on the other grids now that I look at it.
Let me toy with that, and I'll see if I can fix it, will let you know.
Cheers,

Best Regards,
Scott
ATS, CDCE, CTIA, CTDC

"Everything should be made as simple as possible, and no simpler."[hammer]
 
So it seems the solution was quite simple/elegant.
Because the Data Environment is managing the relationships and because no fields were updated (no need for ThisForm.Refresh()) by simply commenting out the InteractiveChange event, (which I had some refresh code there to update any fields that might be on screen in this case), the issue was solved.

The main thing I think was with 4 "navigation grids", the independent relationships were fine, but when the grandchild relationship occurred, during the refresh of the grid, it would have the effect of "re-clicking" the click code, which would reselect the parent, and update the child (grandchild in this case), and that would result in the "hickup". I happened to notice once that it did highlight the record very briefly, and then leap back to the first record again, so that was my clue something was repositioning it after it had been moved. And also why it worked fine in the other tab where ONLY that grid existed, because the others weren't getting refreshed.

So problem solved. One of my favorite ways to solve problems is to take away complexity, and just let the simple things come through. This was one of those cases.
That and I created these classes some 15+ years ago, and I certainly haven't been tinkering with their inner workings for quite a long time. It has reminded me how much I miss it though!


Best Regards,
Scott
ATS, CDCE, CTIA, CTDC

"Everything should be made as simple as possible, and no simpler."[hammer]
 
It's fully understandable you don't know your base classes anymore after 15 years. I would never have guessed a refresh() would renavigate via relations. Do you have something in the refresh, too?

In my knowledge a relation only takes effect, when a record pointer is moved in the parent table of the relation, not when a refresh reads from its current row. A grid refresh might differ, as it reads multiple rows, but when grids are on non active pages, they don't get a refresh call. Dud you do something in the pagerame refresh(), like activating all pages and explicitly refreshing them?

Indeed in a form with eg a grid and some controls for the single fields it's best o have a form.refresh() in the afterrowcolchange event, also in a navigation bar. In itself it shouldn't cause relations to position child tablel record pointers, there's got to be something else, but I'll later give it an experiment.

Bye, Olaf.

PS: I didn't yet experiment, but if it's happening because of refreshing, it should also happen with the first level child, you click on the second child record, refresh and the parent would pull the record pointer back to the firrst child. As it only happens to your grandchild grid, there's got to be more involved in your base classes. We'll see later.
 
I'm inclined to agree, but for the moment, I've solved the issue. I will dig deeper in it later. This is the prototype, so I don't have to have it 100% bug free on day one. :)


Best Regards,
Scott
ATS, CDCE, CTIA, CTDC

"Everything should be made as simple as possible, and no simpler."[hammer]
 
I just don't want this stand untested. Not that someone later refers here to state grandchild relations have a different behaviour.

I did a quite simple thing: Put the customers, orders and orderdetails into the dataenvironment of a standard form class. This generates the table objects with relations in the DE.
Now I dragged the three tables into the form and created three grids (baseclass). So there is nothing in their afterrowolchange events or refresh or anyhting. All just base behavour.

Starting the form you can navigate freely in all three grids. Navigating in the customer grid shows first orders and the orderdetails of the first order, obviously.
navigating in the orders leaves the customer as is and jsut influences the orderdetails. And I can activate any orderdetail without influencing the two parent and grand parent grids.

By the way: The grids don't have any of their special linkmaster and relationalexpr set, there are relation objects in the DE and the data session windows shows the relations in the right listbox going from top table customers to orders and finally to orderdetails, a straight downward hierarchy.

At this point: Doubel check, if the relations go in the directions you think of them, the DE may find and create relations you don't want. The DE can tell you in the preropties of the relations, if you right click the lines, bu the datasession will show parents above childs and indent childs, so there it would get very obvious, if you have a false directed relation.

So far, so good.


Second Setup: Refresh() calls

Now I introduced THISFORM.REFRESH in all grids afterrowcolchange events and here the fun begins:
Yes, as I though, the effect is not only on grandchildren, if you click inside the orders grid, the refresh in it also refreshes the customers grid and puts the order back to the first order of the first customer. Via this refresh mechanism you are locked at each first record and can't move.

Third Setup: Pages

Now I put each grid into its separate page of a pagefram. My assumption is and was, the refresh will not act on the non active pages.
And voila: The grids now don't refresh each other anymore, as they are separated and so there is no pseudo locking of the record pointer anymore.

So you can have your base grid with Thisform.Refrssh in its AfterRowColChange event, but then don't put two grids side by side into the same parent container (be it a page or a container or the form itself), as this would cause a lock in the child (or grandchild or further down the drain) grid.

As simple as that. And if that happens to you with grids separated in a page each, then you have done something in your base pageframe class to make the general pageframe refresh cascade into each page, also into non active ones. That "fix" costs you this bug. I see many more options, but this would be one explanation. In general the problem simply is the relations taking effect as soon as the parent side table is iterated by eg a grid refresh.

Bye, Olaf.
 
Olaf,
Yes, I believe that is exactly what I'm seeing as well.
In my AfterRowCol change, I have code to "combat" this issue, when there is just parent and child, which involves capturing the record pointer before the refresh, and then forcing it to move back to the right records after. That was fine because I only ever considered it in parent and child (and god knows what I was doing with old DE's). So when just using the simple DE to manage the relationships, and having grandchild in the same page, you get just what you describe, so I set them NOT to refresh, and then the work. As you say, grids in other tabs aren't affected, because the "ThisForm.Refresh" only affects the active tab. (And I have code in my class to handle that too), but it's all very rusty to me... so when there is something broken, it's a bit challenging to remember WHY I did what I did 15 years ago. But for now, my philosophy has been "keep it simple", and if VFP can manage the relationships for me, I don't want to do a lot to try to usurp that "power". It's probably more maintainable that way anyway. :)

Thanks for the rundown, and the analysis. Well done.


Best Regards,
Scott
ATS, CDCE, CTIA, CTDC

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top