JeffP
JeffP

Reputation: 555

Derived TClientdataset; defining an always-run OnAfterPost

I'm deriving from TClientdataset and trying to define an 'always run' AfterPost event. I have tried assign my AfterPost event at the constructor, but the derived component does not seem to pick it up

TMyClientDataset = class(TClientDataset)
private
  FInserting: Boolean;    //set to True at the MyOnNewRecord event
  property FuserAfterPost: TDataSetNotifyEvent;
...
public
  constructor Create(AOwner: TComponent);
...

implementation
constructor TMyClientDataset.Create(AOwner: TComponent)
begin
  ...
  if Assigned(AfterPost) then
    FuserAfterPost := AfterPost;
  Afterpost := MyAfterPost;
...
end;

procedure TMyClientDataset.MyAfterPost(Dataset: TDataset);
begin
  If Assigned(FuserAfterPost) then
    FuserAfterPost(Dataset);
  FInserting := False;
end;

What I'm trying to do: On new record, set Finserting := True; On after post, run the user supplied OnAfterPost and set FInserting := False; But the MyAfterpost event won't even run. I'm assuming the constructor is not the right place to do AfterPost := MyAfterPost;? Where should it go?

Upvotes: 3

Views: 255

Answers (2)

Disillusioned
Disillusioned

Reputation: 14832

Sertac's answer is excellent guidance on this type of problem. And yes it does answer the question you asked, but it's missing something.

It seems to me that you have an XY problem, and failed to ask the correct question. There is no need for you to try to manually track FInserting. Delphi already does this. Take a look at TDataSet.State and TDataSetState.

Basically your FInserting is equivalent to State = dsInsert.
Although, as you have pointed out, your FInserting flag is True in OnAfterPost (which makes it misleading, and on that basis is technically a bug).

Upvotes: 0

Sertac Akyuz
Sertac Akyuz

Reputation: 54812

There's no good place for what you want to do. Because a user of the component may attach a handler or nil to the event handler anytime while the program is running, not just at design time. May detach an existing handler too. Then your code will not run.

For this reason, VCL employs a two step call to event handlers. First is a virtual procedure which, generally, does nothing more than to call a possible event handler. In your case, this is DoAfterPost.

TMyClientDataset = class(TClientDataset)
  ..
protected
  procedure DoAfterPost; override;

...

procedure TMyClientDataset.DoAfterPost;
begin
  inherited;
  FInserting := False;
end;


For a case when no such opportunity exists, there would be no chance but properly document and hope for the user of the component reads and complies with it. Overriding Loaded would be the right place to backup an existing design-time attached handler.

Upvotes: 3

Related Questions