最近公司项目中用到dxTreelist控件,以前没怎么用过这个控件,该控件比TreeView功能更强大,要完全掌握还真不容易,下面是我个人做的一个Demo,对该控件进行增删改遍历操作,以便自己以后忘了使用方法随时可以查吧。
1.首先新建一个数据库。
打开SQL Server2005,新建数据库TreeTest,新建表DeviceTab,表的字段设计如下:
2.新建Delphi应用程序
选择File-New-Application新建应用程序,File-New-Data Module,新建一个数据库模块,添加TADOConnection和TImageList控件,设置ADOConnection的LoginPrompt为false,给ImageList控件添加7个图片,该数据模块的Create事件代码如下:
procedure Tdm.DataModuleCreate(Sender: TObject);
begin
if not con1.Connected then
begin
//设置连接字符串
con1.ConnectionString:='Provider=SQLOLEDB.1;Password=123456;Persist Security Info=True;User ID=sa;Initial Catalog=TreeList;Data Source=ZH\SQLEXPRESS;';
con1.Open; //打开数据库连接
end;
end;
在窗体上放置dxTreeList控件和四个Button控件以及一个Timer控件设置Timer控件的Interval属性为100,各按钮相关事件及源码如下:
unit Main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, dxExEdtr, dxCntner, dxTL, dxTLClms,ADODB, Menus,
cxLookAndFeelPainters, StdCtrls, cxButtons, ExtCtrls;
type
TfrmTree = class(TForm)
dxTreeList1: TdxTreeList;
btnAddNode: TcxButton;
btnDelNode: TcxButton;
btnUpdate: TcxButton;
btnbl: TcxButton;
tmr1: TTimer;
procedure btnblClick(Sender: TObject);
procedure btnAddNodeClick(Sender: TObject);
procedure btnDelNodeClick(Sender: TObject);
procedure btnUpdateClick(Sender: TObject);
procedure tmr1Timer(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure CreateColumn(tree:TdxTreeList;list:TStrings);
procedure CreateImageColumn(tree:TdxTreeList;Image:TImageList);
procedure FillTree(node:TdxTreeListNode;pid:Integer;con:TADOConnection);
function GetMaxId(con:TADOConnection):Integer;
procedure DelTree(pid:Integer;con:TADOConnection);
procedure UpdateTree(newname:string;id:Integer;con:TADOConnection);
function GetCount(tree:TdxTreeList):Integer;
end;
var
frmTree: TfrmTree;
implementation
{$R *.dfm}
uses unitDM;
var
list:TStrings;
procedure TfrmTree.CreateColumn(tree:TdxTreeList;list:TStrings); //动态创建dxTreeList的列
var
i:Integer;
col:TdxTreeListColumn;
begin
for i:=0 to list.Count-1 do
begin
col:=tree.CreateColumn(TdxTreeListMaskColumn);
col.Caption:=list[i]; //显示标题
col.ColIndex:=i; //列索引
col.Name:=list[i]; //列标识
col.Width:=90+10*i; //列宽
end;
end;
procedure TfrmTree.CreateImageColumn(tree:TdxTreeList;Image:TImageList);//创建带图片的列
var
col:TdxTreeListColumn;
i:Integer;
begin
col:=tree.CreateColumn(TdxTreeListImageColumn);
col.Width:=50;
col.Name:='img';
TdxTreeListImageColumn(col).Images:=Image;
for i:=0 to image.Count-1 do //关联图片
begin
TdxTreeListImageColumn(col).ImageIndexes.Add(IntToStr(i));
TdxTreeListImageColumn(col).Values.Add(IntToStr(i));
end;
end;
procedure TfrmTree.FillTree(node: TdxTreeListNode; pid: Integer;con:TADOConnection);//构造树
var
tmpnode:TdxTreeListNode;
ADOQuery:TADOQuery;
begin
ADOQuery:=TADOQuery.Create(nil);
try
ADOQuery.Connection:=con;
ADOQuery.Close;
ADOQuery.SQL.Clear;
ADOQuery.SQL.Text:='select * from DeviceTab where pid='+Inttostr(pid);
ADOQuery.Open;
with ADOQuery do
begin
First;
while not Eof do
begin
if node=nil then
tmpnode:=dxTreeList1.Add //添加根节点
else
tmpnode:=node.AddChild; //添加子节点
pid:=FieldByName('id').AsInteger;
tmpnode.Strings[0]:=IntToStr(pid);
tmpnode.Strings[1]:=FieldByName('pid').AsString;
tmpnode.Strings[2]:=FieldByName('aName').AsString;
tmpnode.Strings[3]:=IntToStr(tmpnode.Level);
tmpnode.ImageIndex:=tmpnode.Level;
tmpnode.SelectedIndex:=tmpnode.Level;
FillTree(tmpnode,pid,con); //递归添加子节点
Next;
end;
end;
finally
ADOQuery.Free;
end;
end;
procedure TfrmTree.btnblClick(Sender: TObject); //遍历子节点
var
node,tmpnode:TdxTreeListNode;
i:Integer;
str:string;
begin
if dxTreeList1.Count=0 then Exit;
node:=dxTreeList1.FocusedNode; //获取焦点的节点
for i:=0 to dxTreeList1.ColumnCount-1 do
str:=str+node.Strings[i]+';';
ShowMessage(str);
tmpnode:=node.GetFirstChild; //获取第一个子节点
while tmpnode<>nil do
begin
str:=';
for i:=0 to dxTreeList1.ColumnCount-1 do
str:=str+tmpnode.Strings[i]+';';
ShowMessage(str);
//if tmpnode=node.GetLastChild then break;
if (tmpnode=node.GetLastChild) and (not tmpNode.HasChildren) then break; //判断是否为最后一个子节点是终止循环
tmpnode:=tmpnode.GetNext; //获取下一个节点
end;
end;
procedure TfrmTree.btnAddNodeClick(Sender: TObject); //添加节点
var
node:TdxTreeListNode;
i:Integer;
idindex,pidIndex,anameindex,imgIndex:Integer;
id,pid:integer;
aname:string;
qry:TADOQuery;
IsExist:Boolean;
begin
aname:=';
pid:=0;
for i:=0 to dxTreeList1.ColumnCount-1 do
begin
if dxTreeList1.Columns[i].Name='aName' then
begin
anameindex:=i;
end
else if dxTreeList1.Columns[i].Name='id' then
begin
idindex:=i;
end
else if dxTreeList1.Columns[i].Name='pid' then
begin
pidIndex:=i;
end
else if dxTreeList1.Columns[i].Name='img' then
begin
imgIndex:=i;
end;
end;
if InputQuery('添加节点','请输入节点名称',aname) then
begin
if dxTreeList1.Count=0 then
begin
node:=dxTreeList1.Add; //添加根节点
end
else
begin
node:=dxTreeList1.FocusedNode;
if node.Level=6 then
begin
ShowMessage('已经添加到节点极限');
exit;
end;
pid:=StrToIntDef(node.Strings[idindex],0);
node:=node.AddChild; //添加子节点
end;
id:=GetMaxId(dm.con1)+1;
node.Strings[idindex]:=IntToStr(id);
node.Strings[pidIndex]:=IntToStr(pid);
node.Strings[anameindex]:=aname;
node.Strings[imgIndex]:=IntToStr(node.Level);
node.ImageIndex:=node.Level;
node.SelectedIndex:=node.Level;
try
qry:=TADOQuery.Create(nil);
qry.Connection:=dm.con1;
qry.Close;
qry.SQL.Clear;
qry.SQL.Text:='insert into DeviceTab values('+inttostr(id)+','+Inttostr(pid)+','+QuotedStr(aname)+')';
qry.ExecSQL;
finally
qry.Free;
end;
end;
end;
function TfrmTree.GetMaxId(con: TADOConnection): Integer; //获取最大ID值
var
qry:TADOQuery;
begin
try
qry:=TADOQuery.Create(nil);
qry.Connection:=con;
with qry do
begin
close;
sql.Clear;
SQL.Add('select Max(id) as mid from DeviceTab');
Open;
First;
Result:=qry.FieldByName('mid').AsInteger;
end;
finally
qry.Free;
end;
end;
procedure TfrmTree.btnDelNodeClick(Sender: TObject); //删除节点
var
node:TdxTreeListNode;
i,aid:integer;
begin
if dxTreeList1.Count=0 then
begin
ShowMessage('没有要删除的节点');
Exit;
end
else
begin
node:=dxTreeList1.FocusedNode;
if MessageBox(Self.Handle,PChar('确定要删除该节点及其所有的子节点吗?'),PChar('删除提示'),MB_OKCANCEL)<>IdOK then Exit;
if node.HasChildren then node.DeleteChildren; //删除子节点
for i:=0 to dxTreeList1.ColumnCount-1 do
begin
if dxTreeList1.Columns[i].Name='id' then
begin
aid:=i;
Break;
end
end;
DelTree(StrToIntDef(node.Strings[aid],0),dm.con1);
node.Free;
end;
end;
procedure TfrmTree.DelTree(pid: Integer;con: TADOConnection); //删除数据库节点记录
var
tmpnode:TdxTreeListNode;
ADOQuery:TADOQuery;
begin
ADOQuery:=TADOQuery.Create(nil);
try
ADOQuery.Connection:=con;
with ADOQuery do
begin
Close;
SQL.Clear;
SQL.Text:='delete from DeviceTab where id='+Inttostr(pid); //删除当前节点记录
ExecSQL;
end;
ADOQuery.Close;
ADOQuery.SQL.Clear;
ADOQuery.SQL.Text:='select * from DeviceTab where pid='+Inttostr(pid); //查找子节点记录
ADOQuery.Open;
with ADOQuery do
begin
First;
while not Eof do
begin
DelTree(FieldByName('id').AsInteger,con); //递归删除下级记录
Next;
end;
end;
finally
ADOQuery.Free;
end;
end;
procedure TfrmTree.btnUpdateClick(Sender: TObject); 修改
var
node:TdxTreeListNode;
aname:string;
i,j,k,id:Integer;
IsExist:Boolean;
begin
IsExist:=False;
if dxTreeList1.Count=0 then
begin
ShowMessage('没有要修改的节点');
exit;
end
else
begin
dxTreeList1.BeginUpdate;
node:=dxTreeList1.FocusedNode;
for i:=0 to dxTreeList1.ColumnCount-1 do
begin
if dxTreeList1.Columns[i].Name='aName' then
begin
j:=i;
aname:=node.Strings[i];
Break;
end
else if dxTreeList1.Columns[i].Name='id' then
begin
k:=i;
id:=StrToIntDef(node.Strings[i],0);
end;
end;
if InputQuery('修改节点','请输入修改后的节点名',aname) then
begin
node.Strings[j]:=aname;
UpdateTree(aname,id,dm.con1);//更新数据库记录
end;
end;
dxTreeList1.EndUpdate;
end;
procedure TfrmTree.UpdateTree(newname: string; id: Integer;
con: TADOConnection);
var
qry:TADOQuery;
begin
qry :=TADOQuery.Create(nil);
try
with qry do
begin
Connection:=con;
Close;
SQL.Clear;
SQL.Text:='update DeviceTab set aname='+Quotedstr(newname)+' where id='+Inttostr(id);
ExecSQL;
end;
finally
qry.Free;
end;
end;
procedure TfrmTree.tmr1Timer(Sender: TObject);
begin
tmr1.Enabled:=False;
list:=TStringList.Create;
dm.con1.GetFieldNames('DeviceTab',list); //获取表的字段名
CreateColumn(dxTreeList1,list);
CreateImageColumn(dxTreeList1,dm.il1);
dxTreeList1.BeginUpdate;
FillTree(nil,0,dm.con1);
dxTreeList1.EndUpdate;
end;
procedure TfrmTree.FormDestroy(Sender: TObject);
begin
list.Free;
if dm.con1.Connected then
dm.con1.Close;
end;
function TFrmTree.GetCount(tree:TdxTreeList):integer; //获取总的节点数
var
node:TdxTreeListNode;
begin
Result:=0;
dxTreeList1.GotoFirst;
node:=dxTreeList1.Items[0];
while node<>nil do
begin
inc(Result);
node:=node.GetNext;
end;
end;
end.
3.运行效果
初始界面
添加节点后界面
删除节点后界面
修改节点后界面
节点遍历( 部分截图)
总结:dxTreelist控件的属性和方法还有许多,功能比TreeView更丰富,同时操作也更复杂,它没有treeview.items.count属性获取节点总数,它的每一个节点都是一个TdxTreeListNode节点,操作每个节点时用Strings或Values集合来赋值给节点的每一列,以后如果用到再深入研究一下,这个Demo足够一般的应用。