这是我上一个问题的延续,我的TreeView有三级:
--小区
  --青青家园
    --1幢
      --101
     --201
   --2幢
      --101
  --幻境佳居
    --2幢
      --201
    --5幢
      --101
这是一个由小区-楼幢-单元号组成的树,前面都有多选框,我现在要在右边的listview中显示TreeView中选中的用户信息内容,我已经试过好几过遍历树的方法,但是都不行,所以想请教这里的朋友,帮忙给个思路,谢谢! 

解决方案 »

  1.   

    treeview是标准控件吗,checkbox是自己加的吗
      

  2.   


    不是标准,就是你上次发给我的那个TRzCheckView
      

  3.   


    ...
    Case Treeview.Selected.Level of
    0:SQL....
    1:SQl....
    2:SQL....
    End;
    ...
    不管什么控件,相信Selected.Level都是差不多的
    我用的是标准控件
      

  4.   

    SQL可以这样取值:SQL.Add('WHERE 自段A ='''+TreeView.Selected.Text+'''');
      

  5.   


    ...
    Case Treeview.Selected.Level of
    0:SQL.Add('WHERE 小区 ='''+TreeView.Selected.Text+'''');
    1:SQL.Add('WHERE 家园 ='''+TreeView.Selected.Text+'''');
    2:SQL.Add('WHERE 住房 ='''+TreeView.Selected.Text+'''');
    End;
    ...
      

  6.   


    代码还没写呢,写过几个都不对,删了。我原先的思路是这样的,遍历Treeview,如果选中的是一级也就是小区级的,那么直接到表中查这个小区的记录,然后再查TreeView的下一个小区级Node,如果没选中,那么再查它的下一级楼幢级是否选中,有则根据小区+楼幢查记录到listView中,没有则继续判下一级单元号是否有选中,没有就查下一个单元号,有就根据小区+楼幢+单元号查记录,我觉的这个思路虽然不是最佳,但也不会错,没想到却是在遍历问题上一直没搞定,我试了一种最简单的遍历:for I:=0 to Treeview.Items.Count - 1 do
    begin
      str := Treeview.Items[i].Text;
      n := TreeView.Items[I].Level;
      b := TreeView.Items[I].Selected;
    end;好象Level和Selected我这样的用法是不对的,因为F8的过程中没想到结果.
    我后来又试了一种:
    function TForm1.AllOverTreeView(node:TTreenode):TTreenode;
    begin
      while node<>nil do
        begin
          if node.HasChildren then
            begin
              node:=node.getFirstChild;
              allovertreeview(node);
              node:=node.Parent;
            end;
          if node.getNextSibling<>nil then
            node:=node.getNextSibling
          else
            exit;
        end;
    end;
    但是我觉的这种在最后一级子节点多的情况下是有问题的,于是我改了一下代码,确实我的方法能把第一个节点的第三级能全部都遍历到,但是这个第三级遍历完却找不到条件回上一级也就是回到楼幢级轮询了。
      

  7.   

    应该使用递归算法,这是我写的遍历树,生成菜单的代码,树可以是多级的,你自己改改应该就行了
    procedure TForm1.Button1Click(Sender: TObject);
    var
      i,j:Integer;
    begin
      i:=self.TreeView1.Items.Count;
      for j:=0 to i-1 do
      begin
        if self.TreeView1.Items.Item[j].Parent=nil then
          self.createmenu(self.MainMenu1.Items,self.TreeView1.Items.Item[j]);
      end;
    end;procedure TForm1.createmenu(mainitem: TMenuItem; tr: TTreeNode);
    var
      s:string;
      newitem:TMenuItem;
      i,j:Integer;
    begin
      s:=tr.Text;
      newitem:=TMenuItem.Create(mainitem);
      newitem.Caption:=s;
      mainitem.Add(newitem);
      i:=tr.Count;
      if i=0 then
        Exit;
      for j:=0 to i-1 do
        self.createmenu(newitem,tr.Item[j]);
    end;
      

  8.   

    是有复选框的? 明白你的意思了.可惜没接触过,不过看你的意图,跟三层循环意思一样的.
    不可以写成3层循环吗? 违码:
    For i:=0 to Level[0].Count do
      begin
        if Checked then
          begin
            ...
            For j:=0 to Level[1].Count do
              begin
                if Checked then
                  begin
                    ...
                    For k:=0 to Level[2].Count do
                      if Checked then ...
                  end;
              end;
           end;
      end;
      

  9.   


    我原先就是写成类似于你写的这个代码,但是我到后来发现在最后一级也就level3上循环跳不到level2了,我也换过用递归,但是总没写成一个可以用的
      

  10.   


    procedure TForm1.Button1Click(Sender: TObject);
    var
      i:Integer;
    begin
      Memo1.Clear;
      for i:=0 to Treeview.Items.Count-1 do
      begin
        //if TreeView.Items[i].Checked then //如果你的那个是这种复选框的话
        Case TreeView.Items[i].Level of
        0:Memo1.Lines.Add(Treeview.Items[i].Text);
        1:Memo1.Lines.Add(' '+Treeview.Items[i].Text);
        2:Memo1.Lines.Add('  '+Treeview.Items[i].Text);
        End;
      end;
    end;我试了下,这样就可以遍历整个树
      

  11.   


    procedure TRES_BOM_VIEW_F.cx_TVChange(Sender: TObject; Node: TTreeNode);
    begin
      inherited;
      if (cx_TV.Parent<>nil) and Assigned(cx_TV.Selected) and (cx_TV.Selected.Level=1) and (cxPageControl1.ActivePage=cxTabSheet5) then //機種不同明細
      begin
        try
          RES_LOADING_F:=TRES_LOADING_F.Create(Self);
          RES_LOADING_F.Label1.Caption:='正在檢索機種明細數據......';
          RES_LOADING_F.Show;
          RES_LOADING_F.Update;
          Application.ProcessMessages;
          adoq_information.Close;
          adoq_information.SQL.Text:='SELECT A.PARN_TYP,A.PARN_LITM,B.PARN_DSC,B.CHLD_LITM,B.CHLD_DSC,B.EFT_FROM,B.EFT_TO,B.QYT,B.LOCATOR,B.PIN_NO,B.ECO_NO '+
                                   ' FROM RES_BOM_LH A LEFT JOIN (SELECT CHLD_LITM,MAX(PARN_DSC)AS PARN_DSC,MAX(EFT_FROM)AS EFT_FROM,MAX(EFT_TO)AS EFT_TO,MAX(CHLD_DSC)AS CHLD_DSC,MAX(QYT)AS QYT,MAX(LOCATOR)AS LOCATOR,MAX(PIN_NO)AS PIN_NO,MAX(ECO_NO)AS ECO_NO '+
                                   ' FROM RES_BOM_LH GROUP BY CHLD_LITM)B ON A.PARN_LITM=B.CHLD_LITM WHERE PARN_TYP='''+ VarToStr(cx_TV.Selected.Text)+''' GROUP BY A.PARN_TYP,A.PARN_LITM,B.PARN_DSC,B.CHLD_LITM,B.CHLD_DSC,B.EFT_FROM,B.EFT_TO,B.QYT,B.LOCATOR,B.PIN_NO,B.ECO_NO ORDER BY A.PARN_LITM';
          adoq_information.Open;
          cxGrid5DBBandedTableView1Column1.DataBinding.FieldName:='';
          cxGrid5DBBandedTableView1Column2.DataBinding.FieldName:='PARN_TYP';
          cxGrid5DBBandedTableView1Column3.DataBinding.FieldName:='PARN_DSC';
          cxGrid5DBBandedTableView1Column4.DataBinding.FieldName:='PARN_LITM';
          cxGrid5DBBandedTableView1Column5.DataBinding.FieldName:='CHLD_DSC';
          cxGrid5DBBandedTableView1Column6.DataBinding.FieldName:='EFT_FROM';
          cxGrid5DBBandedTableView1Column7.DataBinding.FieldName:='EFT_TO';
          cxGrid5DBBandedTableView1Column8.DataBinding.FieldName:='ECO_NO';
          cxGrid5DBBandedTableView1Column9.DataBinding.FieldName:='LOCATOR';
          cxGrid5DBBandedTableView1Column10.DataBinding.FieldName:='PIN_NO';
          cxGrid5DBBandedTableView1Column11.DataBinding.FieldName:='QYT';
          Application.ProcessMessages;
        finally
          RES_LOADING_F.Close;
        end;
      end;  if (cx_TV.Parent<>nil) and Assigned(cx_TV.Selected) and (cxPageControl1.ActivePage=cxTabSheet7) then //IQC異常信息
      begin
        try
          RES_LOADING_F:=TRES_LOADING_F.Create(Self);
          RES_LOADING_F.Label1.Caption:='正在檢索相關數據......';
          RES_LOADING_F.Show;
          RES_LOADING_F.Update;
          Application.ProcessMessages;
          adoq_linev.Close;
          adoq_linev.SQL.Text:='select distinct b.parn_litm,a.* from openquery(svr_iqcjl,''select * from LineHis'') a left join res_bom_lh b on a.cplh=b.parn_litm '+
                               ' where b.parn_litm in (select distinct parn_litm from res_bom_lh union all select distinct chld_litm from res_bom_lh) and cplh='''+ VarToStr(cx_TV.Selected.Text)+''' order by errdate desc';
          adoq_linev.Open;
          cxGrid7DBBandedTableView1Column1.DataBinding.FieldName:='autoid';
          cxGrid7DBBandedTableView1Column2.DataBinding.FieldName:='bh';
          cxGrid7DBBandedTableView1Column7.DataBinding.FieldName:='cplh';
          cxGrid7DBBandedTableView1Column8.DataBinding.FieldName:='custname';
          cxGrid7DBBandedTableView1Column11.DataBinding.FieldName:='linecode';
          cxGrid7DBBandedTableView1Column12.DataBinding.FieldName:='errdate';
          cxGrid7DBBandedTableView1Column10.DataBinding.FieldName:='errproduct';
          cxGrid7DBBandedTableView1Column9.DataBinding.FieldName:='descript';
          cxGrid7DBBandedTableView1Column6.DataBinding.FieldName:='yjdc';
          cxGrid7DBBandedTableView1Column3.DataBinding.FieldName:='fx';
          cxGrid7DBBandedTableView1Column4.DataBinding.FieldName:='errpresent';
          cxGrid7DBBandedTableView1Column5.DataBinding.FieldName:='pm';
          Application.ProcessMessages;
        finally
          RES_LOADING_F.Close;
        end;
      end
      else
      begin
        try
          RES_LOADING_F:=TRES_LOADING_F.Create(Self);
          RES_LOADING_F.Label1.Caption:='正在檢索相關數據......';
          RES_LOADING_F.Show;
          RES_LOADING_F.Update;
          Application.ProcessMessages;
          adoq_linev.Close;
          adoq_linev.SQL.Text:='select distinct b.parn_litm,a.* from openquery(svr_iqcjl,''select * from LineHis'') a left join res_bom_lh b on a.lh=b.parn_litm '+
                               ' where b.parn_litm in (select distinct parn_litm from res_bom_lh union all select distinct chld_litm from res_bom_lh) and lh='''+ VarToStr(cx_TV.Selected.Text)+''' order by errdate desc';
          adoq_linev.Open;
          cxGrid7DBBandedTableView1Column1.DataBinding.FieldName:='autoid';
          cxGrid7DBBandedTableView1Column2.DataBinding.FieldName:='bh';
          cxGrid7DBBandedTableView1Column7.DataBinding.FieldName:='lh';
          cxGrid7DBBandedTableView1Column8.DataBinding.FieldName:='custname';
          cxGrid7DBBandedTableView1Column11.DataBinding.FieldName:='linecode';
          cxGrid7DBBandedTableView1Column12.DataBinding.FieldName:='errdate';
          cxGrid7DBBandedTableView1Column10.DataBinding.FieldName:='errproduct';
          cxGrid7DBBandedTableView1Column9.DataBinding.FieldName:='descript';
          cxGrid7DBBandedTableView1Column6.DataBinding.FieldName:='yjdc';
          cxGrid7DBBandedTableView1Column3.DataBinding.FieldName:='fx';
          cxGrid7DBBandedTableView1Column4.DataBinding.FieldName:='errpresent';
          cxGrid7DBBandedTableView1Column5.DataBinding.FieldName:='pm';
          Application.ProcessMessages;
        finally
          RES_LOADING_F.Close;
        end
      end;  
    end;
      

  12.   

    icegirl914 ,你最终需要得到怎样一个效果,举个例子说明一下,也好帮你写代码
      

  13.   


    procedure TForm1.Button1Click(Sender: TObject);
    var
      i:Integer;
    begin
      Memo1.Clear;
      for i:=0 to Treeview.Items.Count-1 do
      begin
        Case TreeView.Items[i].Level of
        0:Memo1.Lines.Add(Treeview.Items[i].Text);
        1:Memo1.Lines.Add(Treeview.Items[i].Parent.Text+' '+Treeview.Items[i].Text);
        2:Memo1.Lines.Add(Treeview.Items[i].Parent.Parent.Text+' '+Treeview.Items[i].Parent.Text+' '+Treeview.Items[i].Text);
        End;
      end;
    end;应该能满足你的需求了,能把三级的条件都取到
    不过说实话,效率不咋滴,期待更效率的案子.
      

  14.   

    我想要实现的:
    1、在TreeView上选择想要查询的用户(这个用户可以根据小区/小区+楼幢/小区+楼幢+单元号从用户信息表中查询出来);
    2、点中一个导入用户列表的按钮;
    3、ListView中显示满足Treeview中条件的记录
      

  15.   

    Case 前加上你那个多选框的判断不就可以了?
      

  16.   


     for i:=0 to rztvMainFrm.Items.Count-1 do
      begin
        if rztvMainFrm.Items[i].Selected then
        begin
          Case rztvMainFrm.Items[i].Level of
            1:ShowMessage(rztvMainFrm.Items[i].Text);
            2:ShowMessage(rztvMainFrm.Items[i].Parent.Text+' '+rztvMainFrm.Items[i].Text);
            3:ShowMessage(rztvMainFrm.Items[i].Parent.Parent.Text+' '+rztvMainFrm.Items[i].Parent.Text + '' +rztvMainFrm.Items[i].Text);
          else
            ShowMessage('没有选中');
          end;
        end;      
      end;我用这个代码试了,只能得到最后一个选中的内容,前面几个选中的都没有显示
      

  17.   


    procedure TForm1.Button1Click(Sender: TObject);
    var
      Node1,Node2,Node3:TTreeNode;
    begin
      Memo1.Clear;
      Node1:=Treeview1.Items.GetFirstNode;
      while Node1.getNextSibling<>nil do
      begin
        Node2:=Node1.getFirstChild;
        while Node2.getNextSibling<>nil do
        begin
          Node3:=Node2.getFirstChild;
          Memo1.Lines.Add(Node3.Text);
          while Node3.getNextSibling<>nil do
          begin
            Memo1.Lines.Add(Node3.Text);
            Node3:=Node3.getNextSibling;
          end;
          Node2:=Node2.getNextSibling;
        end;
        Node1:=Node1.getNextSibling;
      end;
    end;
    实现你要的全遍历.
      

  18.   


    复选框的判断是用Selected? //Selected 是判断是否为当前焦点的吧
    不是Checked?
      

  19.   


    while Node3.getNextSibling<>nil do
    begin
      Node3:=Node3.getNextSibling;
      Memo1.Lines.Add(Node3.Text);
    end;
    我之前代码第三级循环里操作写反了
      

  20.   

    你要的效果不就是迅雷在下载文件时用的那个列表控件嘛!有许多第三方控件可以实现,但控件包太太,而且集成的控件太多,或者有些你根本用不上。我有一个仅实现ListView中以Treeview显示记录的控件可以给你,请留下你的QQ我发给你。
      

  21.   

    非常感谢hduhjh你的帮忙,但是这个代码还是有问题的
      

  22.   

    procedure TMainFrm.ToolButton1Click(Sender: TObject);
    var
      Node, Node1: TTreeNode;
    begin
      //得到首节点
      Node := rztvMainFrm.Items.GetFirstNode;
      //得到小区的首节点
      Node := Node.getFirstChild;
      while Node <> nil do
      begin
        Node := Node.GetFirstChild;      //楼幢
        //判
        while Node <> nil do
        begin
          if Node.HasChildren then
          begin
            Node := Node.getFirstChild;
            //以下读单元号
             while Node.getNextSibling <> nil do
              Node := Node.getNextSibling;
          end;
          Node := Node.Parent;
          Node1 := Node;          //保存上一个楼幢Node
          Node := Node.getNextSibling;
        end;
        Node := Node1;    Node := Node.Parent;
        Node := Node.getNextSibling;
      end; 
    end;我用上面的代码实现了我所需要的遍历
      

  23.   

    现在还要实现的就是判选中,然后根据条件在ListView显示
      

  24.   

    为什么明明选 中了,但是我用if Node.Selected then ShowMessage('选中');这句话来判却是Selected是False?
      

  25.   

    说过了的,复选框的选取肯定不是Selected.//Selected表示选中,而不是选取
    像TCheckBox,它的判断就是CheckBox.Checked
    其他很多类似都是用Checked,而不是Selected.
      

  26.   

    楼上的说的对是我弄错了,这个贴子的问题已经解决了,虽然代码不优有点啰嗦,但是对我而言是目前解决问题的方法:
    procedure TMainFrm.ToolButton1Click(Sender: TObject);
    var
      Node, Node1: TTreeNode;
      Str: String;
    begin
      //得到首节点
      Node := rztvMainFrm.Items.GetFirstNode;  //得到小区的首节点
      Node := Node.getFirstChild;                       //和睦小区
      while Node <> nil do
      begin
        if GetTreeNodeChecked(Node) then
        begin
          AddUserInfoToListView(Node.Text, '', '', 0);  //选中小区级
        end else
        begin
          Node := Node.GetFirstChild;
          Node1 := Node;
          //1幢
          while Node <> nil do
          begin
            if GetTreeNodeChecked(Node) then
            begin
              AddUserInfoToListView(Node.Parent.Text,Node.Text, '', 1)
            end else
            begin
              if Node.HasChildren then
              begin
                Node := Node.getFirstChild;
                if GetTreeNodeChecked(Node) then
                begin
                  AddUserInfoToListView(Node.Parent.Parent.Text, Node.Parent.Text, Node.Text, 2);
                end;            while Node.getNextSibling <> nil do
                begin
                  Node := Node.getNextSibling;
                  if GetTreeNodeChecked(Node) then
                  begin
                    AddUserInfoToListView(Node.Parent.Parent.Text, Node.Parent.Text, Node.Text, 2);
                  end;
                end;
              end;
              Node := Node.Parent;
              Node1 := Node;
            end;
            Node := Node.getNextSibling;
          end;
          Node := Node1;
          Node := Node.Parent;
        end;
        Node := Node.getNextSibling;
      end;
    end;function TMainFrm.GetTreeNodeChecked(Node: TTreeNode): Boolean;
    var
      vItem : TTVItem;
    begin
      vItem.mask  := TVIF_HANDLE or TVIF_STATE;
      vItem.hItem := Node.ItemId;
      vItem.stateMask := TVIS_STATEIMAGEMASK;
      TreeView_GetItem(Node.TreeView.Handle, vItem);
      Result  := Boolean((vItem.state shr 12)-1);
    end;
      

  27.   

    楼上的说的对是我弄错了,这个贴子的问题已经解决了,虽然代码不优有点啰嗦,但是对我而言是目前解决问题的方法:
    procedure TMainFrm.ToolButton1Click(Sender: TObject);
    var
      Node, Node1: TTreeNode;
      Str: String;
    begin
      //得到首节点
      Node := rztvMainFrm.Items.GetFirstNode;  //得到小区的首节点
      Node := Node.getFirstChild;                       //和睦小区
      while Node <> nil do
      begin
        if GetTreeNodeChecked(Node) then
        begin
          AddUserInfoToListView(Node.Text, '', '', 0);  //选中小区级
        end else
        begin
          Node := Node.GetFirstChild;
          Node1 := Node;
          //1幢
          while Node <> nil do
          begin
            if GetTreeNodeChecked(Node) then
            begin
              AddUserInfoToListView(Node.Parent.Text,Node.Text, '', 1)
            end else
            begin
              if Node.HasChildren then
              begin
                Node := Node.getFirstChild;
                if GetTreeNodeChecked(Node) then
                begin
                  AddUserInfoToListView(Node.Parent.Parent.Text, Node.Parent.Text, Node.Text, 2);
                end;            while Node.getNextSibling <> nil do
                begin
                  Node := Node.getNextSibling;
                  if GetTreeNodeChecked(Node) then
                  begin
                    AddUserInfoToListView(Node.Parent.Parent.Text, Node.Parent.Text, Node.Text, 2);
                  end;
                end;
              end;
              Node := Node.Parent;
              Node1 := Node;
            end;
            Node := Node.getNextSibling;
          end;
          Node := Node1;
          Node := Node.Parent;
        end;
        Node := Node.getNextSibling;
      end;
    end;function TMainFrm.GetTreeNodeChecked(Node: TTreeNode): Boolean;
    var
      vItem : TTVItem;
    begin
      vItem.mask  := TVIF_HANDLE or TVIF_STATE;
      vItem.hItem := Node.ItemId;
      vItem.stateMask := TVIS_STATEIMAGEMASK;
      TreeView_GetItem(Node.TreeView.Handle, vItem);
      Result  := Boolean((vItem.state shr 12)-1);
    end;