在数据库内有N条数据(1千<N<10万),小弟必须按关系将他们放进一个TreeView内,数据的格式如下:
-------------------
ID | Title | Ref |
1 aa
3 bb 1
4 cc 1,3
7 dd
8 ee 7
12 ff 7,8
15 gg 7,8,12
-------------------
说明:ID是唯一的,但却不连续。Ref的值,表示是对应ID的子数据。即如果Ref为空,则是一个最顶层节点,有一个数字就是下一层,有两个数字就是第三层,如此类推。
上述的数据放到TreeView就是如下:
aa
|_bb
|_cc
dd
|_ee
|_ff
|_gg
请问怎样可以做到呢?请各位大哥帮帮忙啦!
-------------------
ID | Title | Ref |
1 aa
3 bb 1
4 cc 1,3
7 dd
8 ee 7
12 ff 7,8
15 gg 7,8,12
-------------------
说明:ID是唯一的,但却不连续。Ref的值,表示是对应ID的子数据。即如果Ref为空,则是一个最顶层节点,有一个数字就是下一层,有两个数字就是第三层,如此类推。
上述的数据放到TreeView就是如下:
aa
|_bb
|_cc
dd
|_ee
|_ff
|_gg
请问怎样可以做到呢?请各位大哥帮帮忙啦!
递归取得就可以了,
参考如下代码
procedure TClsRightManager.Dataset2TreeView(aDtst: TDataset; aTreeView: TRzCheckTree;
aImgLst: TImageList; const ImgInx: ArrayBooleanOfInteger;
const RightableFieldValue: ArrayBooleanOfString;
const RightableField: string;
const TextField: string;
const ParentField: string;
const IdField: string); function GetRecordInfo(const Id: string): PArrayString;
var
i, IdInx: integer;
Finded: Boolean;
begin
with aDtst do
begin
IdInx := FieldDefs.IndexOf(IdField);
Finded := Fields[IdInx].AsString = Id; if not Finded then
begin
First;
while not Eof do
begin
Finded := Fields[IdInx].AsString = Id;
if Finded then break;
Next;
end;
end;
end; if Finded then
begin
New(Result);
SetLength(Result^, aDtst.FieldCount);
for i := 0 to aDtst.FieldCount - 1 do
Result^[i] := aDtst.Fields.Fields[i].AsString;
end; if not Finded then
raise Exception.Create('没有找到该id的TTreeNode!!!');
end;
{-----------------------------------------------------------------------------
Procedure: GetRootNode
Author: javad
Date: 02-三月-2004
Arguments: None
Result: TTreeNode
得到RootNode;有两种情况,
1.表有外键:存在aParentField和IdField值相同的记录,即外键指向本记录的记录
2.表没有外键:这种情况将寻找IdField值为空(StringField)或0(IntegerField)的记录作为根节点
将优先采取第1种方式来进行查找-----------------------------------------------------------------------------}
function GetRootNode: TTreeNode;
var
Finded: Boolean;
begin
Result := nil;
//查找记录 //根据第1种情况
with aDtst do
begin
First;
while not Eof do
begin
if FieldByName(ParentField).AsString = FieldByName(IdField).AsString then
begin
Finded := True;
break;
end;
Next;
end;
end; //根据第2种情况
if not Finded then
begin
with aDtst do
begin
First;
while not Eof do
begin
if (FieldByName(IdField).AsString = '') or
(FieldByName(IdField).AsString = '0') then
begin
Finded := True;
break;
end;
Next;
end;
end;
end; //创建RootNode
if Finded then
Result := aTreeView.Items.AddChildObject(nil,
aDtst.FieldByName(TextField).AsString,
GetRecordInfo(aDtst.FieldByName(IdField).AsString)); if Result = nil then
raise Exception.Create('没有找到符合规则的根节点记录!!!');
end; function FindNode(const Id: string): TTreeNode;
var
i: integer;
tmp: ArrayString;
begin
Result := nil;
with aTreeView do
for i := 0 to Items.Count - 1 do
begin
tmp := PArrayString(Items[i].Data)^;
if Length(tmp) = 0 then continue;
if tmp[aDtst.FieldDefs.IndexOf(IdField)] = Id then
begin
result := Items[i];
break;
end;
end;
end; function GetNode(const Id: string; const Text: string): TTreeNode; function GetFieldValue(const Id: string; const FieldName: string): string;
var
IdInx, FieldInx: integer;
begin
IdInx := aDtst.FieldDefs.IndexOf(IdField);
FieldInx := aDtst.FieldDefs.IndexOf(FieldName);
Result := '';
with aDtst do
begin
if Fields[IdInx].AsString = Id then
begin
Result := Fields[FieldInx].AsString;
exit;
end;
First;
while not Eof do
begin
if Fields[IdInx].AsString = Id then
begin
Result := Fields[FieldInx].AsString;
break;
end;
Next;
end;
end;
end;
begin
Result := FindNode(Id);
if Result = nil then
Result := aTreeView.Items.AddChildObject(
GetNode(GetFieldValue(Id, ParentField), GetFieldValue(Id, TextField)),
Text, GetRecordInfo(Id));
end;var
I: integer;
ModuleList: TStringList;
tmpNode: TTreeNode;
begin
Assert((aDtst <> nil) and
(aTreeView <> nil) and
(Trim(TextField) <> '') and
(Trim(ParentField) <> '') and
(Trim(IdField) <> ''),
'传入参数错误!!!');
//清除原有节点
aTreeView.Images := aImgLst;
aTreeView.Items.Clear; ModuleList := TStringList.Create;
aDtst.DisableControls;
try
with aDtst do
begin
First;
while not Eof do
begin
ModuleList.Add(FindField(IdField).AsString + '=' + FindField(TextField).AsString);
Next;
end;
end; GetRootNode.ImageIndex := ImgInx[True];
with ModuleList do
for i := 0 to Count - 1 do
begin
tmpNode := GetNode(Names[i], Values[Names[i]]);
if PArrayString(tmpNode.Data)^[aDtst.FieldDefs.IndexOf(RightableField)] = RightableFieldValue[True] then
begin
tmpNode.ImageIndex := ImgInx[True];
tmpNode.SelectedIndex := ImgInx[True];
end
else
begin
tmpNode.ImageIndex := ImgInx[False];
tmpNode.SelectedIndex := ImgInx[False];
end;
end; aTreeView.Items.GetFirstNode.Expand(False);
finally
aDtst.EnableControls;
ModuleList.Free;
end;
end;
Classes, ComCtrls, ADODB, SysUtils;type
TNodeData = record
Index: integer;
Caption: string;
end;
PNodeData = ^TNodeData;
TTreeFill = class(TThread)
TV: TTreeView;
TableName: string;
FieldIndex: string;
FieldPID: string;
FieldCaption: string;
RootText: string;
Conn: TADOConnection;
Ptr: PNodeData;
constructor Create(ATreeView: TTreeView; AConn: TADOConnection;
ATable: string; ARootText: string = '我的目录';
AFieldIndex: string = 'ID'; AFieldPID: string = 'PID';
AFieldCaption: string = 'Caption');
private
procedure AddTree(Node: TTreeNode; PN: PNodeData);
protected
procedure Execute; override;
end;implementation
//------------------------------------------------------------------------------
constructor TTreeFill.Create(ATreeView: TTreeView; AConn: TADOConnection;
ATable: string; ARootText: string = '我的目录';
AFieldIndex: string = 'ID'; AFieldPID: string = 'PID';
AFieldCaption: string = 'Caption');
begin
FieldIndex := AFieldIndex;
FieldPID := AFieldPID;
FieldCaption := AFieldCaption;
TV := ATreeView;
TableName := ATable;
RootText := ARootText;
Conn := AConn;
New(Ptr);
inherited Create(False);
end;
//------------------------------------------------------------------------------
procedure TTreeFill.Execute;
var
Node: TTreeNode;
begin
FreeOnTerminate := True;
TV.Items.Clear;
Ptr^.Index := 0;
Ptr^.Caption := RootText;
Node := TV.Items.AddObject(nil, RootText, Ptr);
Node.ImageIndex := 0;
Node.SelectedIndex := 0;
AddTree(Node, Ptr);
TV.FullExpand;
end;
//------------------------------------------------------------------------------
procedure TTreeFill.AddTree(Node: TTreeNode; PN: PNodeData);
var Query: TADOQuery;
nNode: TTreeNode;
PNode: PNodeData;
begin
try
Query := TADOQuery.Create(nil);
Query.Connection := Conn;
Query.SQL.Text := 'Select * from ' + TableName + ' where ' + FieldPID + ' =' + IntToStr(PN^.Index);
if not Query.Active then
//Query.Close;
Query.Active:=true;
while Query.Eof = False do
begin
New(PNode);
PNode^.Caption := Query.FieldByName(FieldCaption).AsString;
PNode^.Index := Query.FieldByName(FieldIndex).AsInteger;
nNode := TV.Items.AddChildObject(Node, PNode^.Caption, PNode);
nNode.ImageIndex := 1;
nNode.SelectedIndex := 2;
AddTree(nNode, PNode);
Query.Next;
end;
finally
Query.Free;
end;
end;
//------------------------------------------------------------------------------
end.ID | pid | Ref |
aa 10
bb 1001
cc 100101
dd 20
ee 2001
ff 200101
你可以这样做
ID | Title | Ref |
1 aa -1
3 bb -1
4 cc 1
5 dd 3
6 ee 5
8 ff 6
那这样的的关系在TreeView中就很好表示了,-1是根项,id =(4 and 5)的是第二层,
id =(6)的是第三层, id =(8)的是第四层,
这样做才是TreeView的标准方式。
比如说你的第四层,没必要把1,2的ID都放进去,
只要第三层的ID就行了。