It seems like this is kind of buggy when using a dataset with mastersource and masterfields.
The problem here is that you are messing with events in a deep level, not knowing when they actually fire.
Imagine this...
1) TSQLQuery.EnableControl will
check a flag to see if the data has changed. If it has it needs to call TDataSource.DataChange.
2)
AFTER TDataSource.DataChange... the flag is cleared.
In TDataSource.DataChange... you toggle TSQLQuery.DisableControl and TSQLQuery.EnableControl.
Because the previous flag hasn't cleared yet (because it's still in DataChange)... the TDataSource.DataChange is triggered again in TSQLQuery.EnableControl (see rule #1).
I agree... this could be handled internally better.. but what if you really change the data between DisableControl and EnableControl there ???
Then it should re-fire (because the data has changed.
Small question...
WHAT are you actually using the DisableControl and EnableControl for? What are you doing in between those in DataChange?
BTW. Using a global flag should have worked if you used it correctly.
At least... this works for me...
var
NotOkToEnterDataChange: boolean = False;
procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);
begin
if NotOkToEnterDataChange then exit;
Caption := Caption + '.';
NotOkToEnterDataChange := True;
try
SQLQuery1.DisableControls;
// ...
finally
SQLQuery1.EnableControls;
NotOkToEnterDataChange := False;
end;
end;