现在有一用户信息表,表里记录了用户所住的小区、楼幢、单元号,程序主界面的left是一个TTreeView,我想在上面显示如下结果:
-全部小区
 -青青小区
  - 1幢
    - 101
 -梦幻城市
  - 6幢
    -101
 -金亭晚秋
我现在的思路是先添加所有小区的结点,然后遍历这些小区,根据小区添加各个小区下面的楼幢,然后遍历楼幢添加楼幢(小区+楼幢相同)的下面的单元号),我总觉的这个思路有点啰嗦,但是实在想不到好办法,所以请教一下,有没有别的好的简单一些的办法?谢谢!

解决方案 »

  1.   

    http://topic.csdn.net/u/20081023/16/a70f97c4-3545-4e92-a6e8-6590cb5cfaa5.html
      

  2.   


    procedure TForm1.Button1Click(Sender: TObject);
    var
    Oneli,twoli:TStringList;
    Nodea,Nodeb,nodec: TTreeNode;
    begin  with adoquery1 do begin
         if SQL.Text='' then exit;
         if not Active then open;
         if IsEmpty then exit;
         First;
         Oneli:=TStringList.Create;
         twoli:=TStringList.Create;
       try
         TreeView1.Items.Clear;
         Nodea:=TreeView1.Items.AddChildFirst(nil,'全部楼层');
         while not eof do begin
            if Oneli.IndexOf(FieldByName('小区').AsString)<0 then begin
                Nodeb:=TreeView1.Items.AddChild(Nodea,FieldByName('小区').AsString);
                Oneli.AddObject(FieldByName('小区').AsString,Nodeb);
            end
            else
               Nodeb:=TTreeNode(Oneli.Objects[Oneli.IndexOf(FieldByName('小区').AsString)]);        if twoli.IndexOf(FieldByName('楼幢').AsString)<0 then begin
               nodec:=TreeView1.Items.AddChild(Nodeb,FieldByName('楼幢').AsString);
               twoli.AddObject(FieldByName('楼幢').AsString,Nodec);
            end
            else
              Nodec:=TTreeNode(twoli.Objects[twoli.IndexOf(FieldByName('楼幢').AsString)]);
          TreeView1.Items.AddChild(Nodec,FieldByName('单元号').AsString);
        next;
        end;   finally
          Oneli.Free;
          twoli.free;   end;
      end;
    end;
      

  3.   


    select a.*, b. 小区, c. 楼幢
      from 用户表 a, 小区表 b, 楼幢表 c
     where a. 小区号 = b. 小区号
       and a. 楼幢号 = c. 楼幢号
      

  4.   

    其实楼主可以先只把各小区挂在树上,在树的OnExpanding事件中根据要展开的节点及其父节点(如果有的话)的信息再从数据库中检索当前节点的子节点信息,这样即可以把检索数据的时间化整为零了,又可以简化数据库操作。这样做的缺点就是不能通过遍历树而查找信息了。
      

  5.   

    给你个例子吧,procedure TFormNewRecord.FormShow(Sender: TObject); 
    var 
    i,n,x,y:integer; 
    node1,node2:TTreeNode; 
    begin 
    ADOQuery1.Close; 
    ADOQuery1.SQL.Clear; 
    ADOQuery1.SQL.Add('select * from materials_ftype'); 
    ADOQuery1.Open; 
    //TreeView建立父节点 
    for i:=0 to ADOQuery1.RecordCount-1 do 
    begin 
    for n:=0 to TreeView1.Items.Count-1 do 
    begin 
    if (node1.Text <> Trim(ADOQuery1.fieldbyname('typename').AsString)) then 
    begin 
    node1:=TreeView1.Items.AddChild(nil,ADOQuery1.fieldbyname('typename').AsString); 
    //TreeView建立子节点 
    ADOQuery2.Close; 
    ADOQuery2.SQL.Clear; 
    ADOQuery2.SQL.Add('select * from materials_type where typename=:zonglei'); 
    ADOQuery2.Parameters.ParamByName('zonglei').Value:=node1.Text; 
    ADOQuery2.Open; 
    for x:=0 to ADOQuery2.RecordCount-1 do 
    begin 
    node2:=TreeView1.Items.AddChild(node1,ADOQuery2.fieldbyname('ftypename').AsString); 

    //TreeView建立三级树 
    ADOQuery3.Close; 
    ADOQuery3.SQL.Clear; 
    ADOQuery3.SQL.Add('select * from materials where materialname=:fenlei'); 
    ADOQuery3.Parameters.ParamByName('fenlei').Value:=node2.Text; 
    ADOQuery3.Open; 
    for y:=0 to ADOQuery3.RecordCount-1 do 
    begin 
    TreeView1.Items.AddChild(node2,ADOQuery3.fieldbyname('mname').AsString); 
    ADOQuery3.Next; 
    end; 
    //end 

    ADOQuery2.Next; 
    end; 
    //end 
    end; 
    end; 
    ADOQuery1.Next; 
    end; 
    TreeView1.Items.Delete(TreeView1.TopItem); 
    //end 
    end;
      

  6.   

    一个循环,一个ADOQuery搞定。
    假定表里的内容:(或者通过查询达到)
    ID    ParentID    Names
    01      00       青青小区
    0101    01       1幢
    010101  0101     101室
    02      00       梦幻城市
    0201    02       6幢
    020101  0201     101室
    03      00       金亭晚秋
    var
      Node0, Node1, Node2, Node3: TTreeNode;
      i: Integer;
      ID1, ID2: string;
    begin
      TreeView1.Items.BeginUpdate;
      try
        TreeView1.Items.Clear;
        Node0 := TreeView1.Items.AddChildFirst(nil, '全部楼层');
        with ADOQuery1 do
        begin
          Close;
          SQL.Text := 'select * from Table1 order by ID';  //一定要order by ID,必须是排序好的
          Open;
          while not EOF do
          begin
            Node1 := TreeView1.Items.AddChild(Node0, FieldByName('Names').AsString);
            ID1 := FieldByName('ID').AsString;
            Next;
            while (not EOF) and (FieldByName('ParentID').AsString = ID1) do
            begin
              Node2 := TreeView1.Items.AddChild(Node1, FieldByName('Names').AsString);
              ID2 := FieldByName('ID').AsString;
              Next;
              while (not EOF) and (FieldByName('ParentID').AsString = ID2) do
              begin
                Node3 := TreeView1.Items.AddChild(Node2, FieldByName('Names').AsString);
                Next;
              end;
            end;
          end;
        end;
      finally
        TreeView1.Items.EndUpdate;
      end;
    end;
      

  7.   

    楼上仁兄的代码已经够了,我觉得关键是数据库的设计,父节点和子节点怎么连接,然后用循环就可以实现你的目的了。
    楼主也可以选择dbtreeview控件,只要指定了父节点和子节点就可以显示出来。
      

  8.   

    真正的关键点只有两个:
    一是在表中要有层级概念。像青青小区是一级子节点、1幢是二级子节点、101是三级,依此类推。表中要有这样的字段能体现出来。二是在节点扩展时,写代码:根据当前节点的层级(level)来获得子结点并添加子结点即可。
      

  9.   

    谢谢各位的回贴,问题已经解决了,我的方法是借鉴了GDTOPONE和Corn1的代码,但是跟他们还是有点不同,用户信息表我增加了一个字段,这个字段是由小区+楼幢+单元号组成的,我按这个索引处理:
      with adrqQuery1 do
      try
        SQL.Clear;
        SQL.Text := 'select * from TB_USERINFO order by NODEID';
        Open;    if IsEmpty then Exit;    First;    Nodea := rztvMainFrm.Items.AddChildFirst(nil, '全部小区');    AreaName := FieldByName('AREANAME').AsString;
        HouseName := FieldByName('HOUSENAME').AsString;
        HouseNo := FieldByName('HOUSENO').AsString;
        Nodeb := rztvMainFrm.Items.AddChild(Nodea, FieldByName('AREANAME').AsString);
        Nodec := rztvMainFrm.Items.AddChild(Nodeb, FieldByName('HOUSENAME').AsString);
        rztvMainFrm.Items.AddChild(Nodec,FieldByName('HOUSENO').AsString);    Next;
        while not Eof do
        begin
          AreaName1 := FieldByName('AREANAME').AsString;
          HouseName1 := FieldByName('HOUSENAME').AsString;
          HouseNo1 := FieldByName('HOUSENO').AsString;      if AreaName <> AreaName1 then
             Nodeb := rztvMainFrm.Items.AddChild(Nodea, FieldByName('AREANAME').AsString);      if HouseName <> HouseName1 then
             Nodec := rztvMainFrm.Items.AddChild(Nodeb, FieldByName('HOUSENAME').AsString);      rztvMainFrm.Items.AddChild(Nodec,FieldByName('HOUSENO').AsString);      AreaName := AreaName1;
          HouseName := HouseName1;
          HouseNo := HouseNo1;      Next;
        end;
      except
        on E:Exception do
        begin
          ShowMessage('刷新用户列表数据出错,出错原因是' + #13 + #10 + E.Message);
          Exit;
        end;
      end;
    以上代码设计还是有点累赘的但是项目任务时间紧,就此结贴,谢谢各位朋友的帮忙!