I have created As Top-Level Form with a corresponding menu.
If I do not press Tab or Enter before clicking Save from menu, the field variable is not being updated.
I’ve tried KEYBOARD {'TAB'}
Any help please.
Shane.
Much more info is needed. What is not saved? Data from the current control? Even without buffering a control only saves its current displayed value to the controlsource, when it's valid event is passed. So saving from toolbar or menu does not save the current value of the current control. Is that your problem?
A simple solution is a save button put on the form instead. Clicking on it, the focus is moved to the save button, causing the valid of whatever current control.
Keep in mind that clicking on a menu item does not lose focus from the control; the control's Valid and LostFocus do not fire, nor is the ControlSource updated.
Mike
__________________________________
Mike Lewis (Edinburgh, Scotland)
A solution within a save menu item or toolbar save button is _SCREEN.ActiveForm.ActiveControl.SetFocus(), but there isn't always a currently active form and when the currently active forms active control is a grid, you also need to drill deeper.
The way this works is that a setfocus to the active control is not so useless as it seems. It maked the control go through a cycle of all the events from valid, lostfocus, when, gotfocs, so its current value is saved.
The KEYBOARD '{TAB}' does not help, as it has no immediate effect, you just queue a keyboar events series, that only will happen after code goes back to READ EVENTS, so when you TABLEUPDATE the TAB still has not had its effect. By the way, it's not KEYBOARD {'TAB'} - that'll give a syntax error.
You could give a DOEVENTS FORCE a try after KEYBOARD '{TAB}', after all you have the menu in the top level form. Nevertheless the easy slution of a save button on the form itself is, it'll move focus to itself automatically anyway, no matter if done by clicking, by tabbing to it and 'clicking' it with SPACE or by letting it be the default button activated by ENTER. The focus always first moves to the button and thereby saves the current control first, before any save code runs.
The valid event has to happen, it does not help to put code into it and call it. That's not at all what I suggested.
Overriding the valid event by writing code into it, you override its base behaviour. That's not at all, what you should do.
Are you at all using the controlsource property to bind controls to data?
About events and when and what code to write into them:
First of all events are happening and in their event method you react to them. A button for example, does nothing, when you click on it and have no code in click. But while that's the most frequently used and first used method most developers ever code, it's not typical for events to have no default behaviour even without code in them.
The events all can be edited and you can program code into them. If events always would need to be kept empty, you wouldn't get the opportunity to code in them. Some events, like KeyPress, even give you parameters, eg which key(s) were pressed. Also the valid event can contain code, but what is the event named? Valid, it decides, whether the data in the control.value is a valid value. In some cases you won't accept empty values, in other cases you won't accept dates in the past, only dates in the future. You return .F., when you don't want to accpet the control value. If you don't program anything into valid, you accept any value, as empty methods automatically return .T.
When the valid event was passed and returns .T., the control also saves its value into it's controlsource. From that persepctive you don't need any save code at all, you only need to set controls controlsource value and the controls save their values automatically. The need of save code arises, if you buffer the fields you bind via controlsource, eg you set the buffering of cursors or views or tables involved. Such save code would do a TABLEUPDATE(), for example. It might do more, it might auto fill other fields or do whatever other data maniupulations, eg set a lastupdate field of a table to datetime().
The point is, that such save code cannot commit a table.field value, when the control valid has not run, in the sense of has not happened. If you call valid you still don't make the control save its value to the controlsource, you only do your own code in it, but don't trigger the valid event. You only trigger it by moving focus to another or (as weird as it may sound) the same control). Then the valid happens.
If you program [tt]REPLACE somefield WITH this.value IN sometable[/tt] within the valid event of the control, you do, what VFP automatically does, when you set the controlsource preoprty to [tt]sometable.somefield[/tt]. VFP does a lot of things for you without any code, if you simply use it correctly and know the properties and their meanings.
So in short again:
You set a textbox.controlsource to sometable.somefield and thereby bind the textbox to that field twoways - it displays the fields value and edits in the textbox go to the field.
You only need to set focus anywhere else to save the displayvalue. A savebutton on the form does this, even without any click code in it. Also closing the form without clicking it will make the focus be lost and the field be set to the new value.
So in this simple setup you don't need anything else, no code in clicks or valid to let the textbox work. It's just a very simple setupand you might want more control. eg validate your data.
So in short about the valid event:
You write code into it checking the validity of data and allowing its saving to the table field by RETURN .T., disallowing with RETURN .F., you can also return 0 to stay in the control, you can also return a value N being the offset in tab order you want to set focus to other controls and finally you also can return ThisFORm.someothercontrol to set focus to someothercontrol, if that matters to set the value correctly. But you don't save data in the valid, the saving of buffered data should be a separaate method, as you had, but it should only run, after the valid has happened.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.