我通常将验证逻辑实现为:
procedure TMyDM.IBQueryAMOUNTValidate(
Sender: TField);
begin
inherited;
if Sender.AsFloat>100
then raise Exception.Create('Amount is too large!');
end;
问题是-是否有机会不在Exception
中引发OnValidate
(这将停止进一步处理),而是默默地恢复OnValidate
中的原始值并继续进行{{ 1}},OnChange
和CheckBrowseMode
/ CheckBrowseMode
调用的所有GUI更新?
当然,我知道我总是可以用处理Post
和OnValidate
的{{1}}逻辑替换OnChange
逻辑,但是在我看来,代码会更干净我坚持使用OldValue
。
答案 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
事件,这使我有可能在不接受新值的情况下静默恢复原始值。