C# TreeView的用法

一:TreeView.Items[0].Expanded := True; // 展开第一个节点
二:TreeView.Items[0].Item[0].Selected := True; // 移动到第一个节点的第一个子节点 
找当前节点的下一个节点,按序号找如下:
if treeview1.Selected.GetNext<>nil then
treeview1.Selected.GetNext.Selected:=true;
TreeView1.SetFocus;

找当前节点的下一个同层兄弟如下:
if treeview1.Selected.getNextSibling<>nil then
treeview1.Selected.getNextSibling.Selected:=true;
TreeView1.SetFocus;
TreeView.Selected.getPrevSibling  //当前选中节点的上一个兄弟节点
TreeView.Selected.Parent          //  当前选中节点的父节点 

getfirstchild是跳到该节点子结点中的第一个
getlastchild是跳到该节点子结点中的最后一个

如果你是想跳到同层兄弟结点的第一个
if treeview1.selected.parent<>nil then
treeview1.selected.parent.getfirstchild.selected:=true
else
treeview1.items.item[0].selected:=true;

如果你是想跳到同层兄弟结点的最后一个
if treeview1.selected.parent<>nil then
treeview1.selected.parent.getlastchild.selected:=true
else
treeview1.Items.Item[treeview1.Items.Count-1].Selected:=true;
TreeView的使用方法


基本信息:
TreeView 是一个显示树型结构的控件,每一个节点都是一个新类,
使用具有代表性
每个节点都有四个值:
TEXT:显示文字 Image Index:显示图形序号
Selected Index:
State Index:

(1)建立目录项(本例中使用的TREEVIEW名称为:TvwTips)

增加根目录下的节点:(节点)
var
CatNode : TTreeNode; //先建立一个TREEVIEW使用的子对象
begin
TvwTips.SetFocus; //将焦点置到这个TREEVIEW控件上
{ 在根标题下建立一个新的子标题 }
CatNode := TvwTips.Items.AddChild(
TvwTips.Items.GetFirstNode,'New Category' );
CatNode.ImageIndex := 1;
CatNode.SelectedIndex := 2;
CatNode.EditText; { 允许用户改变这个标题 }
end;

增加下一级目录(内容):
var
ParentNode, TipNode : TTreeNode; //先建立TREEVIEW使用
的子对象
VersionNum : Integer;
begin
TvwTips.SetFocus; //将焦点置到这个TREEVIEW控件上
VersionNum := TMenuItem( Sender ).Tag; { Ver num of new tip }
ParentNode := TvwTips.Selected; { 取出当前的选中节点 }
if ParentNode.Level = nlTip then{ Parent cannot be a tip node }
ParentNode := TvwTips.Selected.Parent;

TipNode := TvwTips.Items.AddChildObject( ParentNode,'New
Subject',Pointer( VersionNum ) );
TipNode.ImageIndex := 3; { Normal tip bitmap }
TipNode.SelectedIndex := 4; { Highlighted tip bitmap }
TipNode.MakeVisible; { Move new tip node into view }
TipNode.EditText; { Immediately allow user to edit subject }
EnableTreeViewFunctions( TipNode.Level );
RtfTip.Clear;
RtfTip.Modified := False;
end;

(2)说明
TvwTips.Items.GetFirstNode 返回TREEVIEW的第一个节点,函数类型为
:TTreeNode
TvwTips.Items.Count 返回当前TreeView的全部节点数,整数
TvwTips.Selected.Level 返回当前选中节点的在目录树中的级别,
根目录为0
TvwTips.Selected.Parent 返回当前选中节点上级节点,函数类型为
:TTreeNode

三、下面这段程序是用TREEVIEW连数据库及一些操作:
unit bmzd;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, ComCtrls, Db, DBTables, ImgList, Buttons, ExtCtrls, Grids,
 DBGrids;

type
 Tfrmbmzd = class(TForm)
   Panel1: TPanel;
   cmd_new: TBitBtn;
   cmd_delete: TBitBtn;
   cmd_exit: TBitBtn;
   tvwcode: TTreeView;
   ScrollBox1: TScrollBox;
   GroupBox2: TGroupBox;
   Label3: TLabel;
   Label2: TLabel;
   Label1: TLabel;
   Label4: TLabel;
   Label5: TLabel;
   Edit2: TEdit;
   Edit3: TEdit;
   Edit4: TEdit;
   Edit5: TEdit;
   ImageList1: TImageList;
   Edit1: TEdit;
   cmd_save: TBitBtn;
   cmd_update: TBitBtn;
   procedure FormShow(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
   procedure cmd_newClick(Sender: TObject);
   procedure cmd_deleteClick(Sender: TObject);
   procedure Edit2KeyPress(Sender: TObject; var Key: Char);
   procedure tvwcodeChange(Sender: TObject; Node: TTreeNode);
   procedure cmd_updateClick(Sender: TObject);
   procedure BitBtn2Click(Sender: TObject);
   procedure tvwcodeClick(Sender: TObject);
 private
   { Private declarations }
     function LoadCode(crTbl:TDBDataSet):Integer;
function GetLevel(sFormat,sCode:String):Integer;

 public
   { Public declarations }
 end;

var
 frmbmzd: Tfrmbmzd;
 ii:integer;
 tv:ttreenode;
 const
SCodeFormat = '222222';   //科目代码结构
SFirstNodeTxt   = '部门分类';

implementation

uses dm;


{$R *.DFM}

function tfrmbmzd.LoadCode(crTbl:TDBDataSet):Integer;
var NowID,sName,ShowTxt:String;
i,Level:Integer;
MyNode:array[0..6]of TTreeNode;
//保存各级节点,最长支持6级(重点)
begin
Screen.Cursor:=crHourGlass;
Level:=0;
With frmdm.tabbm do
begin
try
if not Active then Open;
First;
tvwCode.Items.Clear;
//以下是增加第一项
MyNode[Level]:=tvwCode.Items.Add
(tvwCode.TopItem,SFirstNodeTxt);
MyNode[Level].ImageIndex:=0;
MyNode[Level].SelectedIndex:=0;
//以上是增加第一项
While Not Eof do
begin
NowID:=Trim(FieldByName('bumeng_id').AsString);
ShowTxt:=FieldByName('bumeng_name').AsString;
Level:=GetLevel(SCodeFormat,NowID);
//返回代码的级数
//以下是增加子项
//以下用上一级节点为父节点添加子节点
if Level>0 then//确保代码符合标准
begin
  MyNode[Level]:=tvwCode.Items.AddChild
(MyNode[Level-1],NowID+' '+ShowTxt);
  MyNode[Level].ImageIndex:=1;
 MyNode[Level].SelectedIndex:=2;
end;  
//以上是增加子项
Next;
end;
finally
Close;
end;
end;
MyNode[0].Expand(False);//将首节点展开
Screen.Cursor:=crDefault;
end;
//以上函数将Code.db表中的科目代码和科目代码名称显示出来

//下面函数的功能是返回一代码的级数,
//参数sFormat传递科目代码结构;
//参数sCode传递某一科目代码
function tfrmbmzd.GetLevel
(sFormat,sCode:String):Integer;
var i,Level,iLen:Integer;
begin
Level:=-1;//如果代码不符合标准,则返回-1
iLen:=0;
if (sFormat<>'')and(sCode<>'')then
for i:=1 to Length(sFormat) do
begin
iLen:=iLen+StrToInt(sFormat[i]);
if Length(sCode)=iLen then
begin
  Level:=i;
  Break;
end;
end;
Result:=Level;
end;

procedure Tfrmbmzd.FormShow(Sender: TObject);
begin

if not frmdm.tabbm.active then frmdm.tabbm.Open;
frmdm.tabbm.IndexFieldNames:='BUMENG_ID';
//按字段aCode排序(不要漏掉)

LoadCode(frmdm.tabbm);

 

end;

procedure Tfrmbmzd.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;

procedure Tfrmbmzd.cmd_newClick(Sender: TObject);
begin
tvwcode.SetFocus ;
if tvwcode.selected.AbsoluteIndex<>0 then
begin
cmd_delete.Enabled:=true;
cmd_update.Enabled:=true;
cmd_save.Enabled :=true;
if not frmdm.tabbm.Active then frmdm.tabbm.Open;

edit1.text:=frmdm.tabbm.Fields[0].asstring;
end;
tvwcode.SetFocus ;
tvwcode.Items.AddChild(tvwcode.selected,'新建部门');
if   tvwcode.Selected.HasChildren then
begin
if tvwcode.Selected.GetLastChild.index+1>9 then
 edit2.text:=inttostr(tvwcode.Selected.GetLastChild.index+1)
 else
edit2.text:='0'+inttostr(tvwcode.Selected.GetLastChild.index+1);
edit3.text:='新建部门';
edit2.Enabled:=true;
edit3.Enabled:=true;
end
else
begin
edit2.text:='01';
edit3.text:='新建部门';
edit2.Enabled:=true;
edit3.Enabled:=true;
end;
if not frmdm.tabbm.Active then frmdm.tabbm.Open;
frmdm.tabbm.edit;
frmdm.tabbm.Append;
cmd_new.Enabled :=false;
cmd_delete.Enabled :=false;
cmd_update.Enabled :=false;
cmd_save.Enabled :=true;
//新建下级部门

tvwcode.Selected.GetLastChild.Selected:=true;
//设选择
tv:=tvwcode.Selected ;
tvwcode.autoExpand:=true;
tvwcode.SetFocus ;


end;

procedure Tfrmbmzd.cmd_deleteClick(Sender: TObject);
var
I:integer;
seno,setext:string;
begin
if tvwcode.Selected.HasChildren=true then
begin
application.messagebox('该部门包含下级,不能删除','提示',MB_OKCANCEL+mb_iconquestion ) ;
end
else
begin
if   application.messagebox('你确实要删除当前部门吗','提示',MB_OKCANCEL+mb_iconquestion )=IDOK then
begin
setext:=tvwcode.selected.text;
i:=0;
while setext[i] <> ' ' do
begin
I := I + 1;
seno:=seno+setext[i];
end;
if not frmdm.tabbm.Active then frmdm.tabbm.Open;
frmdm.tabbm.setkey;
frmdm.tabbm.Fields[0].asstring:=seno;
if frmdm.tabbm.GotoKey then
begin
frmdm.tabbm.edit;
frmdm.tabbm.Delete;
end;
tvwcode.Selected.Delete ;
cmd_new.Enabled :=true;
tvwcode.autoExpand:=true;
 tvwcode.SetFocus ;
end;
end;

end;

procedure Tfrmbmzd.Edit2KeyPress(Sender: TObject; var Key: Char);
begin
if key  in ['0'..'9',Chr(vk_Back)]   then

else
begin
key:=#0;
application.messagebox('','',mb_ok);

end;
end;

procedure Tfrmbmzd.tvwcodeChange(Sender: TObject; Node: TTreeNode);
var
i,lev:integer ;
strr,seno,setext:string;
begin
if cmd_new.Enabled =true then
begin
if tvwcode.selected.AbsoluteIndex<>0   then
begin
cmd_delete.Enabled:=true;
cmd_update.Enabled:=true;
cmd_save.Enabled :=true;
setext:=tvwcode.selected.text;
i:=0;
while setext[i] <> ' ' do
begin
I := I + 1;
seno:=seno+setext[i];
end;
if not frmdm.tabbm.Active then frmdm.tabbm.Open;
frmdm.tabbm.setkey;
frmdm.tabbm.Fields[0].asstring:=seno;
frmdm.tabbm.GotoKey;
strr:='';

case tvwcode.Selected.Level of
2: strr:=copy(frmdm.tabbm.fields[0].asstring,1,2);
3: strr:=copy(frmdm.tabbm.fields[0].asstring,1,4);
 end;
 edit1.text:=strr;
//加上级编码
edit3.text:=frmdm.tabbm.Fields[1].asstring;
//本级编码

edit2.text:=copy(frmdm.tabbm.fields[0].asstring,length(frmdm.tabbm.fields[0].asstring)-1,2);

end
else
begin
edit1.text :='';
edit2.text :='';
edit3.text :='部门分类';
cmd_delete.Enabled :=false;
cmd_update.Enabled :=false;
end;
end;
end;


procedure Tfrmbmzd.cmd_updateClick(Sender: TObject);
var
i:integer;
begin
for i:=0 to ComponentCount-1  do
begin
if (Components[I]  is tedit ) then
(Components[I]  as tedit).enabled:=false;
end;
for i:=0 to ComponentCount-1  do
begin
if (Components[I]  is tbitbtn ) then
(Components[I]  as tbitbtn).enabled:=true;
end;
if tvwcode.Selected.AbsoluteIndex<>0 then
begin

if not frmdm.tabbm.Active  then frmdm.tabbm.Open;
frmdm.tabbm.Edit;
frmdm.tabbm.Fields[0].asstring:=edit1.text+edit2.text;
frmdm.tabbm.Fields[1].asstring:=edit3.text;
try
frmdm.tabbm.Post;
//表的保存
except
on edbengineerror do
begin
edit2.Enabled :=true;
 application.messagebox('编号不能重复,请重新输入','提示',MB_OK+mb_iconquestion ) ;
exit;
end;
 end;
tvwcode.Selected.Text:=edit1.text+edit2.text+' '+edit3.text;
tvwcode.SetFocus ;
//修改树
end;

cmd_new.Enabled :=true;
edit2.Enabled :=false;
end;

procedure Tfrmbmzd.BitBtn2Click(Sender: TObject);
begin
cmd_new.Enabled :=false;
cmd_delete.Enabled :=false;
edit2.enabled:=true;
edit3.Enabled :=true;

end;

procedure Tfrmbmzd.tvwcodeClick(Sender: TObject);
var
i:integer;
begin
if cmd_new.Enabled =false then
begin
application.MessageBox('当前是修改状态,请单击保存按钮','提示',mb_ok);
tv.Selected :=true;
end;
if  tvwcode.selected.AbsoluteIndex=0 then
begin
for i:=0 to ComponentCount-1  do
begin
if (Components[I]  is tedit ) then
(Components[I]  as tedit).enabled:=false;
end;
for i:=0 to ComponentCount-1  do
begin
if (Components[I]  is tbitbtn ) then
(Components[I]  as tbitbtn).enabled:=false;
cmd_new.Enabled :=true;
cmd_exit.Enabled :=true;
end;
end;
end;
end

四、使用概述
树形图(Treeview)是Win95下新增加的通用显示部件(Common Control,在COMCTL32.DLL中)之一,从Delphi2.0开始也增加了相应的控件Treeview,用于取代原Outline控件。由于树形图结构较复杂,使用起来常不知如何下手。这里就使用中的一些问题作些介绍。
   Treeview用于显示按照树形结构进行组织的数据,这在实际当中用途还是比较广泛的,如计算机中的文件系统(Windows95中的资源管理器)、企业或公司的组成结构等等。Treeview控件中一个树形图由节点(TreeNode)和连接线组成。TtreeNode是TTreeview的基本组成单元。一个树的节点又包含文本(Text)和数据(Data)。Text为String类,Data则为无定形指针(Untyped Pointer),可以指向一个与节点相联系的数据结构。
  每一个节点下子节点形成这一节点的Items属性,当前节点有一个唯一的Index(TreeNode的Index属性),用于说明子节点在Items中的位置,每一个节点下的子节点是顺序编号的,第一个是0,第二个是1,依次类推。用IndexOf方法获得子节点的顺序,绝对顺序(AbsoluteIndex)则是指从Treeview第一个项开始的顺序值,第一个是0,如此推下去。Item属性则根据Index的值返回当前节点的第Index个子节点。Count则表明属于此项的所有子节点的数量。用MoveTo方法将Item由一个位置移到另一个位置。
  Expanded属性表明是否所有的子项都全部展开(包括子项的子项),为True表示全部展开。IsVisible属性表明一个项是否在树中能被看到,如果树全部展开那么这个Item是肯定可以被看到。HasChildren属性表明一个项是否有子项。 GetFirstChild, GetLastChild, GetPrevChild, and GetNextChild分别返回当前项子项的第一个、最后一个和前一个、后一个项。GetNextSibling and GetPrevSibling则返回在同一Level下的下一个和上一个项。GetNextVisible and GetPrevVisible则返回能看得到的下一个和上一个项。如果一个节点有Parent,则HasAsParent方法返回True. Parent为当前项的父项。Focused属性确定焦点是否落在此节点上,被Focus时会一个标准的方框围住。很显然,只有一个节点会被聚焦。 Selected属性表明一个节点是否被选中,同样只有一个节点会被选中。DropTarget属性表明节点在拖动操作中是源还是目标。
1.添加、删除、修改节点:
静态的方法可以在设计时通过Items的编辑器设置各节点的内容。
在添加和删除前必须保证有节点被选中(Treeview.Selected = nil)
用AddFirst, AddFirstChild, AddChild等先添加根节点,如Treeview.Items.AddFirst( nil, 'Root');
然后以此为基础,添加此项的子节点。

删除节点
Treeview.Selected.Delete
编辑节点内容
Treeview.Selected.EditText
注意:由于根节点没有父节点 (TTreeNode.Parent= nil)
此外,在大批量添加数据到Treeview中时最好使用
  TreeView.Items.BeginUpdate;
  添加节点
  TreeView.Items.EndUpdate
这样能加快显示速度。

2.在节点上添加图象
Treeview中几个与图象相关的属性:
  SelectedIndex:当节点被选中时在TimageList 中选什么样的图象
  OverlayIndex:选那副图象作为掩图(一幅图象透明地显示在另一幅图象的前面),比如一个节点不可用时加一副X图象在其前面。
  ImageIndex:在常态时选用的图的序号
  StateIndex: 在StateImages这个ImageList中对应的序号,-1时不显示图象
  比较典型的,象在文件管理器中的所显示的一样,Treeview控件在节点之前也可以显示图象。在Form中放置一ImageList控件,加入几个图片,分别被Index为0,1,…在Treeview的Image属性项填入你所加入的ImageList的控件名称。TreeNode的ImageIndex表示节点未被选中时(Selected=nil)的图片序号,SelectedIndex表示节点被选中时图片序号。

3.关于Level
Level的概念可以用下图表示:
Level0   Level1 Level2

4.排序
SortType决定什么时候进行排序;
TreeView.AlphaSort对节点进行排序,如果不能满足要求,你可以定义自己的CustomSort方法。
5.Drag&Drop操作,与标准的拖放操作使用方法一样。

五、一个例子:
 首先,在库的构建上要有一定策略以下几个字段非常重要:
'codeID'      代码集名称 (例如:'AB')
'code'        节点代码   (例如:'新疆'节点的代码为'65','乌鲁木齐'的节点代码为'6501'等)
'description' 节点描述   (例如:如上面的'新疆'、'乌鲁木齐'等)
'pptr'        父节点代码(例如:'乌鲁木齐'节点的父代码为'65',最高层节点的父节点代码可同其代码集,例如:'新疆'的父节点为                              'AB')
'cptr'        子节点标识 (例如:该节点是否有下级节点,有则取值'1',没有则取值'0')

 

建立树由两部分构成:

procedure TForm1.FormActivate(Sender: TObject);
var
 code_ID,new_sql,node_text,table_name:string;
 new_node:Ttreenode;
begin

//要传递的参数
code_ID:='AB';
table_name:='sr_codeitem';

//********
treeview1.Items.BeginUpdate;

//清空所有项目
treeview1.Items.Clear;


new_sql:='select * from '+ table_name + ' where codeID='+''''+code_ID+''''
        + ' and '+'pptr='+''''+code_ID+'''';


//数据集中先筛选出所有要增加节点
with dm1.Query1 do
begin
  close;
  sql.Clear;
  sql.Add(new_sql);
  open;
  //增加第一层节点
  while not eof do
    begin
      node_text:=fieldbyname('code').asstring;
      node_text:=node_text+'   '+fieldbyname('description').asstring;
      new_node:=treeview1.Items.add(nil,node_text);
      new_node.HasChildren:=true;
      next;
    end;//end while
end;//end with

treeview1.Items.EndUpdate;
end;

procedure TForm1.TreeView1Expanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
var
 new_sql,node_text,child_text,code_ID,table_ID:string;
 child_node:Ttreenode;
begin
//获取参数
code_ID:='AB';
table_ID:='sr_codeitem';

treeview1.Items.BeginUpdate;
node_text:=node.Text;
//截取所点击节点的code
node_text:=copy(node_text,1,pos(' ',node_text)-1);
with dm1.Query1 do
begin
  close;
  sql.Clear;
  new_sql:='select * from '+table_ID+' where pptr='+''''+node_text+'''' + ' and codeID='
            +''''+code_ID+'''';
  sql.Add(new_sql);
  open;//定位所点的项
  //清除原来的下级节点
  node.DeleteChildren;
  while not eof do
     begin//增加下级节点
       child_text:=fieldbyname('code').asstring+'   '+fieldbyname('description').asstring;
       child_node:=treeview1.Items.AddChild(node,child_text);
       if fieldbyname('cptr').asstring='1' then
          child_node.HasChildren:=true;
          next;
     end;//end while

end;//end with
treeview1.Items.EndUpdate;
end;
 第二部分:在 treeview 的onExpanding 事件中添加如下代码
procedure TForm1.TreeView1Expanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
var
 new_sql,node_text,child_text,code_ID,table_ID:string;
 child_node:Ttreenode;
begin
//获取参数
code_ID:='AB';
table_ID:='sr_codeitem';

treeview1.Items.BeginUpdate;
node_text:=node.Text;
//截取所点击节点的code
node_text:=copy(node_text,1,pos(' ',node_text)-1);
with dm1.Query1 do
begin
  close;
  sql.Clear;
  new_sql:='select * from '+table_ID+' where pptr='+''''+node_text+'''' + ' and codeID='
            +''''+code_ID+'''';
  sql.Add(new_sql);
  open;//定位所点的项
  //清除原来的下级节点
  node.DeleteChildren;
  while not eof do
     begin//增加下级节点
       child_text:=fieldbyname('code').asstring+'   '+fieldbyname('description').asstring;
       child_node:=treeview1.Items.AddChild(node,child_text);
       if fieldbyname('cptr').asstring='1' then
          child_node.HasChildren:=true;
          next;
     end;//end while

end;//end with
treeview1.Items.EndUpdate;
end; 

六、让我们一个一个来回答:
第一个:取出节点的text属性值,赋给Richedit的Lines.text即可;
例如: self.RichEdit1.Lines.text:= self.Treeview1.selected.text;
第二个:TtreeView控件有函数保存和载入树的结构到文件
例如:self.Treeview1.SaveToFile('文件名');//保存结构
     self.TreeView1.LoadFromFile('文件名');//载入结构
第三个:TreeView的每个节点都有ItemID(句柄),AbsoluteIndex(相对于树头节点的索引位置),
Index(在当前层的位置),Level(本节点的层数)通过访问这些可以知道其位置;
例如:self.TtreeView1.selected.ItemID;//返回句柄
    self.TreeView1.selected.Level;//返回层数
    self.TreeView1.Items.count//返回所有节点的个数;
**寻找某一个节点的话,就只有写一个循环来遍历整个树,直到找到符合条件的节点为止,
关于查找节点的代码我也在想,先参考上面同志们的回答吧;

??**为某个节点加上子节点,例如:
var NewNode:TTreeNode;
begin
NewNode:=self.Treeview1.Items.addChild(self.Treeview1.Items[3],'新的字节点');
//为self.Treeview1.Items[3]加上一个字节点,标签是'新的字节点',
//还有其他的ADD方法,可以查找Delphi帮助
//然后可以给刚加上去的子节点赋值;
NewNode.ImageIndex:=n;
NewNode.SelectedIndex:=M;
NewNode.Data:=X;//注意X是一个指针类型;关于这方面的帮助
//可以找一下TTreeNode.Data 属性例子
end;
??**想选中某个节点:self.TreeView1.Items[n].selected:=true;//这样就选中了
??**展开某节点就容易了:self.TreeView1.Items[n].Expand;//展开啦!
//想合上就用Collapse(Recurse: Boolean)函数,
总之呢,去查一下TtreeNode的帮助吧!
??**清除某节点下的所有子节点,用DeleteChildren是没错的,例如:
self.Treeview1.Items[n].DeleteChildren;//OK,下面都没了!

七、query1.close;
query1.sql.clear;
query1.sql.add('select * from t08 order by t0801');
try
  query1.open;
except
  on e:exception do
  begin
     application.MessageBox(pchar('打开数据库文件失败!'+#13+#13+e.Message),'错误信息',16);
     close;
     exit;
  end;
end;
//创建结构树
while not query1.eof do
begin
   s:=trim(query1.fields[0].asstring);
   case length(s) of
   2:begin
        tv1.Selected:=tv1.items.add(nil,trim(query1.fields[1].asstring));
        tv2.Selected:=tv2.items.add(nil,trim(query1.fields[0].asstring));
     end;
   4:begin
        p1:=tv1.items.addchild(tv1.Selected,trim(query1.fields[1].asstring));
        p2:=tv2.items.addchild(tv2.Selected,trim(query1.fields[0].asstring));
     end;
   6:begin
        tv1.Items.addchild(p1,trim(query1.fields[1].asstring));
        tv2.Items.addchild(p2,trim(query1.fields[0].asstring));
     end;
   end;
   query1.next;
end;
query1.close;
if tv1.Items.Count>0 then
begin
 tv1.Selected:=tv1.Items[0];
 tv1.Selected.Expand(true);
end;
tv1.OnClick(self); 
八、clear速度慢的问题
 问题的关键在于Clear方法会一个一个地删除每个Node,
于是TreeView不断刷新,所以速度就....
代码修正一下:
with MyTreeView.Items do
<B>try</B>
BeginUpdate;
Clear;
<B>finally</B>
EndUpdate;
<B>end;</B>

另外
1、你现在遇到的问题是大量删除,
如果是大量插入,也应该同样处理
2、ListView有同样问题,注意
其他Windows控件也有,但不很明显
比如Memo、RichEdit等等
总之,凡大量数据修改的情况下,
应该注意BeginUpdate和EndUpdate
3、<B>BeginUpdate和EndUpdate应该一一对应</B>,
因为Delphi实际上是用<B>计数器</B>来处理的,
如果忘了EndUpdate,
或者BeginUpdate比EndUpdate次数多,
可能导致控件不刷新了

九、用treeview做权限管理

posted @ 2013-01-12 10:12  赤狐(zcm123)  阅读(810)  评论(0编辑  收藏  举报