如何在运行时分配 TFDMemtable AfterPost 和 AfterDelete 事件?

How to assign TFDMemtable AfterPost and AfterDelete events on runtime?

我有一个由多个表单共享的 DataModule,我在其中构建了一个过程来处理作为参数传递的 TFDMemtable。为了处理它,我必须禁用事件 AfterPost 和 AfterDelete,并且在结束处理时我必须重新启用它们。我没有成功启用它们,因为我无法以 "actualnameAfterpost".

的形式获取这些事件的实际名称

我试过了:

    pMemTable.AfterPost  := @pMemTable.AfterPost ; // Result ==> compile error          
    pMemTable.AfterPost  := addr(pMemTable.AfterPost) ; // Result ==> compile error          
   pMemTable.AfterPost  := MethodAddress(Pmemtable.ClassName +'AfterPost'); // 
   Result ==> compile error

这是主要代码:

procedure UpdateMemtable (var pMemTable : TFDmemtable);
begin
      pMemTable.AfterPost   := nil;
      pMemTable.AfterDelete := nil;

     TRY
     with pMemTable do 
     begin 
             { code to process pMemtable }
        end;
      FINALLY
        pMemTable.AfterPost    := ["actualmemtablenameAfterPost" ??];   
        pMemTable.AfterDelete  := ["actualmemtablenameAfterDelete" ??];   
      END;    
end;

谢谢大家!

您只需要编写您的程序,然后将它们分配为

...
  private
    { Private declarations }
    procedure MyAfterPost(ADataSet: TDataSet);
    procedure MyAfterDelete(ADataSet: TDataSet);
...
procedure TForm1.MyAfterDelete(ADataSet: TDataSet);
begin
  ShowMessage('After Delete Fired');
end;

procedure TForm1.MyAfterPost(ADataSet: TDataSet);
begin
  ShowMessage('After Post Fired');
end;
....
pMemTable.AfterPost:= MyAfterPost;
pMemTable.AfterDelete:= MyAfterDelete;

这里有一个简单的示例可以帮助您理解,只需 运行 看看会发生什么

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, FireDAC.Stan.Intf, FireDAC.Stan.Option,
  FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf,
  FireDAC.DApt.Intf, Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client,
  Vcl.ExtCtrls, Vcl.DBCtrls, Vcl.Grids, Vcl.DBGrids;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    pMemTable: TFDMemTable;
    Ds: TDataSource;
    Grid: TDBGrid;
    Navigator: TDBNavigator;
    procedure MyAfterPost(ADataSet: TDataSet);
    procedure MyAfterDelete(ADataSet: TDataSet);
    procedure GridTitleClick(Column: TColumn);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  // Free all
  pMemTable.Free;
  Ds.Free;
  Navigator.Free;
  Grid.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Create the pMemTable
  pMemTable:= TFDMemTable.Create(Nil);
  with pMemTable do
    begin
      FieldDefs.Add('Column1', ftInteger);
      FieldDefs.Add('Column2', ftInteger);
      CreateDataSet;
      // Assign the procedures
      AfterPost:= MyAfterPost;
      AfterDelete:= MyAfterDelete;
    end;
  // Create DataSource
  Ds:= TDataSource.Create(Self);
  Ds.DataSet:= pMemTable;
  // Create DBNavigator
  Navigator:= TDBNavigator.Create(Self);
  with Navigator do
    begin
      Align:= alTop;
      Parent:= Self;
      DataSource:= Ds;
    end;
  // Create DBGrid
  Grid:= TDBGrid.Create(Self);
  with Grid do
    begin
      Align:= alClient;
      Parent:= Self;
      DataSource:= Ds;
      OnTitleClick:= GridTitleClick;
    end;
  //
  Self.Width:= 250;
  Self.Height:= 250;
  Self.BorderStyle:= bsDialog;
  Self.Position:= poScreenCenter;
end;

procedure TForm1.GridTitleClick(Column: TColumn);
begin
  {
   The events now is enabled on creation, if you click on "Column1" title
   then you disable them, if you click on "Column2" title, you enable them again.
  }
  if Column.Index = 0 then
    begin
      pMemTable.AfterPost:= nil;
      pMemTable.AfterDelete:= nil;
    end
      else
        begin
          pMemTable.AfterPost:= MyAfterPost;
          pMemTable.AfterDelete:= MyAfterDelete;
        end;
end;

procedure TForm1.MyAfterDelete(ADataSet: TDataSet);
begin
  // You will see this message after post
  ShowMessage('After Delete Fired');
end;

procedure TForm1.MyAfterPost(ADataSet: TDataSet);
begin
  // You will see this message after delete
  ShowMessage('After Post Fired');
end;

end.

最后,我建议访问那些页面并阅读它们:

两个事件的类型都是TDataSetNotifyEvent。使用两个这种类型的局部变量来临时保存事件。

要禁用事件,请将它们保存到临时变量中,然后将它们置零。 完成操作后,从临时变量中恢复实际事件。

procedure UpdateMemtable (var pMemTable : TFDmemtable);
var
  tmpAfterPost,
  tmpAfterDelete: TDataSetNotifyEvent
begin
  tmpAfterPost := pMemTable.AfterPost;
  tmpAfterDelete := pMemTable.AfterDelete;

  pMemTable.AfterPost   := nil;
  pMemTable.AfterDelete := nil;

  TRY
    with pMemTable do 
    begin 
             { code to process pMemtable }
    end;
  FINALLY
    pMemTable.AfterPost    := tmpAfterPost;   
    pMemTable.AfterDelete  := tmpAfterDelete;   
  END;    
end;