2011-12-13 35 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;