2011-12-13 86 views
5

我有一个节点列表。我想添加一个拖放到重新排列的功能,但我不知道如何去做这件事。VirtualTreeview拖放来排列列表中的节点

我尝试使用TVirtualStringTree的OnDragDrop事件,但我无法弄清楚。我查看了文档,可悲的是没有简单的示例代码,用于简单节点拖放。

请注意,这只是一个单级列表。没有层次。 :)

+0

这取决于你如何建立你的树。提供更多的信息。 – Linas

+0

一切都存储在PVirtualNode的数据,如果这就是你的意思?这就像一个实际的列表视图。 – Jeff

回答

11

如果通过GetNodeData比你拖放获取数据可以实现这样的:

uses 
    ActiveX; 

分配拖动事件树:

OnDragAllowed

procedure TForm1.vt1DragAllowed(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; 
    var Allowed: Boolean); 
begin 
    Allowed := True; 
end; 

OnDragOver

procedure TForm1.vt1DragOver(Sender: TBaseVirtualTree; Source: TObject; Shift: TShiftState; 
    State: TDragState; Pt: TPoint; Mode: TDropMode; var Effect: Integer; var Accept: Boolean); 
begin 
    Accept := (Source = Sender); 
end; 

OnDragDrop

procedure TForm1.vt1DragDrop(Sender: TBaseVirtualTree; Source: TObject; DataObject: IDataObject; 
    Formats: TFormatArray; Shift: TShiftState; Pt: TPoint; var Effect: Integer; Mode: TDropMode); 
var 
    pSource, pTarget: PVirtualNode; 
    attMode: TVTNodeAttachMode; 
begin 
    pSource := TVirtualStringTree(Source).FocusedNode; 
    pTarget := Sender.DropTargetNode; 

    case Mode of 
    dmNowhere: attMode := amNoWhere; 
    dmAbove: attMode := amInsertBefore; 
    dmOnNode, dmBelow: attMode := amInsertAfter; 
    end; 

    Sender.MoveTo(pSource, pTarget, attMode, False); 

end; 

也不要忘记设置toAutoDeleteMoveNodes为False TreeOptions.AutoOptions

+0

谢谢!完美的作品! :) – Jeff

+0

有关如何移动多个节点(在单级列表中)的任何想法?我尝试获取所有选定的节点 - 不仅是“FocusedNode” - 但收效甚微。尽管SelectedCount大于1,'GetFirstSelected'返回'FocusedNode','GetNextSelected'返回nil。 – DarkByte

+0

@Linas - 你如何得到这个与你的svTrees代码一起工作?当在“类似树的数据结构(用于VirtualTreeview)”下发布的解决方案中使用它时,它似乎只是更新VSTree而不是基础数据结构 – TheSteven

0

多个节点拖放:

procedure TForm1.vst(Sender: TBaseVirtualTree; 
    Source: TObject; DataObject: IDataObject; Formats: TFormatArray; 
    Shift: TShiftState; Pt: TPoint; var Effect: Integer; Mode: TDropMode); 
var 
    pSource, pTarget: PVirtualNode; 
    attMode: TVTNodeAttachMode; 
    List: TList<PVirtualNode>; 
begin 
    pTarget := Sender.DropTargetNode; 

    case Sender.GetNodeLevel(pTarget) of 
    0: 
     case Mode of 
     dmNowhere: 
      attMode := amNoWhere; 
     else 
      attMode := amAddChildLast; 
     end; 
    1: 
     case Mode of 
     dmNowhere: 
      attMode := amNoWhere; 
     dmAbove: 
      attMode := amInsertBefore; 
     dmOnNode, dmBelow: 
      attMode := amInsertAfter; 
     end; 

    end; 
    List:= TList<PVirtualNode>.create(); 
    pSource := Sender.GetFirstSelected(); 
    while Assigned(pSource) do 
    begin 
    List.Add(pSource); 
    pSource := Sender.GetNextSelected(pSource); 
    end; 

    for pSource in List do 
    Sender.MoveTo(pSource, pTarget, attMode, False); 

List.Free; 
end;