本帖最后由 xuleitz 于 2011-12-05 22:23:09 编辑

解决方案 »

  1.   

    你程序写得事件不对,不应该放在beforepost,所以堆栈溢出。
      

  2.   

    DataSet.Post写到一个按钮或函数中都可以用try exepct 来捕获,不需要写到DataSet的事件中,这样肯定会报错。因为在DataSet.Post的时候你又触发了一次DataSet.Post。你没理解事件的概念。
      

  3.   

    多谢各位,我没有考虑到。现在我是这么做的:procedure TForm1.tbl1BeforePost(DataSet: TDataSet);
    var
      i: Integer;
    begin
      tbl1.BeforePost := nil;
      try
        try
          DataSet.Post;
        except
          //Do something...
        end;
      finally
        tbl1.BeforePost := tbl1BeforePost;
        Abort;
      end;
    end;又有个小问题:
        Abort会取消所有操作,而如果是按上或下方向键提交更改的,那么当前行并不会改变,而要再按一次方向键才行。所以我想:
        能不能在TDataSet.BeforPost事件中取消cxGrid的更改提交,但又觉得TDataSet.BeforPost事件是由cxGrid引起的,根本无法影响cxGrid的此次行为。那就只能在cxGrid上想办法了,但又找不到引发TDataSet.BeforPost事件的cxGrid的事件。所以如我一开始所说的“实现对用户输入的验证”不知道怎么实现才好。
      

  4.   

    执行Post的话是会先执行beforpost的,所以你写的代码就造成了循环,就会出错。解决办法,5楼的可行。另外,你不用 try..except.. //异常处理的代码...  end;
    这样写,你可以,在save的地方直接写DataSet.Post;beforpost里面写你要检查的项目就行了。还有,如果出错了,当前行的记录是要取消,还是不变等待用户输入,你要想好思路才行。取消用Abort;停在当前行的话就出一个提示框给用户。
      

  5.   

    BeforePost里面不须要再Post;
    简单的东西让你想复杂了,你只需要要里面判断是否符合条件即可,如:
    如:
    procedure TForm1.tbl1BeforePost(DataSet: TDataSet);
    begin
      if Trim(DataSet.fieldbyname('X').asstring)='' then
      begin
        showmessage('X列不可为空');
        abort;
      end;
    end;
      

  6.   

    可能我说得还不够清楚。我的想法,换种方式表达:
        cxGrid可以自动提交更改而不用手动写SQL语句,我就是想保持cxGrid的这种便捷性,而只是把异常信息以用户可以接受的方式表达出来(而非用户无法读懂的异常提示),并可以加以操纵。而之前所用的方法(我5楼的),虽可以达到要求,但操作会变得不顺畅(Abort也会阻止在不引发异常时应该执行的操作,如移行等)。
        我想我的要求并不过份吧。另外:给分是不是就必须结帖了?
      

  7.   

    我想这不会是没有办法的,我知道ApplicationEvents可以做到我想要的效果,
    但缺点是无法精确控制,因为无法知道异常是在哪一步出现的。