【问题标题】:Prevent date mismatch防止日期不匹配
【发布时间】:2013-04-03 06:20:42
【问题描述】:
我正在使用 cxGrid,其中有两个日期字段(start_date 和 end_date),它们从查询中获取结果。我试图防止用户在网格中输入数据时输入错误的日期范围。我试图阻止用户输入低于 start_date 的 end_date。我试过了:
procedure TForm1.ABSQuery1BeforePost(DataSet: TDataSet);
begin
if (ABSQuery1.FieldByName('end_DATE').AsDateTime < ABSQuery1.FieldByName('start_DATE').AsDateTime) then
showmessage('end date cant be lower than start date ');
ABSQuery1.Cancel;
end;
我收到错误:数据集未处于插入或编辑模式。我该如何解决这个问题,或者有更好的方法吗?
【问题讨论】:
标签:
delphi
devexpress
delphi-xe2
delphi-xe
【解决方案1】:
您的代码错误:您在 if 构造中调用了 Cancel,因此您也为有效记录调用它,但不要在验证例程中调用 Cancel 方法。
在这种情况下,cxGrid 负责数据集的编辑,所以如果你真的想防止你的用户输入错误的日期:
如果您发现某些内容无法验证,则该合同将引发异常,因此您可以将代码更改为以下内容:
procedure TForm1.ABSQuery1BeforePost(DataSet: TDataSet);
begin
if (ABSQuery1.FieldByName('end_DATE').AsDateTime < ABSQuery1.FieldByName('start_DATE').AsDateTime) then
raise Exception.Create('end date can''t be lower than start date');
end;
如果你定义自己的 Exception 类来避免引发(太)通用的 Exception 实例会更好,例如:
type
EInputValidationError = class(Exception)
end;
procedure TForm1.ABSQuery1BeforePost(DataSet: TDataSet);
begin
if (ABSQuery1.FieldByName('end_DATE').AsDateTime < ABSQuery1.FieldByName('start_DATE').AsDateTime) then
raise EInputValidationError.Create('end date can''t be lower than start date');
end;
这样,将来您可以将输入验证错误与程序中引发的其他类型的异常区分开来。
【解决方案2】:
我更喜欢使用 end_date 和 start_date 字段的 OnValidate,因为这将在设置字段值时引发,这将在发布之前很久发生。如果必须输入很多字段,这可能会很有趣,例如用户在发布时在第三个选项卡上进行编辑,而日期的输入在第一个选项卡上。
procedure TForm5.DateSpanValidateValidate(Sender: TField);
begin
if not Sender.DataSet.FieldByName('end_DATE')
.IsNull and not Sender.DataSet.FieldByName('start_DATE').IsNull then
if (Sender.DataSet.FieldByName('end_DATE')
.AsDateTime < Sender.DataSet.FieldByName('start_DATE').AsDateTime) then
raise EYourValidationError.Create(
'end date can''t be lower than start date');
end;