表DeptInfo: Code SubCode (字段) A C A E B D B F C G D H 其中,Code是SubCode的上级部门。 上述表用TREEVIEW显示如下: ___ A--| C--G | |___ E | B--|-- D-H | ---- F 请问用什么算法让数据更快更好的加载到TREEVIEW来呢? 100分相送,决不食言!!! (有代码最好!)
procedure CreateSubTree(FNodeName: string; Node: TTreeNode = nil);
var mLocalName: string;
TreeNode: TTreeNode;
Ads_Tmp: TADODataSet;
begin
ADS_Tmp := TADODataSet.Create(Self);
ADS_Tmp.Connection := ADOConn;
with ADS_Tmp do
begin
Close;
CommandText := 'Select * from Type Where ParentID =' + FNodeName;
Open;
First;
while not Eof do
begin
mLocalName := FieldbyName('ID').Asstring;
TreeNode := TreeView.Items.AddChild(Node, FieldByName('Name').AsString);
CreateSubTree(mLocalName, TreeNode);
Next;
end;
end;
end;
TDBTreeView=class(TTreeView)
private
fTable:TDataSet;
fId,fParentId,fName:string;
function AddItem:TTreeNode;
function FindItem(Id:string):TTreeNode;
protected
procedure Change(Node: TTreeNode); override;
public
function GetId:string;
procedure BuildTree;
procedure ClearTree;
function TDBTreeView.FindItem(Id:string):TTreeNode;
var i:integer;
NodeInfo:^TTreeNodeInfo;
begin
Result:=nil;
For i:=0 to Items.Count-1 do
begin
NodeInfo:=Items[i].Data;
If NodeInfo^.Id=Id then
begin
Result:=Items[i];
Exit;
end;
end;
end;
function TDBTreeView.GetId:string;
var NodeInfo:^TTreeNodeInfo;
begin
If Selected=nil then Result:=''
else
begin
NodeInfo:=Selected.Data;
Result:=NodeInfo^.Id;
end;
end;
function TDBTreeView.AddItem:TTreeNode;
var NodeInfo:^TTreeNodeInfo;
BMark:TBookMark;
ObjParent:TTreeNode;
Name,CurId:string;
begin
ObjParent:=FindItem(fTable.FieldByName(fId).AsString);
If ObjParent<>nil then
begin
Result:=ObjParent;
Exit;
end
else
begin
New(NodeInfo);
NodeInfo^.Id:=fTable.FieldByName(fId).AsString;
NodeInfo^.ParentId:=fTable.FieldByName(fParentId).AsString;
Name:=fTable.FieldByName(fName).AsString;
If fTable.FieldByName(fParentId).AsString<>'' then
begin
ObjParent:=FindItem(Name);
If ObjParent<>nil then
Result:=Items.AddChildObject(ObjParent,Name,NodeInfo)
else
begin
CurId:=fTable.FieldByName(fId).AsString;
If fTable.Locate(fId,fTable.FieldByName(fParentId).AsString,[]) then
begin
Result:=Items.AddChildObject(AddItem,Name,NodeInfo);
fTable.Locate(fId,CurId,[]);
end
else
Result:=Items.AddObject(Selected,Name,NodeInfo);
end;
end
else
begin
Result:=Items.AddObject(Selected,Name,NodeInfo);
end;
end;
end;
procedure TDBTreeView.BuildTree;
var ChangeEvent:TTVChangedEvent;
begin
If (fTable=nil) or (not fTable.Active) then Exit;
ChangeEvent:=OnChange;
OnChange:=nil;
Items.BeginUpdate;
ClearTree;
fTable.First;
While not fTable.Eof do
begin
AddItem;
fTable.Next;
end;
AlphaSort;
Items.EndUpdate;
OnChange:=ChangeEvent;
end;
procedure TDBTreeView.ClearTree;
var NodeInfo:^TTreeNodeInfo;
i:integer;
begin
Items.BeginUpdate;
for i:=0 to Items.Count-1 do
begin
NodeInfo:=items[i].Data;
Dispose(NodeInfo);
end;
While Items.Count>0 do Items.Delete(Items[0]);
Items.EndUpdate;
end;
procedure Register;
begin
RegisterComponents('Data Controls',[TDBTreeView]);
end;
constructor TDBTreeView.Create(AOwner: TComponent);
begin
inherited;
end;
destructor TDBTreeView.Destroy;
begin
inherited;
end;
如果不在deptinfo中增加记录就用下面的代码,个人觉得加两条记录方便些procedure TForm1.Button1Click(Sender: TOBject);
var
m:TTreeNode;
s_ADOQuery:TADOQuery;
begin
s_ADOQuery:=TADOQuery.Create(self);
s_ADOQuery.Connection:=ADOConnection1;
s_ADOQuery.Close;
s_ADOQuery.SQL.Clear;
s_ADOQuery.SQL.Text:='select distinct(code) from deptinfo where code not in (select distinct(subcode) from deptinfo)';
s_ADOQuery.Open;
if not s_ADOQuery.IsEmpty then
begin
while not s_ADOQuery.Eof do
begin
m:=TreeView1.Items.Add(nil,s_ADOQuery.fieldbyname('code').AsString);
InitTreeView(m,s_ADOQuery.fieldbyname('code').AsString);
s_ADOQuery.Next;
end;
end;
end;
function TForm1.FindNode(TreeView:TTreeView;text:string):TTreeNode;
var i,j:integer;
begin
result:=nil;
j:=treeview.Items.Count;
for i:=0 to j-1 do
begin
if treeview.Items[i].Text=text then
begin
result:=treeview.Items[i];
exit;
end;
end;
end;
procedure TForm1.MoveChildNode(TreeView:TTreeView;DestNode:TTreeNode;SourNode:TTreeNode);
var tn1,tn2:TTreeNode;
begin
tn1:=nil;
tn2:=nil;
tn1:=sournode.getFirstChild;
if tn1<>nil then
begin
tn2:=treeview.Items.AddChild(destnode,tn1.Text);
if tn1.HasChildren then
begin
self.MoveChildNode(treeview,tn2,tn1);
end;
end;
tn1:=sournode.GetNextChild(tn1);
while tn1<>nil do
begin
tn2:=treeview.Items.AddChild(destnode,tn1.Text);
if tn1.HasChildren then
begin
self.MoveChildNode(treeview,tn2,tn1);
end;
tn1:=sournode.GetNextChild(tn1);
end;
tn1:=nil;
tn2:=nil;
end;
procedure TForm1.Button1Click(Sender: TObject);
var tn1,tn2,tn3:TTreeNode;i,j:integer;value:string;
begin
table1.Open;
while not table1.Eof do
begin
value:=table1.FieldValues['code'];
tn1:=self.FindNode(self.TreeView1,value);
if tn1=nil then
begin
tn1:=self.TreeView1.Items.Add(nil,value);
end;
value:=table1.FieldValues['subcode'];
tn2:=self.FindNode(self.TreeView1,value);
if tn2=nil then
begin
tn2:=self.TreeView1.Items.AddChild(tn1,value);
end else
begin
tn3:=self.TreeView1.Items.AddChild(tn1,value);
self.MoveChildNode(self.TreeView1,tn3,tn2);
tn2.Delete;
end;
table1.Next;
end;
table1.Close;
end;
在你的表中加两条记录 0 A 0 B
procedure InitTreeView(TreeNode:TTreeNode;Key:String);
var
TN:TTreeNode;
s_ADOQuery:TADOQuery;
begin
s_ADOQuery:=TADOQuery.Create(self);
s_ADOQuery.Connection:=ADOConnection1;
s_ADOQuery.Close;
s_ADOQuery.SQL.Clear;
s_ADOQuery.SQL.Text:='select code,subcode from deptinfo where code='+Quotedstr(key);
s_ADOQuery.Open;
if not s_ADOQuery.IsEmpty then
begin
while not s_ADOQuery.Eof do
begin
TN:=Treeview1.Items.AddChild(TreeNode,s_ADOQuery.fieldbyname('subcode').AsString);
InitTreeView(TN,s_ADOQuery.fieldbyname('subcode').AsString);
s_ADOQuery.Next;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TOBject);
begin
InitTreeView(nil,'0');
end;
用SQL就可以解决这样的问题那还要Delphi干嘛?好老说,你这个数据库的设计也有问题,如果把你的SubCode改为UpCode就要好作多了。当然,象你这样也可以作的,不过要多一个Query
先用一个RootQry:TADOQuery来取第一级部门SQL象这样
select * from DepInfo where not code in (select SubCode from DepInfo)
用一个DetailQry:TADOQuery来Select * from DepInfo然后再用递归生成树---绝对累不死CPU,除非你程序有死循环!也不应该很慢!!大体如下:
var
ANode:TTreeNode;
begin
RootQry.First;
while not RootQry.Eof do
begin
ANode:=TreeView.Items.Add(nil,RootQry.FieldByName('Code').AsString);
CreateChild(ANode);
RootQry.Next;
end;
procedure CreateChild(FNode:TTreeNode);
var
BookMark:String;
ANode:TTreeNode;
begin
DetailQry.First;
While Not DetailQry.Eof do
begin
if DetailQry.FieldByName('Code').AsString=FNode.Text then
begin
ANode:=TreeView.Items.AddChild(FNode,
DetailQry.FieldByName('SubCode').AsString);
Bookmark:=DetailQry.Bookmark;
CreateChild(ANode);//此处递归!!
DetailQry.Bookmark:=Bookmark;
end;
DetailQry.Next;
end;
DetailQry.
end;