2011-12-13 4 views
5

Ho una lista di nodi. Vorrei aggiungere una funzione drag-and-drop-to-rearrange, ma non so come fare per farlo.VirtualTreeview trascinamento della selezione per organizzare i nodi in un elenco

Ho provato a utilizzare l'evento OnDragDrop di TVirtualStringTree, ma non sono riuscito a capirlo. Ho guardato la documentazione e non c'è purtroppo nessun codice di esempio minimo per il semplice nodo che si trascina.

Si noti che è solo un elenco a livello singolo. Nessuna gerarchia. :)

+0

Dipende da come avete costruito il vostro albero. Fornisci maggiori informazioni a riguardo. – Linas

+0

Tutto è memorizzato nei dati di PVirtualNode, se questo è ciò che intendi? È come una listview in realtà. – Jeff

risposta

11

Se stai ricevendo dati tramite GetNodeData di quanto il tuo drag and drop potrebbero essere attuate in questo modo:

uses 
    ActiveX; 

eventi di trascinamento Assegnare alla struttura ad albero:

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; 

Inoltre non dimenticate di impostare toAutoDeleteMoveNodes False in TreeOptions.AutoOptions.

+0

Grazie! Funziona perfettamente! :) – Jeff

+0

Qualche idea su come spostare più nodi (in un elenco a livello singolo)? Ho provato a ottenere tutti i nodi selezionati - non solo il 'FocusedNode' - ma con scarso successo. Sebbene SelectedCount sia maggiore di 1 e 'GetFirstSelected' restituisca il' FocusedNode', 'GetNextSelected' restituisce nil. – DarkByte

+0

@Linas - come faresti funzionare in combinazione con il tuo codice svTrees? Quando si utilizza questo con la soluzione che hai postato sotto "Struttura ad albero (per l'uso con VirtualTreeview)" sembra che stia aggiornando solo la VSTree e non la struttura dati sottostante – TheSteven

0

nodi multipli drag'n'drop:

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;