我用treeview和listview做了一个树型数据表的显示,譬如我在treeview上选择一个treenode(节点)在listview上就会显示出属于这个节点的子节点,做法就是用该treenode的名字查询数据库,把属于该节点的子节点数据用listview显示出来。但有一个问题就是,如果treeview上存在两个相同名字的treenode时,这是就查询不出来了,但如果在每一个treenode上都记录一个id值,对应数据表的ID字段,在查询时用id来查询而不是用treenode的名字,这样就算存在两个相同名字的treenode时都没所谓了,那应该怎样来记录这个id的值呢?在线等待!
解决方案 »
- 求delphi高手帮忙!
- 急!!!delphi7在win2000下开发的软件在XP操作系统下的问题???
- 请问如何控制MDI子窗体的位置!!求助!
- 小弟编写了一个实时传送信息软件。遇到一个小问题。请高手解答。--附客户端源代码
- 数据一直累加,就是不从新开始,急啊
- DBLookupComboBox的使用,
- netuseradd()在哪个单元?
- 简单问题:Can only modify a image if it contains a bitmap.代码如下。
- 苯熊熊的苯问题:如何在程序中随时得到SQL Server某一数据表的更新信息
- 求助,用什么做GUIDE界面最简单,
- 高分求教,提示"not founs system.pas"...
- 用access本身导出的功能所导出为*.db的数据中,凡是中文字段内的内容全部“?”号,怎么办?
也可以就利用treenode.stateindex
在创建treeview的时候,将stateindex一起赋值
Type
PMyCode = ^TMyCode;
TMyCode = Record
vName: String; //名称
vCode: String; //编码
End;var
DataRec1:PMyCode; new(DataRec1);
DataRec1^.vCode := trim(FindField(vCode).AsString);
DataRec1^.vName := trim(FindField(vName).AsString);
{
.....
}
TreeView1.Items.AddChildObject(Mynode, '名字', DataRec1);当选中时(OnChange):
if TreeView1.Selected<>nil then
ShowMessage(PMyRec(TreeView1.Selected.Data)^.vCode);
type Tmytreenode=class(Ttreenode)
vname:string;
vcode:string;
end;
但如何用自已的这个Tmytreenode形成treeview呢?
id = integer(Node.Data);
这样的话,再一次用到时,便可以直接到字符串列表中找了。
procedure Tfrm_main.RefreshCata; //刷新视图
var
node:TTreeNode;
str,id:String;
begin
list_bh.Clear;
list_cata.Items.Clear;
sql_cata.SQLQuery('select bh,cata_name,cata_xm_count,cata_memo from cata');
id:=sql_cata.GetValueByIndex(0);
if id<>'' then
sql_xm.SQLQuery('select * from xm where xm_cata_bh='+id);
id:=sql_xm.GetValueByIndex(0);
sql_jdb.SQLQuery('select * from jdb where jdb_xm_bh='+id);
while Not sql_cata.Eof do
begin
str:=sql_cata.GetValueByIndex(1);
node:=list_cata.Items.Add(nil,str);
str:=sql_cata.GetValueByIndex(0);
list_bh.add(str);//注意!这里记录所需要的ID值。
sql_cata.Next;
end;
sql_cata.Close;
end;
对于使用标准的OO设计方法,TTreeView提供了AddItem(‘string’,Point)方法,Point可以用于存储对象的指针。在需要根据节点引用对象时,可以使用RTTI的is、as来取得对象(也可以用类标识符强制类型转换,但不安全);
对于设计跟数据库相关的程序,还有InfoPower的TfcTreeView组件可以使用,TfcTreeView的节点TfcTreeNode除了“Text”外带有两个扩展字符串属性“StringData”、“StringData2”,我自己经常采用的做法是,“Text”属性存储显示标题,“StringData”属性存储记录的ID,“StringData2”属性存储记录的类型(先要在程序中将每种记录类型用不重复的常量进行标记),这样在寻找节点对应记录时将带来巨大方便。但TfcTreeView的缺点有:1、当图标节点多时,组件图象更新很慢,包括拖动条响应;2、在更新组件前后需要依次调用BeginUpdate与EndUpdate方法,否则很可能导致屏幕显示出问题;
为了树型视图加载的快速性,普遍采用的方法是——根据需要加载子节点,首先为未确认的是否含有子节点的对象设置一个虚拟子节点(所谓虚拟节点是指一个在软件中被作了标记的但无其它实际意义的节点),并保持收缩状态(未展开),当用户点击要展开节点时,在节点的OnExpanding事件中添加处理函数,首先判断是否只包含虚拟节点,如果是则先删除虚拟节点,再将其所包含的真正子节点加载(如果无子节点,则被选节点自然显示为叶节点)。
对于上面的一般通则,尤其针对于那些展开节点需要花较长时间的情况比较适用,如WINDOWS的“网上邻居”节点部分,“SQL SERVER”中展开数据库的节点等等。
这种做法还有一个遗留问题,就是——如果用户没有选择具体节点,那么所有边缘节点就都处于收缩状态且很可能这些边缘节点下并不包含任何子节点,好象不如WINDOWS资源管理器中本地目录树那样直观。其实,处理这个问题的办法很简单,就是在展开某层(如第一层)节点时的事件处理函数中添加下层(就是第二层)节点的虚拟节点处理事件。但这种做法需要考虑程序响应时间的问题,如果此过程消耗时间太多,会对用户的操作性能有很大影响。
另外补充,还可以在以上处理过程中添加消息处理函数Application.ProcessMessage以响应用户操作,但需要考虑这样可能带来的临界资源竞争,程序绘写事件冲突等问题,总之,如果要这样做,你必须清楚的知道自己在做什么。■ TListView关于对象指针需要注意的问题
看了上面关于TTreeView第一段的描述,很自然的会希望在TListView中也能够使用对象指针。不幸的是,我多次的经验告诉我,TListView中TListItem所包含的指针属性不如TTreeView中来得可靠,到底是什么原因还不得而知(我认为是Borland自己的问题,不能太迷信,Borland的一些组件确实有问题,譬如我在写《物业I》系统时发现的TCombBoxEx的文本信息存取出错问题等!)
至于替代的办法是,在TListItem的SubItems最后添加多几条自定义的不在Columns列显示的信息。
出于时间的考虑,还是推荐使用InfoPower的TfcTreeView组件(当然,选用组件时也要注意组件的稳定性、性能等指标)。
如果要的话,发封邮件到.cn