Assigning TDatasetNotifyEvent

I have many TTable components in my app and I want all(actually, most) of them to have the same common BeforeDelete event handler (A custom "are you sure" MessageDlg).

I tried to create a procedure:
Procedure CommonBeforeDelete(DataSet : TDataSet);

This has the same prototype as TDataSetNotifyEvent.
I declared that proc in a commonly used unit.

Each time my app starts it runs a loop which opens any TTable it finds, I tried to assign the "BeforeDelete" event to that proc - but it won't compile.
I also tried declaring a variable as TDataSetNotifyEvent and make it point to that proc, but it won't go as well.

How do I do it?
Is there a better way to make a common data-aware delete confirmation?
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

simonetConnect With a Mentor Commented:
>I'm not sure if that has to do
>with "implicit parameters" per se...?

Yes, it does.

One thing is a simple procedure, that doesn't belong to any class. Example:

procedure Sing;

Another completely different thing is a class procedurem this is defined as:

  TMyProcedure = procedure (parameters : paramtypes) of object;

Class procedures have an implicit parameter (not seen through in the actual code or in the tooltips) that is the object to which the procedure belongs.

Therefore simple procedures and class procedures cannot be assigned to each other.

Notice that by doing what I suggested, idok's program will work fine, because at the moment the procedure was put inside the form's class declaration, it started being a class procedure, therefore assigneable to any other class procedure variable.

I tested the code and it worked.

>If you care to comment on that for no

Ok. EE suggests that questions are graded 50 points for easy questions, 100 for medium and 200 for hard questions. Thus, by assigning your question less than 50 points you are stating 2 things:

1) Your question is very, very easy (which is not the case here)

2) You don't consider your question to be very relevant and you don't mind if it is not answered inmmediatly (I gave idok a correct answer only 24 minutes after the question was posted, which is much better than any paid support he could have).

It's important to note that the higher the amount of points you assign to a question, the better the chances are that your question will draw more attention from the best experts and that it will receive more and better attention from them (note that not too many - you and me - experts cared about this question, because it was a low-pointer).

Common sense is the most important thing when assigning points to your question. I suggest you "feel" what it is like around here first, observe the relation Points Assigned X Time of Answer/Comments. There is a direct relation.

200 is not the ceiling either. If you have a very, very important question and you want to have all the experts try to help you out, you are free to assign as many points as you have.



There is a large difference between the function you're defining and the one you are trying to pass to the TTable.

The TTable's OnBeforeDelete methods requires "CLASS PROCEDURE", which has an implicit parameter that cannot be declared when defining simple procedures.

The solution for that is to create a common BeforeDelete procedure, but make it on the public section of your main form or on the main TDataModule (if any). By doing so, you won't have to create a class that will be only a placeholder for the common procs.

Putting in code what I just said, take a look at this:

  TFrmMain = class(TForm)
    Table1: TTable;
    Table2: TTable;
    Table3: TTable;
    procedure FormCreate(Sender: TObject);
    { Private declarations }
        procedure CommonBeforeDelete(DataSet: TDataSet);
    { Public declarations }

  FrmMain: TFrmMain;


uses Unit2;

{$R *.DFM}

procedure TFrmMain.CommonBeforeDelete(DataSet: TDataSet);
      Resp := application.messagebox('Are you sure you want to delete this record?', pchar(application.title), MB_ICONQUESTION + MB_YESNO);
  if Resp=IDNO then abort;

procedure TFrmMain.FormCreate(Sender: TObject);
   Table1.BeforeDelete := CommonBeforeDelete;
   Table2.BeforeDelete := CommonBeforeDelete;
   Table3.BeforeDelete := CommonBeforeDelete;
  Form2.Table1.BeforeDelete := CommonBeforeDelete;


The above could also be done using the ObjectInspector.



idokAuthor Commented:
What's the difference between the proposed code and what I am doing?

Why does a "class procedure" has to be a public member of some form?
Is there a way to override this behavior?

You see, I still have a problem since my app uses (Delphi 5) frames (and no data modules) and I have my tables on many different frames and one common unit with general-purpose application-related procedures.

Each frame which gets focus calls the common "OpenAllTablesOnFrame" procedure in the common unit which does the loop I described before.

Any ideas?

Thanks for your help, Alex.
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

For only 40 points, the answer I gave you is pretty good.

If you want further explanation on how class methods, implicit parameters, unit dependency, etc, work, increase the points.

idokAuthor Commented:
How much you want?
Actually, Simonet, I'm not sure if that has to do with "implicit parameters" per se...?

And BTW, since I am thinking of asking a question myself, are there any guidelines for how many points to offer? Official ex-ex documentation, general consensus that has developed among the user community, something else...? Or should one just take a shot, offer 100 or something, and increase it if people say it's too low?

(If you care to comment on that for no points?  :-)

Christian R. Conrad
idokAuthor Commented:
Ok, Alex. Thanks for your help.
I'll put the common BeforeDelete in the main form. All the frames uses that unit anyway (I think).

All Courses

From novice to tech pro — start learning today.