避免调用重复验证

Avoid calling duplication for validation

我有点卡住了。我的目标是始终检查和验证我的货币字段,当它的值发生变化时,不管是从内联代码还是从用户界面。是否有任何验证模式或样本?我想避免调用我的验证程序两次。

如有任何帮助或建议,我们将不胜感激。

这是我的例子:

type
TMyForm = class(TForm)   
  ceMyCurrencyEdit: TcxCurrencyEdit;
  procedure FormShow(Sender: TObject);
private
{ Private declarations }
  procedure SetupMyForm;
public
{ Public declarations }
  procedure ValidateMyCurrencyValue;
  function IsValidCurrency: Boolean;
end; 

procedure TMyForm.ValidateMyCurrencyField;
begin
  if not IsValidCurrency then
  begin
    WarningDlg(
       Format(
           'InValid value in field: [%s..%s]',
           [Formatfloat(ceMyCurrencyEditDisplayFormat, ceMyCurrencyEdit.MinValue),
           Formatfloat(ceMyCurrencyEdit.DisplayFormat, ceMyCurrencyEdit.MaxValue)]
        )
    );
    ceMyCurrencyEdit.Value := ceMyCurrencyEdit.MinValue; 
  end;   
end;

function TMyForm.IsValidCurrency: Boolean;
begin
  Result := (ceMyCurrencyEdit.Value >= ceMyCurrencyEdit.MinValue) and (ceMyCurrencyEdit.Value <= ceMyCurrencyEdit.MaxValue);  
end;

procedure TMyForm.SetupMyForm;
begin
  //MaxValue is 100
  ceMyCurrencyEdit.Value := 102;
  //At this point I need to call ValidateMyCurrencyField to get warning msg and refuse its value
  ValidateMyCurrencyField;
end;

procedure TMyForm.FormShow(Sender: TObject);
begin
  SetupMyForm;
end;

procedure TMyForm.ceMyCurrencyEditPropertiesEditValueChanged(Sender: TObject);
begin
  ValidateMyCurrencyField;
end;

我想要的是...

感谢您的回答!

我不确定为什么你似乎有点不屑一顾 os @Nil 的建议,但在下面 是一个示例项目,它显示了使用 cxCurrencyEdit 的验证工具 并使用 interposer TcxCurrencyEdit class 记录验证结果 在其 ValidationState 属性.

中处理

显然你可以使用 ValidationState 属性 来避免重复 你的验证过程,或者如果国家说它是有效的,就真的这样做。 但是,就性能而言,我非常怀疑您是否会自救 任何东西。

很明显,interposer class的重点是记录验证状态 控件,这样您就可以避免对其进行第二次验证。是否与 cxCurrencyEdit1PropertiesValidate 事件结合使用完全取决于您。

我让你将它与你现有的代码结合起来。

顺便说一句,TEdit 控件就在那里允许焦点从 cxCurrencyEdit 转移到触发它的 cxCurrencyEdit1PropertiesValidate 事件。

更新您在评论中询问了验证代码中设置的值。和 一个 interposer class,很容易为值 属性 添加一个 Getter 和 Setter 并在 Setter 中进行验证 - 请参阅下面的 `SetValue,

  type
    TCurrencyValidation = (cvNotDone, cvOK, cvInvalid);

    TcxCurrencyEdit = class(cxCurrencyEdit.TcxCurrencyEdit)
    private
      FValidationState : TCurrencyValidation;
      function GetValue: Double;
      procedure SetValue(const AValue: Double);
    protected
      property ValidationState : TCurrencyValidation read FValidationState write FValidationState;
    published
      property Value : Double read GetValue write SetValue;
    end;

    TForm1 = class(TForm)
      cxCurrencyEdit1: TcxCurrencyEdit;
      Edit1: TEdit;
      procedure FormCreate(Sender: TObject);
      procedure cxCurrencyEdit1PropertiesChange(Sender: TObject);
      procedure cxCurrencyEdit1PropertiesValidate(Sender: TObject;
        var DisplayValue: Variant; var ErrorText: TCaption;
        var Error: Boolean);
    end;

  procedure TForm1.FormCreate(Sender: TObject);
  begin
    cxCurrencyEdit1.Properties.MinValue := 5;
    cxCurrencyEdit1.Properties.MaxValue := 10;
    cxCurrencyEdit1.Value := 8;
  end;

  procedure TForm1.cxCurrencyEdit1PropertiesChange(Sender: TObject);
  begin
    TcxCurrencyEdit(Sender).ValidationState := cvNotDone;
  end;

  procedure TForm1.cxCurrencyEdit1PropertiesValidate(Sender: TObject;
    var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean);
  var
    Min,
    Max : Double;
  begin
    Min := TcxCurrencyEdit(Sender).Properties.MinValue;
    Max := TcxCurrencyEdit(Sender).Properties.MaxValue;
    if (DisplayValue >= Min) and (DisplayValue <= Max) then
      TcxCurrencyEdit(Sender).ValidationState := cvOK
    else
      TcxCurrencyEdit(Sender).ValidationState := cvInvalid;
    Error := not (TcxCurrencyEdit(Sender).ValidationState = cvOK);
    if Error then
      ErrorText := 'InvalidValue';
  end;

  function TcxCurrencyEdit.GetValue: Double;
  begin
    Result := inherited Value;
  end;

  procedure TcxCurrencyEdit.SetValue(const AValue: Double);
  begin
    //  insert code to validate AValue here
    inherited Value := AValue;
  end;