1.数据库结构与我的上一篇文章数据库->树型结构(TTreeView篇)完全相同
2.我的创建TVirtualStringTree树结构的单元文件代码
unit BuildVirtualTreeUnit;
interface
uses
DB, ADODB, ComCtrls,Dialogs,VirtualTrees;
// 定义树结点对数据库表记录对应的结构体
type
PNode = ^TNode;
TNode = record
FID:integer; // 记录的ID号
FCaption:string;
FBM:TBookMark; // 定位记录的指针(书签)
end;
function BuildTree(DataSet: TADODataSet; TV: TVirtualStringTree; SelfField,SelfName,ParentField:String):boolean;
implementation
function BuildTree(DataSet: TADODataSet; TV: TVirtualStringTree; SelfField,SelfName,ParentField:String):boolean;
{ 以下子函数为在表中查找第一个PNode=AIndex的记录}
function FindKey(AIndex: integer; FFirst:boolean): boolean;
begin
Result:=DataSet.Locate(ParentField,AIndex,[loCaseInsensitive]);
end;
{ 以下函数在FindKey的基础上找出下一个符合的记录}
function FindNext(AIndex: integer): boolean;
begin
DataSet.Next;
if DataSet.Eof then
Result:=false
else
Result:=DataSet.FieldValues[ParentField]=AIndex;
if not Result then DataSet.Prior;
end;
{ 以下函数据构造当前结点的一级子树 }
function GetChildNode(index: integer; ANode: PVirtualNode):integer;
var
MyNode:PNode;
Node:PVirtualNode;
begin
if FindKey(index,true) then
begin
Node:=TV.AddChild(ANode);
MyNode := TV.GetNodeData(Node) ;
with DataSet do
begin
MyNode^.FID :=FieldValues[SelfField];
MyNode^.FBM :=GetBookmark;
MyNode^.FCaption := FieldValues[SelfName];
end;
Result:=1;
while FindNext(index) do
begin
Node:=TV.AddChild(ANode);
MyNode := TV.GetNodeData(Node);
with DataSet do
begin
MyNode^.FID :=FieldValues[SelfField];
MyNode^.FBM :=GetBookmark;
MyNode^.FCaption := FieldValues[SelfName];
end;
Result:=Result+1;
end;
end
else
Result:=0;
end;
{ 以下函数据以ANode 为结当,构造一棵属于自己的子树}
procedure BuildMe(AIndex: integer; ANode: PVirtualNode);
var
NodeNum:integer;
Node:PVirtualNode;
i:integer;
begin
NodeNum:=GetChildNode(AIndex,ANode);
//exit;
if NodeNum>0 then
begin
if ANode=nil then Node:=TV.GetFirst
else
Node:=ANode.FirstChild;
for i:=1 to NodeNum do
begin
BuildMe(PNode(TV.GetNodeData(Node))^.FID,Node);
Node:=TV.GetNext(Node);
end;
end;
end;
// 组合部份
begin
if (DataSet=nil) or (DataSet.Active =false) then
Result:=false
else if (TV=nil) then
Result:=false
else begin
TV.Clear;
BuildMe(0,nil);
Result:=true;
end;
end;
end.
3.要在TVirtualStringTree上显示文字,需要提供一个回调:
procedure TfrmMain.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
_pNode:PNode;
begin
_pNode := Sender.GetNodeData(Node);
if Assigned(_pNode) then
CellText := _pNode.FCaption;
end;
5.当在TVirtualStringTree上点击时,可以获取当时项对应的数据库记录:
procedure TfrmMain.VSTClick(Sender: TObject);
var
_pNode:PNode;
begin
_pNode := VST.GetNodeData(VST.FocusedNode) ;
//第一种方式
ShowMessage(_pNode^.FCaption);
//第二种方式
DM.dsGroup_.GotoBookmark(_pNode.FBM);
ShowMessage(DM.dsGroup_.FindField('group_name').AsString);
end;
4.调用
BuildTree(DM.dsGroup_,VST,'id','group_name','parent_id');
注:TVirtualStringTree的功能非常的强大,速度效率绝非TTreeView能比的。自然使用起来就复杂,但是只要掌握了它的原理,就很好理解了.