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
中静默恢复原始值并继续OnChange
、CheckBrowseMode
和CheckBrowseMode
/Post
调用的所有GUI更新?
当然,我知道我总是可以用处理OldValue
和NewValue
的OnChange
逻辑替换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 可以在不引发异常的情况下恢复原始值吗?的主要内容,如果未能解决你的问题,请参考以下文章