JRG
JRG

Reputation: 593

How to assign TFDMemtable AfterPost and AfterDelete events on runtime?

I have a DataModule shared by several forms and in that I built a procedure to processing a TFDMemtable passed as parameter. In order to process it I must to disable the events AfterPost and AfterDelete and when conclude processing I have to enable them back. I'm not suceeding in enable them back, because I can't get the actual name of these events in a form "actualnameAfterpost".

I've tried :

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

This is the main code :

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;

Thanks all !

Upvotes: 0

Views: 462

Answers (2)

Ilyes
Ilyes

Reputation: 14928

You need just to write your procedures and then assign them as

...
  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;

Here is a simple sample to help you understand, just run it and see what's happening

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.

Finally, I suggest to visit those pages and read them:

Upvotes: 2

Tom Brunberg
Tom Brunberg

Reputation: 21045

Both events are of type TDataSetNotifyEvent. Use two local variables of this type to hold the events temporarily.

To disable the events, save them to the temporary variables and then nil them. After you have done the manipulation restore the actual events from the temporary vars.

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;

Upvotes: 4

Related Questions