Delphi TField.OnValidate是否可以在不引发异常的情况下恢复原始值?

时间:2018-10-18 08:25:06

标签: delphi delphi-2009

我通常将验证逻辑实现为:

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

问题是-是否有机会不在Exception中引发OnValidate(这将停止进一步处理),而是默默地恢复OnValidate中的原始值并继续进行{{ 1}},OnChangeCheckBrowseMode / CheckBrowseMode调用的所有GUI更新?

当然,我知道我总是可以用处理PostOnValidate的{​​{1}}逻辑替换OnChange逻辑,但是在我看来,代码会更干净我坚持使用OldValue

2 个答案:

答案 0 :(得分:4)

除了引发异常以拒绝该请求外,请勿使用OnValidate做任何事情 Sender的值。

要了解原因,请设置一个简单的测试应用,该应用由TClientDataSet组成,其中的ID为(Integer)和Name(String(20)),TDataSource, 名称字段的TDBNavigator,TDBGrid和TDBEdit。添加以下代码:

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;

编译,运行并将“ x”(不带引号)输入DBEdit。然后在DBNavigator上单击“保存”。

请注意,已取消编辑,但“ x”保留在DBEdit中。这是 在Delphi 10.2.3中,顺便说一句。过去D7天,情况甚至更糟-错误的排 数据库网格将显示“ x”!

另一件事是,OnValidate实际上从未在TDataSet的方法中调用, 仅后裔,例如TClientDataSet。因此,我们无法保证 OnValidate会全部或在正确的时间被调用-取决于数据集类型的作者来正确设置。

因此,我认为您的q的答案是“否”,请保留OnValidate引发异常,但不再更多。

答案 1 :(得分:2)

在我看来,OnValidate事件的唯一目的是引发异常。在Delphi帮助(http://docwiki.embarcadero.com/Libraries/Berlin/en/Data.DB.TField.OnValidate)中:

  

拒绝OnValidate事件中字段的当前值   处理程序,引发异常   ...
  如果写入数据没有引发   例外,调用OnChange事件处理程序以允许响应   更改。

对于验证任务,我使用OnSetText事件,这使我有可能在不接受新值的情况下静默恢复原始值。