各位大虾,我想把TreeView控件的某一父节点下的所有子节点移动到其他子节点或父节点中,但是我只能移动父节点一个节点,我应该如何做呢?非常感谢大家!
代码如下:
procedure TAFX_dw_basic.TreeView1DragDrop(Sender, Source: TObject; X,
  Y: Integer);
var
  mynode:TTreenode;
begin
  try
    Screen.Cursor := crHourGlass;
    if drag_flag=false then exit;
    d_node:=Treeview1.DropTarget;   //拖放的目的节点
    if d_node=nil then exit;
    //如果源节点和目的节点相同,则什么也不做
    if pdw(d_node.Data)^.dwid=getupid(drag_start) then exit;
    if MessageDLG('确定要移动吗?',mtConfirmation, [mbYes, mbNo], 0) = mrYes then
    begin
      if d_node.HasChildren then
        drag_end:=next_id(pdw(d_node.Data)^.dwid)
      else
        drag_end:=pdw(d_node.Data)^.dwid+'001';
      ClientDataSet_dw.Locate('dw_id',drag_start,[loCaseInsensitive]);
      ClientDataSet_dw.Edit;
      ClientDataSet_dw.FieldByName('dw_id').value:=drag_end;
      new(p_dw);
      p_dw^.dwid:=drag_end;
      p_dw^.dwname:=gloabnode.Text;
      mynode:=Treeview1.Items.AddChild(d_node,p_dw^.dwname);
      mynode.Data:=p_dw;
      gloabnode.Delete;
      UpdateDWID(drag_end,drag_start);
    end;
  finally
  drag_flag:=false;
  Screen.Cursor := crDefault;
  end;
end;
///////////////////////////////////
变量:drag_flag:boolean; //拖拽标志
       drag_start,drag_end:string[21];  //拖拽值
          d_node:TTreenode;       //拖拽node

解决方案 »

  1.   

    你的代码混乱,无逻辑,阅读困难。最好重写。
    给你点建议
    判断能否Drop不应该像你那样,应该在DragOver事件中判断
    procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    这个ACcept就表示能否接受拖放目标。给个简单的例子你参考。procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
     State: TDragState; var Accept: Boolean);
     function IsChild(TNode,SNode:TTreeNode):boolean;
     var
       TempNode: TTreeNode;
     begin
       if TNode = SNode then
       begin
         Result := True;
         exit;
       end;
       tempNode := Tnode.Parent;
       while Assigned(TempNode) do
       begin
         if TempNode = sNode then
         begin
           Result := true;
           exit;
         end;
         tempNode := tempnode.Parent;
       end;
       Result := False;
     end;
    var
     TargetNode: TTreeNode;
    begin
     TargetNode := TreeView1.DropTarget;
     if (Sender = TreeView1) and Assigned(TargetNode) then
     begin
            //检查目标是否合法
       if IsChild(TargetNode,treeview1.Selected) or (TreeView1.Selected.Parent = TargetNode) then
         accept := false
       else
         Accept := true;
     end   { (Sender = TreeView1) and Assigned(TargetNode)  }end;
    procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
    var
     AttachMode: TNodeAttachMode;
    begin
     with TreeView1 do
     begin
       if Not Assigned(Selected) then Exit;
       if Assigned(DropTarget.Data) then    //如果是目标是叶节点
         AttachMode := naInsert             //插入
       else
         AttachMode := naAddChild;          //否则加为子节点
       Selected.MoveTo(DropTarget, AttachMode);
       Selected.MakeVisible;    
     end;
    end;
      

  2.   

    一个很笨的方法,提供思路,紧供参考:
    找到当前节点的节点号,然后在找到当前节点的兄弟几点的节点号,记录当前节点的partent节点,然后重新填加。
    其实要是有数据库就好了,可以重新生成文本在load 就可以了
      

  3.   

    procedure TFrmArea.tvAreaDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    var
       targetnode,sourcenode: TTreenode;
    begin
       targetnode := tvArea.getnodeat(x,y);
       if (Source = Sender) and (targetnode <> nil) then //保证移动在TreeView上,且目标节点不为空
       begin
          Accept := true;
          sourcenode := tvArea.selected;
          //以下代码防止用户将一个选项拖到其子项上(它会随着选项一起移动,导致死循环)
          while (targetnode.parent <> nil) and (targetnode <> sourcenode) do
             targetnode := targetnode.parent;
          if (targetnode = sourcenode) then Accept := false;
       end
       else Accept := false;
    end;procedure TFrmArea.tvAreaDragDrop(Sender, Source: TObject; X, Y: Integer);
    var
       targetnode,sourcenode:  TTreenode;
       SqlStr:  String;
       targetNodeInf: PAreaNodeInf;  //目的节点
       sourcenodeInf : PAreaNodeInf; //目标节点
    begin   targetnode := tvArea.getnodeat(x,y); //获得目的节点
       sourcenode := tvArea.selected; //获得目标节点
       New(targetNodeInf);
       New(sourcenodeInf);   sourcenodeInf:= sourcenode.Data;
       targetNodeInf := targetNode.Data;   //修改数据库中当前节点的父节点号parent_id,使其等目标节点标识号;
       SqlStr:='update Area set Area_UC= '''+targetNodeInf.Area_CC+''''+
                                           ' Where Area_CC ='''+sourcenodeInf.Area_CC+'''';   with  DMArea.adocmdArea do
       begin
          CommandText := SqlStr;
          try
             Execute;
          except
          on E :exception do
          begin
             Showmessage('修改地域出错!');
             Exit;
          end;
          end;
       end;   tvArea.items.beginupdate; //禁用TreeView重绘操作
       try
          copynodeunder(tvArea,sourcenode,targetnode); //启动移动过程
          tvArea.selected := targetnode;
       finally
          tvArea.items.endupdate; //重新设置
       end;
    end;
    ////copy树
    procedure TFrmArea.CopyNodeUnder(Treeview: TTreeview; Sourcenode,
      TargetNode: TTreeNode; i: integer);
    var
       NewNode: Ttreenode;
       j: integer;
    begin
       NewNode:=treeview.items.addchildfirst(targetnode,''); //建立目标项
       NewNode.assign(SourceNode); //复制源项属性
       for j:=sourcenode.count-1 downto 0 do //递归调用,按倒序移动其所有子项
          CopyNodeUnder(treeview,sourcenode.item[j],newnode);
          //treeview.items.delete(sourcenode); //删除源项
    end;