对 cxGrid 执行行级数据合法性校验(原创)

如果在 cxGrid 中的数据列的 OnValidate 事件中写入代码,执行的是字段级别的合法性校验,这种方法的优点是:强校验,当输入焦点移出指定列时就对该列进行合法性校验(当 cxGrid 控件失去焦点时也会触发),强制用户纠正非法数据;但同时也有弊端,就是在该列尚未输入数据时删除行(Unbound模式),也会先执行数据校验,会因缺少合法数据而跳出提示框,比较烦人。

另一种方案是进行 级别的数据校验,在 BeforePost 事件中对整行数据中的关键列进行合法性校验。需要注意的是,如果直接在 BeforePost 事件中写入校验代码,对 cxGrid 的可视性属性进行设置,很容易导致 cxGrid 花屏,最好的办法是发送自定义消息,在消息响应函数中对可视性属性进行设置。

const
  CM_COLUMN_ERROR = WM_USER + 1;

type
  TfrmAddOrder = class(TForm)
    procedure OnInvalidColumn(var Msg: TMessage); message CM_COLUMN_ERROR;
    function DoValidate: Boolean;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

procedure TfrmAddOrder.OnInvalidColumn(var Msg: TMessage);
begin
  if Msg.WParam = clCaption.Index then
    cxMsgDlg('必须输入品名!', mtError, [mbYes], mbYes)
  else if Msg.WParam = clPrice.Index then
    cxMsgDlg('必须输入价格!', mtError, [mbYes], mbYes)
  else if Msg.WParam = clNumber.Index then
    cxMsgDlg('必须输入数量!', mtError, [mbYes], mbYes)
  else
    exit;

  cxGridAddOrder.SetFocus;
  // 将输入焦点移动到非法数据所在列,需要配合 AlwaysShowEditor 属性
  cvAddOrder.Controller.FocusedColumnIndex := Msg.WParam;
  // 指定列获得焦点后自动进入编辑状态,如果为 False,则只显示焦点框
  // cvAddOrder.OptionsBehavior.AlwaysShowEditor := True;
end;

// 对指定列进行检验,全部合格返回 True
function TfrmAddOrder.DoValidate: Boolean;
var
  iRecord: Integer;
  val: Variant;
begin
  iRecord := cvAddOrder.DataController.FocusedRecordIndex;
  Result := False;

  val := cvAddOrder.DataController.Values[iRecord, clCaption.Index];
  if VarIsNull(val) and (iRecord <> -1) then begin
    PostMessage(Handle, CM_COLUMN_ERROR, Integer(clCaption.Index), 0);
    Exit;
  end;

  val := cvAddOrder.DataController.Values[iRecord, clPrice.Index];
  if VarIsNull(val) and (iRecord <> -1) then begin
    PostMessage(Handle, CM_COLUMN_ERROR, Integer(clPrice.Index), 0);
    Exit;
  end;

  val := cvAddOrder.DataController.Values[iRecord, clNumber.Index];
  if VarIsNull(val) and (iRecord <> -1) then begin
    PostMessage(Handle, CM_COLUMN_ERROR, Integer(clNumber.Index), 0);
    Exit;
  end;
  Result := True;
end;

procedure TfrmAddOrder.cvAddOrderDataControllerBeforePost(
  ADataController: TcxCustomDataController);
begin
  if not DoValidate then Abort;
end;
posted @ 2024-08-31 09:10  汉学  阅读(10)  评论(0)    收藏  举报