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 Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

ComboBox: Force InteractiveChange to write new selected value to table field 1

Status
Not open for further replies.

Rajesh Karunakaran

Programmer
Sep 29, 2016
545
MU
Hi friends,

I have a comboBox in a grid which is bound to a table field. Now, after user selects a new value from comboBox, I want that value to be written to the table immediately even before the user leaves the comboBox.

Rajesh
 
If I understand you correctly, you only want to do what the usual controlsource data binding does when Valid event fires (and allows saving)
Then all you need to do is writing THIS.Value into This.Controlsource in the combobox interactivechange:

Code:
REPLACE (This.Controlsource) With This.Value In thetable
It's not necessary to do as even closing the form means the grid loses focus and so the valid and lostfocus of the combobx fire and the selected value is stored. If you experience a problem, what doe not work for you without enforcing what's automatically done anyway?

Chriss
 
One more detail:

If This.Controlsource is alias.field, then you can generally just do:
Code:
REPLACE (JustExt(This.ControlSource)) WITH This.Value in (JustStem(This.ControlSource))

Chriss
 
Chriss,

I am running this form from multiple sessions (from different terminals at client side)

As you suggested, in the Combo InteractiveChange, I am already doing like
Code:
REPLACE tbl.field WITH this.Value IN tblAlias
and I can see the new value shown in the 1st session. Here, say, I am staying in the same record.

Now, in session two, suppose it's on the same record in grid. Even if a go past that record (up or down), I cannot see the new value saved from session 1.
However, in session 1, if I move from that record, then in session 2, the new value shown when I am on that record.

As a general rule of record locking, it's waiting for pointer to move from that record for actual value update in table?

Rajesh
 
Didn't we had that topic in a previous thread.

Neither Browse nor grid will pull new data, even less so the file server will push in changes.
If our record is buffered you also will only get curvals from moving away and back to the record, if the record buffer is flushed.

So to see all fields most recent values fromm multiple sessions becoming proactive in interactivechange and not wait for valid to save changes, you also need to pull in changes, they don't propagate to every other client automatically.

And while you work with buffering there is table and row buffering but not something as detailed as field buffering, so anything you didn't change gets read from the current DBF. You only get current values of a whole record, when you change to it and it wasn't yet buffered, i.e. the gird can change from the value it read at the time the grid refreshe last time to the current DBF value, if you activate a record. But that only happens, if that record isn't yet buffered.

So there are two parts of this: 1. How immediate is your change of the DBF, an 2. how immediate is your reading of current values from the DBF.

You're expecting too much of active polling of curvals. Grid/Browser don't autorefresh and when anything in a record is changed and thus the record buffered (before it's committed by tableupdate), current values don't refresh such rows, so you can't see a merge of your own and other users changes without getting active in a very detailed way to actively read the current values of data that is displayed. And in yet other words what you see displayed was either that way when it first was written to display or is changed by you, things changed by others at best display in the moment you click into a record that has no changes by yourself but was updated in the DBF from other users.

Chriss
 
Chriss,

Yes, I had posted another thread discussing updating latest values in a table on different terminal screens realtime.

In this case, I don't want to go for anything more than a simple work around, if possible.
Otherwise, let me check how crucial is this for the client.

Thanks
Rajesh
 
There is no workaround.

If a client A should see changes of another client B, then both things have to be done:
1. client B has to tableupdate the DBF so changes are in general available for everyone else, too
2. client A (and any other) needs to pull this from the DBF.

REPLACE in interactive CHANGE pushes the selected value from combobox control into the buffer, it's not yet saving to DBF. But even assumed you do a REPLACE and TABLEUPDATE of the current row to have the nearest as possible DBF change, other clients still will need to actively read this.

So you don't jsut need to act on the interactivechange, you should also reacct in When or at least Gofocus with refreshing the control a user activates before he starts editing. A change of a control you activate happens automatically on certain conditions:
1. The value displayed was read from the DBF at time of starting the form or last scrolling it
2. The record you change to has no buffered changes yet
3. changes of other sessions have been stored to the dbf
And with views this has a 4th condition that you REQUERY() the view or at least REFRESH() the current record (or a bunch of rows). And that, just like the automatic refresh of directly bound DBF without the view layer only happens, if the to be refreshed rows have no changes yet from the local user, neither in the field you focus, not in any other field of the record. VFP only refreshes whole records.

There is nothing buggy about this that will need a workaround, that's the design and if you want to improve it you can consolidate between CURVAL() - value in the DBF - OLDVAL() - value that was first read at form start or last grid scroll/refresh and then alias.field, the value that may still be OLDVAL() or could be modified locally and thus subject to an update conflict as you already have a partial unsaved change from OLDVAL() and a CURVAL() that's also a change from OLDVAL() and I didn't even mention that control.value can be a fourth value of the same field of the same record, conceptually, as the control.value isn't buffered until valid returns true and the controlsource (buffer) is updated.

So, do you understand that CURVAL("alias.field"), OLDVAL("alias.field2), and alias.field and conrtol.value bound to alias.field can be four different values? And that a record is buffered whan alias.fieldX differs from OLDVAL("alias.fieldX") for any field of the record (no matter if row or table buffering), not just for the one field you'Re interested in? Which in detail means that no refresh will be made even if alias.field == OLDVAL("alias.field") (no edit/conflict) and there is a new CURVAL("alias.field"). You have to make it the locally most current and thus buffered value yourself, that's only automatic if the record didn't yet participate in buffering. And for that reason row buffering is easier in getting to that state at least once you change to another record and back. Ideally for this to cause any refresh would be no buffering, as it removes the prerequisite of not buffered row for refreshing . Well, the problem with that is that CURVAL and OLDVAL are only available in a buffered mode. Without buffering you can't read CURVAL("alias.field") and if you think that's no problem, because then alias.field itself will read from the DBF, you underestimate the networking effects, alias.field always is just a workarea value, buffering on or off. CURVAL() enforces read from DBF, but requires buffering to be turned on.

You can check whether you really understand the buffering concept if you understand that while using no buffering you get nearer to the imagination the grid shows you the actual DBF data as it is currently, but that's never the case. The only solution to get nearer to that goal is making the problem worse with buffering first, which introduces the four level concept of values of a field but is the only mode that also gives you the strong strictly reading from DBF file with CURVAL(). And then, this strong power ends at the DBF file, it won't go on further and look into any other users more current buffered value, because that's only what you imagine is the even more current value someone else already knows he will save. Buffers are only local, CURVAL() can only read from DBF not look into all other users buffers and ask for the most latest change made. There is really nothing like that. So to get nearest to a grid monitoring a DBF you need to use buffering, actively save values earlier than the controlsource mechanism does and also do more than automatic refresh of controls does when you set focus to them.

Chriss
 
Chriss,

Chriss said:
If a client A should see changes of another client B, then both things have to be done:
1. client B has to tableupdate the DBF so changes are in general available for everyone else, too
2. client A (and any other) needs to pull this from the DBF.
Yes.

In my form, the table is not buffered. It's a small free table.

Thanks,
Rajesh
 
Well, Rajesh, see my edited post. Buffering is the only way to get to nearly monitoring the most current values of a DBF: And even in what I said to use CURVAL() to update a field just in time you GotFocus. That's only the best time to refresh when thinking about stating to edit anything from the most recent centrall known state. If you want a form / grid to just sit there without local user activity refreshing with other user changes as soon as possible after they happen, you would still need a timer to refresh at least the display rows of the grid and can't rely on that just happening.

So you actuall still much more ask about what to do in such a timer than what to do in interactivechange. The only thing to add to interactivechange aside of REPLACE is TABLEUPDATE to get it from control to buffer and then from buffer to DBF, so the timer in other users grids can refresh with that stored value.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top