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

Posted

技术标签:

【中文标题】Delphi TField.OnValidate 可以在不引发异常的情况下恢复原始值吗?【英文标题】:Can Delphi TField.OnValidate restore the original value without raising exception? 【发布时间】:2019-03-23 00:27:27 【问题描述】:

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

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

问题是 - 是否有机会不在OnValidate 中提出Exception(这会停止进一步处理),而是在OnValidate 中静默恢复原始值并继续OnChangeCheckBrowseModeCheckBrowseMode/Post调用的所有GUI更新?

当然,我知道我总是可以用处理OldValueNewValueOnChange 逻辑替换OnValidate 逻辑,但在我看来,如果我坚持使用OnValidate,代码会更简洁。

【问题讨论】:

【参考方案1】:

除了引发异常以拒绝 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 中。这是 在德尔福 10.2.3 中,顺便说一句。早在 D7 天,情况就更糟了 - 错误的行 数据库网格将显示“x”!

另一件事是OnValidate 从未在 TDataSet 的方法中实际调用过, 只有后代,例如TClient 数据集。所以一般情况下不能保证 OnValidate 将被完全调用或在正确的时间调用 - 由数据集类型的作者决定是否正确。

所以我认为您的 q 的答案是“否”,让 OnValidate 引发异常,但仅此而已。

【讨论】:

【参考方案2】:

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

从 OnValidate 事件中拒绝字段的当前值 处理程序,引发异常 ... 如果写入数据不会引发 异常,调用 OnChange 事件处理程序以允许响应 变化。

对于验证任务,我使用OnSetText 事件,如果不接受新值,我可以静默恢复原始值。

【讨论】:

请记住,在不使用 DBware 控件的情况下,将值直接分配给字段时不会触发 OnSetText @AnselmoMS,是的,应该考虑在内。

以上是关于Delphi TField.OnValidate 可以在不引发异常的情况下恢复原始值吗?的主要内容,如果未能解决你的问题,请参考以下文章

TField OnValidate 事件

delphi10和delphi2010区别

delphi编程

如何安装Delphi5

通过delphi执行DOS??

delphi 2010 编译乱码问题