Hello Jonathan.
Thanks. Where should I place that code?? in the form's refresh event?First of all, an explanation of why you are seein gthis behavior:
One of the behaviors that has driven people crazy since the earliest days of FoxPro, and which still drives developers nuts in Visual FoxPro, is the way in which a control’s Valid() method fires. The problem occurs if you have a control (e.g. a TextBox) which has code in its Valid to ensure that bad data cannot be entered and also use a Toolbar or a Menu option to initiate the save. A user can enter bad data into the control, choose SAVE from the toolbar or menu, and the control’s valid fails to fire, allowing the bad data to be saved. What is going on?
The answer lies in the purpose of the Valid()! This event, is intended to fire when a control is about to lose focus in order to determine whether it should be permitted to lose focus or not. However, if the control does NOT lose focus, the event never fires. Unfortunately, this is precisely what happens when you use a toolbar (or a menu option) to determine the next action. The reason is that neither a toolbar, nor a menu, ever receive focus in Visual FoxPro, so the focus never leaves the control and the Valid never fires - the result is bad data in your database.
The reason for this behavior is so that Toolbars and Menus will not interfere in the normal operation of screens. It would be very irritating indeed if all the user wanted to do was to use the EDIT options of the menu to copy some text and the Valid (and LostFocus) of the current control immediately fired. After all, there is no way for Visual FoxPro to know WHICH menu item, or toolbar button, the user is about to choose!
The solution is to ensure that in your SAVE routines you force the currently active control to lose focus - thereby firing the Valid and LostFocus events.
Now, what you want to do is add a method called WriteBuffer() to your data aware form class. This code goes in the WriteBuffer() method:
LOCAL loColumn, loActiveControl, loControl, llRetVal
llRetVal = .T.
IF TYPE( 'Thisform.ActiveControl.Name' ) = 'C'
loActiveControl = Thisform.ActiveControl
IF UPPER( loActiveControl.BaseClass ) # 'GRID'
IF NOT EMPTY( loActiveControl.Valid() )
loActiveControl.SetFocus()
llRetVal = .T.
ELSE
llretVal = .F.
ENDIF
ELSE
FOR EACH loColumn IN loActiveControl.Columns
IF loActiveControl.ActiveColumn = loColumn.ColumnOrder
loControl = EVAL( 'loColumn.'+ loColumn.CurrentControl )
IF NOT EMPTY( loControl.Valid() )
loControl.SetFocus()
llRetVal = .T.
ELSE
llRetVal = .F.
ENDIF
EXIT
ENDIF
ENDFOR
ENDIF
ENDIF
RETURN llRetVal
I am assuming that your data aware form class has a DoSave() method that gets called from the click of the Save button in the toolbar. Call your WriteBuffer method like thid from your form's DoSave() method:
IF Thisform.WriteBuffer()
ELSE
ENDIF