TDataSet will automatically posted a modified record when scrolling between rows. However, when the dataset is closed a modified record is “cancelled” and the changes lost. This gives rise to two problems:
1.In some cases, it may be better to cancel any changes when scrolling rather than post. A good example of this is when using a TDBGrid and you scroll beyond the end of the grid. In this case, a new row is automatically added. If the user ignores this and scrolls back, the append should be cancelled and not saved.
2.Automatic posting on scroll is arguably inconsistent with no similar behaviour on dataset close. Instead, this behaviour has to be added explicitly in an OnBeforeClose event handler.
IBX (v 1.2.3) attempts to improve upon this by adding the “OnValidatePost” event and the “DataSetCloseAction” property.
TOnValidatePost = procedure (Sender: TObject; var CancelPost: boolean) of object;
This event is called as the first action in the Post method. If it returns with “CancelPost” set to true, then the “Cancel” method is called and the “Post” terminated. The event handler can thus decide if the Post should be cancelled by checking the actual field values, even prompting the user to decide.
In terms of event sequencing, the event occurs before an OnBeforePost Event. Thus when the dataset is scrolled and the current record is in the “modified” state, then the following events will occur:
•OnValidatePost (returns CancelPost = false)
•OnBeforePost
•OnAfterPost
•OnBeforeScroll
•OnAfterScroll
or
•OnValidatePost (returns CancelPost = true)
•OnBeforeCancel
•OnAfterCancel
•OnBeforeScroll
•OnAfterScroll
Note that trying to call “Cancel” in an OnBeforePost handler does not work as the Post still proceeds and, with IBX, an error will be reported.
An exception could be raised in either the OnValidatePost handler or in the OnBeforePost handler to report an actual error in the record.
TDataSetCloseAction = (dcDiscardChanges, dcSaveChanges);
The property is used in the TIBCustomDataSet.OnBeforeClose method i.e.
procedure TIBCustomDataSet.DoBeforeClose;
begin
inherited DoBeforeClose;
if State in [dsInsert,dsEdit] then
begin
if FInTransactionEnd and (FCloseAction = TARollback) then
Exit;
if DataSetCloseAction = dcSaveChanges then
Post;
{Note this can fail with an exception e.g. due to
database validation error. In which case the dataset remains open }
end;
end;
If the dataset is still in the insert or edit state after any OnBeforeClose handler is called then “Post” is called if the property is set to “dcSaveChanges”. The exception is when the dataset is being automatically closed due to a transaction rollback.
If the DataSetClose action is “dcDiscardChanges” (default) then no action occurs and the changes are lost. i.e. the previous behavour.
For backwards compatibility reasons, dcSaveChanges must be explicitly set in the Object Inspector.