1

I'm using Dephi 10.1 Berlin and Access 2013.

My problem is related to TADODataSet.Cancel().

I want to show my user a message box asking for a confirmation before posting, in case data has been modified.

In the TADODataSet.BeforePost event, I added the following code:

if Application.MessageBox('Save changes?', '', 52) = idNo then
    ADODataSet1.Cancel;

If the user click on btnNo, something unexpected happens.

Changes are canceled from the current record, but a new record with all fields empty is created.

The only field with some data is the one that was previously modified by the user.

If I cancel the modification via the cancel button of TDBNavigator, everything is fine.

If I simulate a click of the Cancel button of the TDBNnavigator in the BeforePost event:

if Application.MessageBox('Save changes?', '', 52) = idNo then
  DBNavigator1.BtnClick(nbCancel);

I have the same behaviour, so a new empty record is created.

Any suggestion?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Alverio
  • 11
  • 1

1 Answers1

1

The help for TADODataSet.BeforePost says in part:

call Abort to cancel the Post operation (Delphi) or throw an exception (C++).

So:

if Application.MessageBox('Save changes?', '', 52) = idNo then
    abort;

Note this is meant for preventing changes that don't pass validation (the common use for BeforePost) from being posted. It doesn't reset the edit buffers like cancel does. Usually that is a separate function in the UI so the user doesn't have to reenter all the changed data in the edits each time posting is rejected by calling abort in BeforePost.

Brian
  • 6,717
  • 2
  • 23
  • 31
  • With Abort, dataset remains in Edit state and changes are not canceled. With Cancel modifications are canceled and dataset is put in Browse state, so it would be better. I tried this code and it seems to work: if Application.MessageBox('Save changes?', '', 52) = idNo then begin dbnavigator1.BtnClick(nbCancel); Abort; end; In this way dataset goes in Browse state and changes are canceled. Not very elegant actually but it works. – Alverio Nov 03 '20 at 22:10
  • The solution with calling a buttonclick from within the post, and then calling Abort after seems scary. It messes with the flow of events, and I wouldn't be surprised if this works just by accident and will result at some weird, hard to debug behavior at some point. I think it's better to ask the question before you call Post in the first place, although I'm not sure how easy that is with a DBNavigator – GolezTrol Nov 03 '20 at 22:40
  • 1
    At the very least, call `ADODataSet1.Cancel()` instead of `DBNavigator1.BtnClick(nbCancel)`, before calling `Abort()`. And on a side note, don't use [magic numbers](https://en.wikipedia.org/wiki/Magic_number_(programming)). 52 is `MB_YESNO or MB_ICONEXCLAMATION` use that instead so the intent of the code is more readable. I would also suggest using `<> idYes` instead of `= idNo`, in case the message dialog returns a failure: `if Application.MessageBox('Save changes?', '', MB_YESNO or MB_ICONEXCLAMATION) <> IDYES then begin ADODataSet1.Cancel; SysUtil.Abort; end;` – Remy Lebeau Nov 03 '20 at 23:49
  • Thanks a lot to everybody for suggestions and comments. – Alverio Nov 04 '20 at 21:05