我想利用Treeview来显示树型结构,使得可以任意增加、删除节点,并且选中节点就显示与该节点有关的内容。我是个初学者,请多多指教!!!

解决方案 »

  1.   

    procedure tfrm_jyyj.showtree;
    var node: TTreeNode;
    begin
    //生成基本树型
      TV_1.Items.Clear;
      TV_1.Items.Add(TV_1.TopItem, '工作职责');
      cds_select.Close;
      cds_select.CommandText := '(select * from t_jy_mkqd where mkbm in' +
        '(select mkbm from t_jy_qxqd where js in' +
        '(select js from t_jy_czryjs where yhm=''' + VU_RYBH + ''' and jgbh=''' + VU_JGBH + ''')) or sfzjd=''0'') order by mkbm';
      cds_select.Open;
      cds_pd.Close;
      cds_pd.CommandText := cds_select.CommandText;
      cds_pd.Open;
      DSSocketConnection1.Connected := false;
      cds_select.IndexFieldNames := 'mkbm';
      cds_select.Filtered := false;
      cds_select.Filter := 'sjmk is null or sjmk=''''';
      cds_select.Filtered := true;
      cds_select.First;
      while not cds_select.Eof do
      begin
        cds_pd.filtered := false;
        cds_pd.Filter := 'mkbm like ''' + cds_select.fieldbyname('mkbm').AsString + '%'' and sfzjd=''1''';
        cds_pd.Filtered := true;
        if cds_pd.RecordCount > 0 then
        begin
          node := TV_1.Items.AddChild(TV_1.TopItem, '[' + cds_select.fieldbyname('mkbm').AsString + ']' + cds_select.fieldbyname('mkmc').AsString);
          node := TV_1.Items.AddChild(node, ''); //使改节点有下一层
        end;
        cds_select.Next;
      end;
      TV_1.AutoExpand := true;
    end;
      

  2.   

    procedure Tfrm_jyyj.tv_1Expanding(Sender: TObject; Node: TTreeNode;
      var AllowExpansion: Boolean);
    var node1: ttreenode;
    begin
     //树型展开查询
      if (Node.getFirstChild.Text = '') then //判断改节点第一个子项是否为空字符
      begin
        Node.DeleteChildren; //删除该子项
        cds_select.filtered := false;
        cds_select.Filter := 'sjmk =''' + fI_getjg(node.Text) + '''';
        cds_select.filtered := true;
        while not cds_select.Eof do
        begin
          cds_pd.filtered := false;
          cds_pd.Filter := 'mkbm like ''' + cds_select.fieldbyname('mkbm').AsString + '%'' and sfzjd=''1''';
          cds_pd.Filtered := true;
          if cds_pd.RecordCount > 0 then
          begin
            node1 := TV_1.Items.AddChild(node, '[' + cds_select.fieldbyname('mkbm').AsString + ']' + cds_select.fieldbyname('mkmc').AsString);
            if cds_select.FieldByName('sfzjd').AsString <> '1' then //判断改节点是否有子项
              TV_1.Items.AddChild(node1, '');
          end;
          cds_select.Next;
        end;
      end;end;
      

  3.   

    create table treedb
    (
       id char(6) primery key,
       text char(32)
    )//该构件的功能是建立从数据库内建立三级树,子叶可以从另外的数据库中显示详细项
    //要求主数据库的索引字段为6byte,ABC结构
    unit newdBTV;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      ComCtrls,dbtables,db;type
      TNewDBTV = class(TTreeView)
      private
        { Private declarations }
        FtvStr: TStringList;
        Fselectstr:TStringList;
        Fchangeimage:boolean;
        FActive:           boolean;//激活
        FBytes:            integer;//每层占用关键字串的字节数
        FMastDataSource:          TDataSource; //SQL
        FDetailDataSource:          TDataSource; //SQL
        procedure ActiveTree(InVal: boolean);
        procedure setByte(InVal: integer);
        function  CreateTree:boolean; //建立树
        procedure SetMastDataSource(Value: TDataSource);
        procedure SetDetailDataSource(Value: TDataSource);
      protected
        procedure Click;override;
      public
        constructor Create(AOwner: TComponent);override;
        destructor  Destroy;override;
        procedure editNode(DispStr,KeyStr:string);//修改当前节点
        procedure  delNode;//删除当前节点
        function  GetNodeKeyStr(tn:TTreeNode):string;//得到当前节点的键值
        function  AddNode(tn:TTreeNode;DispStr,KeyStr:string):TTreeNode;//加子节点
        procedure ClearTree;//清除树
      published
        property Active:boolean          read FActive
                                        write ActiveTree;
        property Bytes:integer           read FBytes
                                        write SetByte;
        property MastDataSource:TDataSource        read FMastDataSource
                                        write SetMastDataSource;
        //sql语句中,规定第0个field为键值,第1个field为显示字段,
        //第2个field为键值长度
        property DetailDataSource:TDataSource        read FDetailDataSource
                                        write setDetailDataSource;
        //sql语句中,规定第0个field为键值,第1个field为显示字段,
        //第2个field为连接字段
        property changeimage:boolean read Fchangeimage write Fchangeimage;  end;procedure Register;implementationprocedure Register;
    begin
      RegisterComponents('Samples', [TNewDBTv]);
    end;
    constructor TNewdbTV.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      Fchangeimage:=false;
      readonly:=true;
      self.HideSelection:=false;
      FActive:=false;
      FBytes:=0;
      FtvStr:=TStringList.create;
      Fselectstr:=TStringList.create;
    end;destructor  TNewdbTV.Destroy;
    begin
      FtvStr.free;
      Fselectstr.free;
      FMastDataSource:=nil;
      FDetailDataSource:=nil;
      inherited Destroy;
    end;function TNewdbTV.GetNodeKeyStr(tn:TTreeNode):string;//得到节点的键值
    begin
      if tn.AbsoluteIndex<>-1 then result:=FtvStr[tn.AbsoluteIndex]
      else result:='';
    end;function TNewdbTV.AddNode(tn:TTreeNode;DispStr,KeyStr:string):TTreeNode;//加节点
    begin
      if tn=nil then
        Result:=Items.Add(tn,DispStr)
      else
        Result:=Items.AddChild(tn,DispStr);
      FtvStr.insert(result.AbsoluteIndex,KeyStr);//影射树
      if Fbytes=0 then
        Fselectstr.insert(result.AbsoluteIndex,'1')
      else
        Fselectstr.insert(result.AbsoluteIndex,'0');
      Result.ImageIndex:=Result.Level+1; //boot
      if Fchangeimage then Result.selectedIndex:=Result.ImageIndex;
    end;procedure TNewdbTv.editNode(DispStr,KeyStr:string);//修改当前节点
    var i:integer;
        s1,s2:string;
    begin
       if selected=nil then exit;
       selected.Text:=DispStr;
       s1:=FtvStr.strings[selected.AbsoluteIndex];
       FtvStr.strings[selected.AbsoluteIndex]:=keystr;
       if FBytes=0 then exit;
       if FDetailDataSource<>nil then exit;
       //修改其子节点得代码
       for i:=selected.AbsoluteIndex+1 to FtvStr.Count-1 do
         begin
           s2:=FtvStr.strings[i];
           if s1=copy(s2,1,length(s1)) then
              FtvStr.strings[i]:=keystr+copy(s2,length(s1)+1,length(s2))
           else
             break;
         end;
    end;
    procedure  TNewdbTv.delNode;//删除当前节点
    var s,s1:string;
        i:integer;
    begin
       if selected=nil then exit;
       i:=selected.AbsoluteIndex;
       s:=FtvStr.strings[selected.AbsoluteIndex];
       selected.Delete;
       if (FBytes=0)or(FdetailDatasource<>nil) then
         begin
           FtvStr.delete(i);
           FselectStr.delete(i);
           exit;
         end;
       //删除其子节点得代码
       while true do
         begin
           FtvStr.delete(i);
           FselectStr.delete(i);
           if i=FtvStr.count then break;
           s1:=copy(FtvStr.strings[i],1,length(s));
           if s1<>s then break;
           if FtvStr.strings[i]='' then break;
         end;
    end;procedure TNewdbTV.ClearTree;//清除树
    begin
      items.Clear;
      FselectStr.clear;
      FtvStr.Clear;
    end;procedure TNewDBTv.ActiveTree(InVal: boolean);
    begin
        FActive:=Inval;
        ClearTree;
        if Inval then
          begin //建立树
            if FMastDatasource=nil then
              begin
                FActive:=false;
                exit;
              end;
            if not CreateTree then
              begin //建立树
                ClearTree;
                FActive:=false;
                exit;
              end;
          end;
    end;
      

  4.   

    procedure TNewDBTv.setmastDatasource(Value: TDatasource);
    begin
       if FmastDatasource<>Value then
         begin
           FmastDatasource:=Value;
           ClearTree;
           FActive:=false;
         end;
    end;
    procedure TNewDBTv.setdetailDatasource(Value: TDatasource);
    begin
       if FDetailDatasource<>Value then
         begin
           FDetailDatasource:=Value;
           ClearTree;
           FActive:=false;
         end;
    end;
    procedure TNewDBTv.setByte(InVal: integer);
    begin //设置树的分层方法,即每层所占关键串的字节数,隐含为2
      ClearTree;//清除树
      FActive:=false;
      if InVal>0 then FBytes:=InVal
      else FBytes:=0;
    end;function TNewDBTv.CreateTree:boolean; //建立树
    var root:ttreenode;
    begin
       result:=false;
       if FMastDatasource.dataset=nil then
           begin
             messagebox(application.handle,pchar('主表数据集不存在!'),'警告',0);
             exit;
           end;
       if FMastDatasource.dataset.active=false then
       try
         FMastDatasource.dataset.Open;
       except
         on e:exception do
           begin
             messagebox(application.handle,pchar('主表打开失败!'+e.message),'警告',0);
             exit;
           end;
       end;
       FmastDatasource.dataset.first;
       if Fmastdatasource.dataset.FieldCount<3 then
         begin
            messagebox(application.handle,'主表字段数不能小于3!','警告',0);
            exit;
         end;
       if FmastDatasource.dataset.isempty then
         begin
           result:=true;
           exit;
         end;
       if FdetailDatasource<>nil then
         begin
           if FdetailDatasource.dataset=nil then
             begin
               messagebox(application.handle,pchar('子表数据集不存在!'),'警告',0);
               exit;
             end;
           if FDetailDataSource.dataset.active=false then
           try
             FdetailDataSource.dataset.Open;
           except
             on e:exception do
               begin
                 messagebox(application.handle,pchar('子表打开失败!'+e.message),'警告',0);
                 exit;
               end;
           end;
           if FDetailDatasource.dataset.FieldCount<3 then
             begin
               messagebox(application.handle,'子表字段数不能小于3!','警告',0);
               exit;
             end;
           FDetailDatasource.dataset.first;
         end;
       FmastDatasource.dataset.filter:=FmastDatasource.dataset.fields[2].fieldname+'='+trim(FmastDatasource.dataset.fields[2].asstring);
       if Fbytes<>0 then FmastDatasource.dataset.filtered:=true;
       items.BeginUpdate;
       root:=AddNode(nil,trim(FmastDatasource.dataset.fields[1].asString),trim(FmastDatasource.dataset.fields[0].asString));
       FmastDatasource.dataset.Next;
       while not(FmastDatasource.dataset.eof) do
         begin
           AddNode(nil,trim(FmastDatasource.dataset.fields[1].asString),trim(FmastDatasource.dataset.fields[0].asString));
           FmastDatasource.dataset.Next;
         end;
       selected:=root;
       click;
       if not root.Expanded then root.Expand(false);
       items.EndUpdate;
       Result:=true;
    end;
    //加当前节点得下级节点
    procedure TNewdbtv.Click;
    var node:ttreenode;
        i:integer;
        s:string;
    begin
      inherited;
      if FActive=false then exit;
      if selected=nil then exit;
      if fselectstr[selected.AbsoluteIndex]='1' then exit;
      FmastDatasource.dataset.filtered:=false;
      FmastDatasource.dataset.filter:=
          FmastDatasource.dataset.fields[2].fieldname+'='+inttostr(length(ftvstr[selected.AbsoluteIndex])+Fbytes);
      i:=length(ftvstr[selected.AbsoluteIndex]);
      s:=ftvstr[selected.AbsoluteIndex];
      FmastDatasource.dataset.filtered:=true;
      while not FmastDatasource.dataset.eof do
        begin
          if copy(FmastDatasource.dataset.fields[0].asString,1,i)=s then
            AddNode(selected,trim(FmastDatasource.dataset.fields[1].asString),trim(FmastDatasource.dataset.fields[0].asString));
          FmastDatasource.dataset.Next;
        end;
      fselectstr[selected.AbsoluteIndex]:='1';
      if (Fdetaildatasource<>nil)and(ftvstr[selected.AbsoluteIndex]<>'') then
      if length(ftvstr[selected.AbsoluteIndex])=length(trim(FdetailDatasource.dataset.Fields[2].AsString)) then
        begin
          FdetailDatasource.dataset.filtered:=false;
          FdetailDatasource.dataset.Filter:=FdetailDatasource.dataset.fields[2].fieldname+'='''+ftvstr[selected.AbsoluteIndex]+'''';
          FdetailDatasource.dataset.Filtered:=true;
          while not FdetailDatasource.dataset.eof do
            begin
              node:=AddNode(selected,trim(FdetailDatasource.dataset.fields[1].asString),trim(FdetailDatasource.dataset.fields[0].asString));
              fselectstr[node.AbsoluteIndex]:='1';
              FdetailDatasource.dataset.Next;
            end;
        end;
    end;end.
      

  5.   

    //读表展开树
       ADOTable1.Active :=true;
       ADOTable2.Active :=true;
       ADOTable3.Active :=true;   //一级树
       with ADOTable1 do
       begin
         first;
         while not ADOTable1.Eof do
         begin
           s:=Fieldbyname('kind1').asstring;
           i:=Fieldbyname('kind1id').asfloat;
           MyTreeNode1:=TreeView1.Items.Add(nil,s);
           //二级树
           with ADOTable2 do
           begin
             Filter:='kind1id=' + floattostr(i);
             Filtered:=true;
             First;
             while not ADOTable2.Eof do
             begin
               s:=Fieldbyname('kind2').asstring;
               i:=Fieldbyname('kind2id').asfloat;
               MyTreeNode2:=TreeView1.Items.AddChild(MyTreeNode1,s);
               //三级树
               with ADOTable3 do
               begin
                 Filter:='kind2id=' + floattostr(i);
                 Filtered:=true;
                 First;
                 while not ADOTable3.Eof do
                 begin
                   s:=Fieldbyname('kind3').asstring;
                   TreeView1.Items.Addchild(MyTreeNode2,s);
                   next;
                 end;
               end;
             next;
             end;
           end;
           next;
         end;
       end; 
      

  6.   

    树形显示结构可以随数据库更新而自动更新
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, Grids, DBGridEh, fcTreeView, ExtCtrls, DBCtrls, Db, ADODB,
      fcdbtreeview, Buttons;type
      TForm1 = class(TForm)
        DBGridEh1: TDBGridEh;
        DBGridEh2: TDBGridEh;
        Label1: TLabel;
        Label2: TLabel;
        ADOQuery1: TADOQuery;
        ADOQuery2: TADOQuery;
        DataSource1: TDataSource;
        DataSource2: TDataSource;
        ADOConnection1: TADOConnection;
        DBNavigator1: TDBNavigator;
        DBNavigator2: TDBNavigator;
        fcDBTreeView1: TfcDBTreeView;
        BitBtn1: TBitBtn;
        procedure FormShow(Sender: TObject);
        procedure BitBtn1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.DFM}procedure TForm1.FormShow(Sender: TObject);
    begin
       Datasource1.DataSet:= ADOQuery1;
       Datasource2.DataSet:= ADOQuery2;   with fcDBTreeView1 do
       begin
          DatasourceFirst:= Datasource1;
          DatasourceLast:= Datasource2;
          DisplayFields.Add('Main名称:+#34+Name+#34');
          DisplayFields.Add('Detail名称:+#34+Name+#34');
       end;
       with ADOQuery1 do
       begin
          Close;
          SQL.Clear;
          SQL.Add(' select * from Main');
          Open;
       end;
       with ADOQuery2 do
       begin
          Close;
          SQL.Clear;
          SQL.Add(' select * from Detail');
          SQL.Add(' where ID=:ID');
          DataSource:= Datasource1;
          Open;
       end;
    end;end.