2011-12-13 22 views
5

Tengo una lista de nodos. Me gustaría agregar una característica de arrastrar y soltar para reorganizar, pero no sé cómo hacer esto.VirtualTreeview arrastrar y soltar para organizar los nodos en una lista

Intenté usar el evento OnDragDrop de TVirtualStringTree, pero no pude resolverlo. Miré la documentación y lamentablemente no hay un código de muestra mínimo allí para arrastrar y soltar nodo normal.

Tenga en cuenta que solo se trata de una lista de un solo nivel. Sin jerarquía. :)

+0

Depende de lo que se ha construido el árbol. Proporcione más información sobre eso. – Linas

+0

Todo está almacenado en los datos de PVirtualNode, si eso es lo que quieres decir? Es como una vista de lista en realidad. – Jeff

Respuesta

11

Si usted está recibiendo datos a través de GetNodeData que su arrastrar y soltar podrían implementarse como esto:

uses 
    ActiveX; 

eventos de arrastre Asignar al árbol:

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; 

Tampoco se olvide de establecer toAutoDeleteMoveNodes a False en TreeOptions.AutoOptions.

+0

Gracias! ¡Funciona perfectamente! :) – Jeff

+0

¿Alguna idea sobre cómo mover varios nodos (en una lista de un solo nivel)? Intenté obtener todos los nodos seleccionados, no solo el 'FocusedNode', pero con poco éxito. Aunque SelectedCount es mayor que 1 y 'GetFirstSelected' devuelve' FocusedNode', 'GetNextSelected' devuelve nil. – DarkByte

+0

@Linas: ¿cómo lograrías que esto funcione junto con tu código svTrees? Al usar esto con la solución que publicó en "Estructura de datos tipo árbol (para uso con VirtualTreeview)", parece que solo está actualizando el VSTree y no la estructura de datos subyacente. – TheSteven

0

múltiples nodos de arrastrar y soltar:

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; 
Cuestiones relacionadas