我通常将验证逻辑实现为:
procedure TMyDM.IBQueryAMOUNTValidate(
Sender: TField);
begin
inherited;
if Sender.AsFloat>100
then raise Exception.Create('Amount is too large!');
end;问题是,是否有可能不在OnValidate中引发OnValidate(这将停止进一步的处理),而是恢复OnValidate中的原始值,并继续执行CheckBrowseMode/Post调用的OnChange、CheckBrowseMode和所有GUI更新。
当然,我知道我可以将OnValidate逻辑替换为处理OldValue和NewValue的OnChange逻辑,但在我看来,代码会更干净--我坚持使用OnValidate。
发布于 2018-10-18 13:28:10
除了引发异常以拒绝Sender的值之外,不要使用Sender来做任何事情。
要了解原因,请设置一个简单的测试应用程序,该应用程序由一个包含字段ID (Integer)和名称(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;在DBEdit中编译、运行并输入'x‘(没有引号)。然后单击DBNavigator上的Save。
请注意,编辑已被取消,但'x‘仍保留在DBEdit中。这是德尔菲10.2.3,顺便说一句。在D7时代,情况甚至更糟-- DB网格中的错误行会显示'x'!
另一件事是,在TDataSet的方法中从未真正调用OnValidate,只有后代,例如TClientDataSet。因此,通常不能保证在任何时候调用OnValidate --这取决于dataset类型的作者是否正确。
所以我认为你的问题的答案是“不”,离开OnValidate来引发例外,但不会有更多。
发布于 2018-10-18 12:48:54
在我看来,OnValidate事件的唯一目的是引发异常。来自Delphi (http://docwiki.embarcadero.com/Libraries/Berlin/en/Data.DB.TField.OnValidate):
若要从OnValidate事件处理程序拒绝字段的当前值,请引发异常. 如果写入数据不会引发异常,则调用OnChange事件处理程序以允许对更改作出响应。
对于验证任务,我使用OnSetText事件,这使我有可能在新的值不可接受的情况下无声地恢复原始值。
https://stackoverflow.com/questions/52869890
复制相似问题