欢迎大家讨论TreeView,无限级(或者有限级),如何设计和实现。
以前用DBTreeView,不是很理想。
欢迎各位朋友讨论。

解决方案 »

  1.   

    http://topic.csdn.net/u/20080703/17/e6cbf9be-dccf-448b-bb4c-a41ca1c48eae.html排版不好看,有点乱,有点多...不过效果还行,没有拖动功能
      

  2.   

    递归,如果数据量很大,就根据选择的node逐步加载
      

  3.   

    好像没有多少东西可以讨论的,都差不多吧。关键看数据库怎么设计一般用id和pid,
    有些设计是只用id,比如父节点的id是01,然后id是0101,0102....的就是它的子节点
      

  4.   


    procedure TCustFormX.LoadGroupDir(billid: Integer; node: TTreeNode);
    var
      i: Integer;
      nodechild, nodeparent: TTreeNode;
    begin
      AGroupFram.tvGroup.Items.BeginUpdate;
      if billid = 0 then
      begin
        if node = nil then
        begin
          for i := 0 to AGroupDirs.Count - 1 do
          begin //根节点
            if TAGroupDir(AGroupDirs[i]).Parent = 0 then
            begin
              nodeparent := AGroupFram.tvGroup.Items.Add(node, TAGroupDir(AGroupDirs[i]).CName);
              nodeparent.Data := AGroupDirs[i];
              LoadGroupDir(billid, nodeparent);
            end;
          end;
        end
        else
        begin
          for i := 0 to AGroupDirs.Count - 1 do
          begin //子节点
            if TAGroupDir(AGroupDirs[i]).Parent = TAGroupDir(node.Data).TreeId then
            begin
              nodechild := AGroupFram.tvGroup.Items.AddChild(node, TAGroupDir(AGroupDirs[i]).CName);
              nodechild.Data := AGroupDirs[i];
              LoadGroupDir(billid, nodechild);
            end;
          end;
        end;
      end
      else
      begin
        if node = nil then
        begin
          for i := 0 to AGroupDirs.Count - 1 do
          begin //根节点
            if (TAGroupDir(AGroupDirs[i]).Parent = 0) and (TAGroupDir(AGroupDirs[i]).BillId = billid) then
            begin
              nodeparent := AGroupFram.tvGroup.Items.Add(node, TAGroupDir(AGroupDirs[i]).CName);
              nodeparent.Data := AGroupDirs[i];
              LoadGroupDir(billid, nodeparent);//递归调用
            end;
          end;
        end
        else
        begin
          for i := 0 to AGroupDirs.Count - 1 do
          begin //子节点
            if (TAGroupDir(AGroupDirs[i]).Parent = TAGroupDir(node.Data).TreeId) and (TAGroupDir(AGroupDirs[i]).BillId = billid) then
            begin
              nodechild := AGroupFram.tvGroup.Items.AddChild(node, TAGroupDir(AGroupDirs[i]).CName);
              nodechild.Data := AGroupDirs[i];
              LoadGroupDir(billid, nodechild));//递归调用
            end;
          end;
        end;
      end;
      AGroupFram.tvGroup.Items.EndUpdate;
      AGroupFram.tvGroup.FullExpand;
    end;
      

  5.   

    用递归 和 只用id,比如父节点的id是01,然后id是0101,0102....的就是它的子节点,
    不知道这两个方案哪个更合适一些。深入思考中。比如这样的结构:中国大陆,华南区,广东,广州。
      

  6.   

    一般是递归,节点数量太大就不要用,用一级缓冲按需生成。如果是数据库结果是这样的,不需要递归也可:
    01
    0101
    0102
    010201
    02
    0201
    ...
    因为只要一排序,父节点总在子节点前面,只要看自身id的长度跟上一条id的长度关系就知道是父子还是兄弟了
      

  7.   

    用id和pid比较方便些,如果数据量比较大还是不要用递归。
      

  8.   

    谢谢各位,深入思考中。树的数据量不大,组织结构树。另外,点击节点时候,判断该节点的ID,目前的方法是根据节点的text值,select数据库中的id,但这样有个问题,不同分支的节点,很有可能text相同。有没有更好的办法获得节点的ID。
      

  9.   

    你把加上去的每个节点的.data都给附上数据库中的id,
    到你选择的时候,你把它的data取出来,取到id就可以啦,
    data的类型为指针,你最好构造一个Record,再定义一个指针。type 
      PR : ^R ;
      R = record 
       id : integer ; //id 
       NodeText : string ;//节点Text值
    end ;var
    p : PR ;
    node : TTreeNode ;
    begin
      new(p) ; try
      p^.id := .. ;
      p^.NodeText := .. ;
      node := TreeView1.Items.Add(....) ;或者  node := TreeView1.Items.AddChild(....) ;
      node.Data :=  p ;end; 
      

  10.   

    你把加上去的每个节点的.data都给附上数据库中的id, 
    到你选择的时候,你把它的data取出来,取到id就可以啦, 
    data的类型为指针,你最好构造一个Record,再定义一个指针。 type 
      PR : ^R ; 
      R = record 
      id : integer ; //id 
      NodeText : string ;//节点Text值 
    end ; var 
    p : PR ; 
    node : TTreeNode ; 
    begin 
      new(p) ; try 
      p^.id := .. ; 
      p^.NodeText := .. ; 
      node := TreeView1.Items.Add(....) ;或者  node := TreeView1.Items.AddChild(....) ; 
      node.Data :=  p ; 
    finally 
     dispose(p) ;
    end; end; 
    读取时,
    var 
    p : PR ; 
    id :integer ;
    nodeText : String ; 
    begin 
      new(p) ; 
    try 
     if TreeView1.Selected <> nil then 
    begin
      if (TreeView1.Selected.Data <> nil ) then 
       betin 
      p :=(PR)TreeView1.Selected.Data ;
      id := p^.id  ;
      nodeText := p^.NodeText ;
       end; 
    end;  
    finally 
     dispose(p) ;
    end; end;直接在这里面写的,你自己看看,我也不知道有没有问题,家里没有环境写。 
      

  11.   

    treeview里面数据多了,慢的很,级次多了也不好,3-5级即可,最好用编码位数控制级次
      

  12.   

    cai5大侠你好,能否解释一下那几个在该函数中没有定义的变量?非常感谢
      

  13.   

    AGroupFram.tvGroup: 是TTreeView;AGroupDirs:是一个结构或者类 ,用于存放Data的,你自己需要把什么放到data中,就定义什么样子的其他的就没什么啦 。