例子描述:
新建立一个Form,在上面放置ADOConnection1、ADOTable1、DataSource1、DBGrid1并分别设置连接字符串和各控件的连接关系,使DBGrid1中显示数据(这是很典型的List)。DBGrid1设置其Options中dgRowSelect=True(点击Grid时选择一行以反白显示而不是一个单元格)。我是比较注重用户对界面的感觉(心理模型)和习惯的。我认为,按照用户的心里模型(习惯),在DBGrid1选中一条记录,然后对其进行(更新)操作后,应该:
①立即在DBGrid1中看到更新后的结果(用户心理:我的更新到底有没有成功,我要看一下);
②在更新后DBGrid1应该没有滚动条的滚动(用户心理:这条记录仍应该在原来的位置);
③更新操作前的选择的记录(即反白显示的那一行记录)仍应保持选中状态(选中的记录仍以反白显示让用户很容易一眼就看到)。考虑以下的代码:
  ADOTable1.Edit;
  ADOTable1.FieldByName('Fee').Value:=1.1;
  ADOTable1.Post;  
这段代码是很典型的利用数据库控件来更新数据的过程,在Post后,DBGrid1的表现实现了前面要求的①(DBGrid1中的显示立即更新了)和②(滚动条没有滚动,屏幕没有闪动和刷新,即被更新的记录在屏幕上的绝对位置没有变化),但是没有实现③(当前记录仍是该被修改的记录,但是它失去了焦点,即不再处于被选中的状态,也即不以反白显示了)。再考虑以下的代码:
Var  RecordPosition:Integer;
begin
//采用ADOCommand控件来执行SQL进行更新操作。
  ADOCommand1.CommandText:='update accflow set fee=1 where accid=154';
  ADOCommand1.Execute;  RecordPosition:=DataSource1.DataSet.RecNo;//记录当前记录号
  DataSource1.DataSet.Close;
  DataSource1.DataSet.Open;//刷新数据集;
  DataSource1.DataSet.MoveBy(RecordPosition-1);//移动当前记录到刷新前的记录号
end;
这段代码只实现了要求①,没有实现②(DataSource1.DataSet.Open执行后当前记录号变成第一条,再执行DataSource1.DataSet.MoveBy(RecordPosition-1)时DBGrid1的滚动条有滚动,并且当前记录的在屏幕上的绝对位置变化了,这样用户在查看该记录的时候,就需要用眼睛寻找)和③(更新后当前记录不以反白显示了)。对比以上两种更新数据和DBGrid1的不同表现行为,可以知道应该有方法在第二段代码执行的时候让DBGrid1的表现实现要求②(我猜测很可能是DBGrid1的内部的某个方法,但我不知道)。至于要求③,我就不知道如何才能实现了。事实上,以上两段代码我只是拿来举例说明,我在我的项目中,早已不用以上的两种方式来更新数据了(我早已放弃使用数据库控件来更新数据,只是用它们来显示数据而已,我的项目中的所有DataSource的AutoEdit属性都是设定为False的;另外我的代码中也不使用任何SQL语句),也不用DBGrid1而是使用DevExpress的dxDBGrid。说了半天,总结一下:
在不使用数据库控件的Edit/Post方法来更新数据的时候,如何才能让Grid控件立即显示更新后的数据而不发生滚动条的滚动(即被更新的记录在屏幕上的绝对位置不变化),并且在更新后,该记录仍保持被选中(反白显示)的状态?先给出50分,如能实现,另开贴送分!

解决方案 »

  1.   

    给你一个我的代码:
    声明一个变量
    BK:TBookMark;在post记录前先保存
    BK:=ADOQuery1.GetBook;
    更新记录后返回原来的定位
    ADOQuery1.GotoBook(BK);
      

  2.   

    做书签之前先ADOQuery1.DisableControls ,结束后ADOQuery1.EnableControls,这样是在关闭控件的数据感知功能,Grid就不会滚动了。
      

  3.   

    综合 Uoooo,shimmergloomzl, 应可以解决了吧
      

  4.   

    刷新前断开数据源连接,刷新后再联上就可以了。反正我时这么做的。dbgrid.datasource.dataset := nil;....
    最后再连上就可以了。