关于如何才能让DBGrid平滑刷新的问题的讨论。。。

littlefat 2004-05-10 05:52:54
(明明已经发送成功怎么不见了?!)

例子描述:
新建立一个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分,如能实现,另开贴送分!
...全文
72 点赞 收藏 11
写回复
11 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
littlefat 2004-05-11
多谢几位!别的论坛有兄弟告诉我DBGrid控件中有一个Option叫做AlwaysShowSelection选项的,将其设定为True是可以实现效果③的。但是dxDBGrid控件却没有这个Option。。。

DisableControl和EnableControl对于第一段代码其实没有什么用处,不用照样不会发生滚动;但是对第二段代码,即使是用了,仍会发生滚动。。。。

其实,第一段代码使用数据控件的Edit、Post功能来更新数据时,因为数据库控件已经“知道”了更新,并且更新正是通过它们来提交的,所以,数据库控件在将更新提交到数据库中时会同时它们自己的本地缓存(显示)中的相应记录;但是第二段代码(或者使用存储过程等另外的方法)来更新数据,没有通过“它们”,所以它们不知道后台已经更新了,它们的缓存中仍保存着更新前的数据,所以必须使用Close、Open方法来强迫“它们”刷新自己的缓存,这时就发生屏幕滚动了。。。。

所以,有没有什么方法和机制,可以在我们使用其他方法更新数据时,通知“它们”某(些)记录已经更新了,请刷新,并且让“它们”刷新的时候不要傻乎乎地将所有记录全部重新读取,而只读取被更新的记录,在更新显示的时候不要滚动屏幕。。。
回复
qizhanfeng 2004-05-11
disablecontrol
enablecontrol
回复
web700 2004-05-11
③更新操作前的选择的记录(即反白显示的那一行记录)仍应保持选中状态(选中的记录仍以反白显示让用户很容易一眼就看到)。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 加个书鉴就可以搞定.

回复
例子描述:
新建立一个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中的显示立即更新了)和②(滚动条没有滚动,屏幕没有闪动和刷新,即被更新的记录在屏幕上的绝对位置没有变化),但是没有实现③(当前记录仍是该被修改的记录,但是它失去了焦点,即不再处于被选中的状态,也即不以反白显示了)。

////////////
我按照上面要求试了一下,满足第三个要求,即更新后还是呈选中的状态,即满足第三个条件,连接数据库为SQL SERVER!!~~~
////////////
回复
--------友情提示:--------

本问题使用的控件是dxDBGrid,不是DBGrid !!!!~~~~

--------提示结束:--------

up ^_^
回复
littlefat 2004-05-11
Up!
回复
楚人无衣 2004-05-11
我的代码只能使右边滚动条不动,却无法使其相对位置不动,我没办法了,盼高手……
回复
littlefat 2004-05-11
谢谢weizi2000(秋风啊) !你的代码运行时仍发生滚动。

回复
楚人无衣 2004-05-11
已有人说过了,呵呵,你试试行不:
sKey:=ADOTable1.FieldByName('AccID').AsInteger;
ADOTable1.DisableControls;
ADOTable1.Requery();
ADOTable1.Locate('AccID',IntToStr(sKey),[loCaseInsensitive, loPartialKey]);
ADOTable1.EnableControls;
回复
littlefat 2004-05-10
谢谢 soaringsouth(栈桥捉鳖) 兄:

以下代码确实可以在刷新数据集后保持原来的行处于选中状态:

var key:Integer;
begin
key:=ADOTable1.FieldByName('AccID').AsInteger;
ADOTable1.Close;
ADOTable1.Open;
ADOTable1.Locate('AccID',IntToStr(key),[loCaseInsensitive, loPartialKey]);
end;

但是滚动条仍发生滚动,即被选中更新的记录在刷新后在屏幕上的绝对位置发生了变化(每次该记录都是显示在Grid窗口的中间部分)。

不管怎样,这比我的第二段代码有进步。。。

谢谢!
回复
soaringsouth 2004-05-10
更新前记住主键的值,更新完毕后
ADOTable1.locate();//参数自己写,不明白看帮助
回复
发帖
数据库相关
创建于2007-08-02

2451

社区成员

Delphi 数据库相关
申请成为版主
帖子事件
创建了帖子
2004-05-10 05:52
社区公告
暂无公告