2015-06-16 39 views
0

我正在开发DataAware组件,并在数据库打开后执行一些代码。Delphi中的组件事件检测

这是我此刻的代码:

TMyDataAwareComponent = class(TDataAwareComponent) 
    private 
    { Private declarations } 
    procedure ToBeExecutedOnAfterOpen(DataSet: TDataSet); 
    protected 
    { Protected declarations } 
    public 
    { Public declarations } 
    constructor Create(AOwner: TComponent); override; 
    end; 

constructor TMyDataAwareComponent.Create(AOwner: TComponent); 
begin 
    inherited; 
    if Assigned(Self.DataSource) then 
    begin 
    Self.DataSource.DataSet.AfterOpen := ToBeExecutedOnAfterOpen; 
    end; 
end; 

procedure TMyDataAwareComponent.ToBeExecutedOnAfterOpen(DataSet: TDataSet); 
var 
    i: Integer; 
begin 
    // Do something here 
end; 

代码工作正常,但连接到组件的数据集的事件AfterOpen不会触发任何更长的时间。 如何确保AfterOpen事件先在数据集中触发,然后在组件中触发?

是否有解决方案适用于数据集中的所有事件(BeforeOpen,AfterOpen,BeforeCancel,BeforeDelete,AfterCancel,AfterDelete等...)?

+1

*代码工作正常,但连接到组件的数据集的事件AfterOpen不会触发任何更长的时间。*你被劫持了! –

+1

编写数据感知组件是指Delphi作者已经完成的组件。对于单字段编辑器,请查看“TDBEdit”及其“FDataLink”字段;对于类网格组件,也可以查看“TDBGrid”及其“FDataLink”字段。 – Abelisto

+0

您需要检查Self.DataSource.DataSet是否也分配了fwiw。 – MartynA

回答

1

您可以使用一个虚拟的方法拦截器拦截DoAfterOpen虚拟呼叫

FVirtualIncerceptor := TVirtualMethodInterceptor.Create(TDataSet); 
FVirtualIncerceptor.OnBefore := procedure(Instance: TObject; Method: TRttiMethod; 
    const Args: TArray<TValue>; out DoInvoke: Boolean; out Result: TValue) 
begin 
    if Method.Name = 'DoAfterOpen' then 
    ToBeExecutedOnAfterOpen(TDataset(Instance)); 
end; 
FVirtualIncerceptor.Proxify(Self.DataSource.DataSet); 

更多信息 http://docwiki.embarcadero.com/CodeExamples/XE8/en/TVirtualMethodInterceptor_(Delphi)

看到这个我想你可以看到如何延长这一以处理其他案例

0

您将不得不保存旧作DataSet.AfterOpen并在ToBeExecutedOnAfterOpen中调用保存的方法。但是正如Abelisto在他的评论中所说的那样,这不是要走的路。它不会将您的要求通过为“对数据集中的所有事件有效的解决方案”。也许这可以帮助您:http://delphidabbler.com/tips/194

0

您可能会看看面向方面编程。就像@Jasper指出的那样...虚拟方法注入...

DSharp想到了很容易设置它。看看DSharp.Aspects.Weaver。您可以轻松绑定到已发布或公开的任何方法。

-Rick