Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 如何防止用户离开DBGrid';s单元取决于它';s值_Delphi_Validation_Delphi 7_Tclientdataset_Dbgrid - Fatal编程技术网

Delphi 如何防止用户离开DBGrid';s单元取决于它';s值

Delphi 如何防止用户离开DBGrid';s单元取决于它';s值,delphi,validation,delphi-7,tclientdataset,dbgrid,Delphi,Validation,Delphi 7,Tclientdataset,Dbgrid,我的情况如下: 我有一个任务,需要使用TClientDataSet进行一些操作(是的,我必须使用这个特定组件)。用户将能够编辑TClientDataSet内的数据,因此我使用连接到TDataSource的TDBGrid,它连接到我的TClientDataSet 我需要做的是根据单元格的值防止用户离开单元格(将焦点移动到程序中的其他位置)。有效值是从00:00到23:59的时间。它不能为空或具有空字符。我正在使用TClientDataSet字段的EditMask属性,因此很容易以正确的格式直接键入

我的情况如下: 我有一个任务,需要使用TClientDataSet进行一些操作(是的,我必须使用这个特定组件)。用户将能够编辑TClientDataSet内的数据,因此我使用连接到TDataSource的TDBGrid,它连接到我的TClientDataSet

我需要做的是根据单元格的值防止用户离开单元格(将焦点移动到程序中的其他位置)。有效值是从00:00到23:59的时间。它不能为空或具有空字符。我正在使用TClientDataSet字段的EditMask属性,因此很容易以正确的格式直接键入

例如: 如果用户在单元格中键入29:00,然后尝试移动到另一个单元格(或另一个组件),我希望能够停止该操作,并让他在单元格中输入其他有效值(如15:00),然后他可以离开该单元格并执行其他操作(如编辑另一个单元格)

进行此类验证的选项有哪些?我用的是Borland Delphi 7

谢谢

使用事件。在验证
EditMask
之后,但在数据实际写入记录缓冲区之前,调用此函数。这允许您在完成基本字符验证后执行更广泛的验证

该事件接收
发送方
参数中验证的字段,该参数为
TFieldNotifyEvent

TFieldNotifyEvent = procedure(Sender: TField) of Object;
您可以执行在该事件中验证数据所需的操作,并在新值不满足时间跨度要求时引发异常。例如,如果字段中输入的字符少于2个,则以下内容将引发异常:

procedure TForm4.ClientDataSet1ClientDataSet1Field1Validate(Sender: TField);
begin
  if not (Length(Trim(Sender.AsString)) > 1) then
    raise Exception.Create('Invalid length for field content.');
end;
另一种方法是使用事件,但我更喜欢将数据验证代码与数据库内容更直接地结合起来,而不是将其绑定到用户界面的特定部分。(将其保留在数据库中,即使您以后改变主意,从使用网格切换到使用单独的表单进行记录维护,或者从代码而不是UI设置字段值,也会自动强制执行。)

就实际验证数据本身而言,最简单的方法是使用您正在使用的Delphi版本中提供的数据。类似这样的表达式应该可以工作:

var
  FoundMatch: Boolean;
  TimeStr: string;
begin
  TimeStr := Sender.AsString;
  FoundMatch := TRegEx.IsMatch(TimeStr,
        '\A([0-1][0-9]|[2][0-3]):[0-5][0-9]\z', [roMultiLine]);
  if not FoundMatch then
    raise Exception.CreateFmt('Invalid time value %s', [TimeStr]);
end;
如果您的Delphi版本中没有
TRegEx
,您可以在网站上找到免费的开源
TPerlRegEx
;它是当前Delphi版本中用于正则表达式支持核心的代码。在这种情况下,此代码也应起作用:

var
    Regex: TPerlRegEx;
    FoundMatch: Boolean;
    TimeStr: string;
begin
  TimeStr := Sender.AsString;
  Regex := TPerlRegEx.Create;
  try
    Regex.RegEx := '\A([0-1][0-9]|[2][0-3]):[0-5][0-9]\z';
    Regex.State := [preNotEmpty];
    Regex.Subject := TimeStr;
    FoundMatch := Regex.Match;
    if not FoundMatch then
      raise Exception.CreateFmt('Invalid time value %s', [TimeStr]);
  finally
    Regex.Free;
  end;
end;
使用事件。在验证
EditMask
之后,但在数据实际写入记录缓冲区之前,调用此函数。这允许您在完成基本字符验证后执行更广泛的验证

该事件接收
发送方
参数中验证的字段,该参数为
TFieldNotifyEvent

TFieldNotifyEvent = procedure(Sender: TField) of Object;
您可以执行在该事件中验证数据所需的操作,并在新值不满足时间跨度要求时引发异常。例如,如果字段中输入的字符少于2个,则以下内容将引发异常:

procedure TForm4.ClientDataSet1ClientDataSet1Field1Validate(Sender: TField);
begin
  if not (Length(Trim(Sender.AsString)) > 1) then
    raise Exception.Create('Invalid length for field content.');
end;
另一种方法是使用事件,但我更喜欢将数据验证代码与数据库内容更直接地结合起来,而不是将其绑定到用户界面的特定部分。(将其保留在数据库中,即使您以后改变主意,从使用网格切换到使用单独的表单进行记录维护,或者从代码而不是UI设置字段值,也会自动强制执行。)

就实际验证数据本身而言,最简单的方法是使用您正在使用的Delphi版本中提供的数据。类似这样的表达式应该可以工作:

var
  FoundMatch: Boolean;
  TimeStr: string;
begin
  TimeStr := Sender.AsString;
  FoundMatch := TRegEx.IsMatch(TimeStr,
        '\A([0-1][0-9]|[2][0-3]):[0-5][0-9]\z', [roMultiLine]);
  if not FoundMatch then
    raise Exception.CreateFmt('Invalid time value %s', [TimeStr]);
end;
如果您的Delphi版本中没有
TRegEx
,您可以在网站上找到免费的开源
TPerlRegEx
;它是当前Delphi版本中用于正则表达式支持核心的代码。在这种情况下,此代码也应起作用:

var
    Regex: TPerlRegEx;
    FoundMatch: Boolean;
    TimeStr: string;
begin
  TimeStr := Sender.AsString;
  Regex := TPerlRegEx.Create;
  try
    Regex.RegEx := '\A([0-1][0-9]|[2][0-3]):[0-5][0-9]\z';
    Regex.State := [preNotEmpty];
    Regex.Subject := TimeStr;
    FoundMatch := Regex.Match;
    if not FoundMatch then
      raise Exception.CreateFmt('Invalid time value %s', [TimeStr]);
  finally
    Regex.Free;
  end;
end;

我用使用OnValidate方法创建的代码编辑了我的问题。它不会引发一个简单的“测试”异常。也许我没有正确处理异常。我是否必须添加任何其他代码才能真正实现我想要的预防,或者仅仅引发该异常就可以停止用户执行的任何其他操作?如果字段上有EditMask,则
Length
将永远不会<1。您需要使用
长度(Trim(Sender.AsString))
。请参阅我的编辑。(显示使用正则表达式进行验证示例的代码也将直接插入该事件处理程序。)引发异常会阻止存储字段内容。您必须编写代码来验证时间是否在允许的范围内,如果不在允许的范围内,则引发异常;regex示例也演示了这样做。因为您已经在标题中添加了Delphi7,所以您需要我链接的TPerlRegEx;是的,但不幸的是我使用的是Delphi 7,所以我不能使用正则表达式(而且我认为外部库不能很好地适应任务上下文(它基本上只是一个测试))。我用使用OnValidate方法创建的代码编辑了我的问题。它不会引发一个简单的“测试”异常。也许我没有正确处理异常。我是否必须添加任何其他代码才能真正实现我想要的预防,或者仅仅引发该异常就可以停止用户执行的任何其他操作?如果字段上有EditMask,则
Length
将永远不会<1。您需要使用
长度(Trim(Sender.AsString))
。请参阅我的编辑。(显示使用正则表达式进行验证示例的代码也将直接插入该事件处理程序中。)引发异常可防止