简体   繁体   中英

Can Delphi TField.OnValidate restore the original value without raising exception?

I usually implement validation logic as:

procedure TMyDM.IBQueryAMOUNTValidate(
  Sender: TField);
begin
  inherited;
  if Sender.AsFloat>100
    then raise Exception.Create('Amount is too large!');
end;

The question is - is there chance not to raise Exception in the OnValidate (which stops further processing), but to restore silently original value in the OnValidate and proceed with OnChange , CheckBrowseMode and all the GUI updates that are called by the CheckBrowseMode / Post ?

Of course, I know that I can always replace OnValidate logic with OnChange logic that handles OldValue and NewValue but it seems to me that code would be cleaner it I stick with OnValidate .

Don't use OnValidate to do anything apart from raise an exception to reject the Sender 's value.

To see why, set up a simple test app consisting of a TClientDataSet with fields ID (Integer) and Name (String(20)), TDataSource, TDBNavigator, TDBGrid and TDBEdit for the Name field. Add the following code:

procedure TForm1.ClientDataSet1NameValidate(Sender: TField);
begin
  if Sender.AsString = 'x' then
    Sender.DataSet.Cancel;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ClientDataSet1.CreateDataSet;
  ClientDataSet1.InsertRecord([1, 'a']);
  ClientDataSet1.InsertRecord([2, 'b']);
  ClientDataSet1.InsertRecord([3, 'c']);
end;

Compile, run, and enter 'x' (without the quotes) into the DBEdit. Then click Save on the DBNavigator.

Notice that the edit is cancelled but the 'x' remains in the DBEdit. This is in Delphi 10.2.3, btw. Back in D7 days, it was even worse - the wrong row in the DB grid would show the 'x'!

The other thing is that OnValidate is never actually called in TDataSet's methods, only descendants, eg TClientDataSet. So there is no guarantee that in general OnValidate will be called at all or at the right time - it's up to the dataset-type's author to get it right.

So I think the answer to your q is "No", leave the OnValidate to raise exceptions but no more.

It seems to me, the only purpose of OnValidate event is raising exceptions. From Delphi help ( http://docwiki.embarcadero.com/Libraries/Berlin/en/Data.DB.TField.OnValidate ):

To reject the current value of the field from the OnValidate event handler, raise an exception ...
If writing the data does not raise an exception, the OnChange event handler is called to allow a response to the change.

For tasks of validation I use OnSetText event, which gives me possibility to silent restore original value if new one is not acceptable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM