Delphi DBgrid撤消更改错误更新

时间:2016-09-23 08:18:11

标签: delphi datasource

我的代码中对我的数据源的datachange的编辑值进行了验证:

procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);
var
sIDin :string;
Continue                :boolean;
begin
    Continue := True;
    if (Table1.RecordCount <> 0 )and (Field <> Nil) then
    begin
        //////////
        if (Field.Text = '') then //(1)
        begin
             Application.MessageBox('is Empty!','',MB_OK + MB_ICONWARNING);
             Continue := false;
        end
        else if (Field.FieldName <> 'GaName') and  (Field.FieldName <> 'MnName' )then
        begin
             sIDin := '$0' + Field.Text;
             if not TryStrToInt64(sIDin) then
             begin
                  Application.MessageBox('Not Hexadecimal!', '',MB_OK + MB_ICONWARNING);
                  Continue := false;
                  //Field.Text := ''; // here i need to set  my filed empty not with wrong value. 
                  // So i use this line .. 
                  // but it generate an error (1)
             end;
        end;
        if Not(Continue) then
            abort
    end;
    inherited ;

end;

在这种情况下输入不验证数据时我需要撤消更改:

if not TryStrToInt64(sIDin) then
begin
      Application.MessageBox('Not Hexadecimal!', '',MB_OK + MB_ICONWARNING);
      Continue := false;
end;

当我输入非十六进制值(&#39; NONEHexa&#39;)时,我需要忽略我的数据集中的这个值。 我尝试使用空Field.Text := ''设置我的字段,但是当我的字段为空时会产生其他错误。

我怎么能这样做?

============ Update1

我的函数TryStrToInt64:

    function TryStrToInt64(InputString : string) : boolean ;
    var
    iValue64          :Int64;
    begin
            try
                    iValue64 := StrToInt64(InputString);
            Except
                    on E : EConvertError  do
                    begin
                            Result:= false;
                            exit;
                    end;
            end;
            Result:=true;
    end;

1 个答案:

答案 0 :(得分:2)

您可以尝试将字段值转换为整数,而不是尝试将字段值转换为整数 测试它的每个字符是否在十六进制字符串中有效,如下所示:

function ValidHex(Input : String) : Boolean;
var
  i : Integer;
begin
  Result := False;
  //  If Input is empty, it can't be valid Hex
  if Input = '' then exit;

  //  Valid Hex must have an even number of characters
  if Odd(Length(Input)) then exit;

  for i := 1 to Length(Input) do
    if not (CharInSet(Input[i], ['0'..'9', 'A'..'F', 'a'..'f'])) then
      exit;
  Result := True;
end;

当然,您可以使用HexToBin库函数将Hex字符串转换为二进制值,并检查字符串中的所有字符是否都在此过程中使用。

关于代码的三件事:

  1. 不是尝试在数据源的OnDataChange事件中进行验证,而是最好在字段&#39; s { {1}}事件,用于执行此类验证。有关详细信息,请参阅在线帮助。

  2. 您可以使用字段的OnValidate属性来限制可以输入的字符。再次,请参阅OLH。我不认为您可以使用EditMask将输入限制为十六进制字符。

  3. 您最好避免使用EditMask作为变量。它对编译器有特殊意义,与Continue循环的执行有关。再次,请参阅OLH

  4. 更新

      

    我试试,但我可以看到如何确保使用TField OnValidate进行验证..你能给出一个例子!..其他问题:当我使用OnValidate for field时,可以在某些字段上更新UNDO #39;是假的?示例:当我输入非十六进制值时,我的字段应该回滚而不接受此值。在我的情况下,我可以在DataChange事件上得到此错误。但在此之前,当我点击其他行时,错误的值似乎保存在我的数据库中!

    保存了错误的值,因为当您对当前行有未保存的更改时单击另一个网格行时,将自动保存该更改 - 这是Delphi数据集的标准行为。

    如果要将字段值恢复为用户更改前的字段值,最简单的方法是使用数据源的OnDataChange事件而不是字段的OnValidate。以下对for的调用将还原字段的值:

    Field.DataSet.Cancel

    但请注意,这会将任何其他未保存的更改还原到同一行。为了能够仅将更改还原为&#34; hex&#34;字段会更复杂 - 我认为您必须在某处保存其他更改的值,并在调用procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField); begin if Field = Nil then Exit; // First, check that the Field is the one we're interested in if Field = Field.DataSet.FieldByName('Value') then begin if not ValidHex(Field.AsString) then begin ShowMessageFmt('Invalid value: %s for field: %s', [Field.AsString, Field.FieldName]); Field.DataSet.Cancel; end; end; end; 后恢复它们。