派生的 TClient 数据集;定义一个 always-运行 OnAfterPost
Derived TClientdataset; defining an always-run OnAfterPost
我从 TClientdataset 派生并试图定义一个 'always run' AfterPost 事件。我已经尝试在构造函数中分配我的 AfterPost 事件,但派生组件似乎没有接收它
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;
我想做的是:在新记录上,设置 Finserting := True
;在 post、运行 之后,用户提供了 OnAfterPost 并设置了 FInserting := False
;但是 MyAfterpost 事件甚至不会 运行。我假设构造函数不是做 AfterPost := MyAfterPost;
的正确位置?它应该去哪里?
想做的事没有合适的地方。因为组件的用户可以在程序 运行ning 时随时将处理程序或 nil 附加到事件处理程序,而不仅仅是在设计时。也可以分离现有的处理程序。那么你的代码就不会运行.
出于这个原因,VCL 采用了对事件处理程序的两步调用。首先是一个虚拟过程,它通常只是调用一个可能的事件处理程序。在您的情况下,这是 DoAfterPost。
TMyClientDataset = class(TClientDataset)
..
protected
procedure DoAfterPost; override;
...
procedure TMyClientDataset.DoAfterPost;
begin
inherited;
FInserting := False;
end;
对于不存在这样的机会的情况,除了正确记录并希望组件的用户阅读并遵守它之外没有机会。覆盖 Loaded 将是备份现有设计时附加处理程序的正确位置。
是解决此类问题的绝佳指南。是的,它确实回答了你提出的问题,但它遗漏了一些东西。
在我看来,您遇到了 XY 问题,未能提出正确的问题。您无需尝试手动跟踪 FInserting
。 Delphi 已经这样做了。看看TDataSet.State and TDataSetState.
基本上你的 FInserting
等同于 State = dsInsert
.
虽然,正如您所指出的,您的 FInserting
标志在 OnAfterPost
中是 True
(这使它具有误导性,并且在此基础上在技术上是一个错误)。
我从 TClientdataset 派生并试图定义一个 'always run' AfterPost 事件。我已经尝试在构造函数中分配我的 AfterPost 事件,但派生组件似乎没有接收它
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;
我想做的是:在新记录上,设置 Finserting := True
;在 post、运行 之后,用户提供了 OnAfterPost 并设置了 FInserting := False
;但是 MyAfterpost 事件甚至不会 运行。我假设构造函数不是做 AfterPost := MyAfterPost;
的正确位置?它应该去哪里?
想做的事没有合适的地方。因为组件的用户可以在程序 运行ning 时随时将处理程序或 nil 附加到事件处理程序,而不仅仅是在设计时。也可以分离现有的处理程序。那么你的代码就不会运行.
出于这个原因,VCL 采用了对事件处理程序的两步调用。首先是一个虚拟过程,它通常只是调用一个可能的事件处理程序。在您的情况下,这是 DoAfterPost。
TMyClientDataset = class(TClientDataset)
..
protected
procedure DoAfterPost; override;
...
procedure TMyClientDataset.DoAfterPost;
begin
inherited;
FInserting := False;
end;
对于不存在这样的机会的情况,除了正确记录并希望组件的用户阅读并遵守它之外没有机会。覆盖 Loaded 将是备份现有设计时附加处理程序的正确位置。
在我看来,您遇到了 XY 问题,未能提出正确的问题。您无需尝试手动跟踪 FInserting
。 Delphi 已经这样做了。看看TDataSet.State and TDataSetState.
基本上你的 FInserting
等同于 State = dsInsert
.
虽然,正如您所指出的,您的 FInserting
标志在 OnAfterPost
中是 True
(这使它具有误导性,并且在此基础上在技术上是一个错误)。