【问题标题】:VirtualTreeview drag and drop to arrange nodes in a listVirtualTreeview拖放以在列表中排列节点
【发布时间】:2011-12-13 10:06:56
【问题描述】:

我有一个节点列表。我想添加一个拖放重新排列功能,但我不知道该怎么做。

我尝试使用 TVirtualStringTree 的 OnDragDrop 事件,但我无法弄清楚。我查看了文档,遗憾的是没有用于普通节点拖放的最小示例代码。

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

【问题讨论】:

  • 这取决于你如何构建你的树。提供更多相关信息。
  • 一切都存储在 PVirtualNode 的数据中,如果这就是你的意思?它实际上就像一个列表视图。

标签: delphi drag-and-drop virtualtreeview


【解决方案1】:

如果您通过 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;

另外不要忘记在TreeOptions.AutoOptions 中将toAutoDeleteMoveNodes 设置为False。

【讨论】:

  • 关于如何移动多个节点(在单级列表中)的任何想法?我尝试获取所有选定的节点——不仅是FocusedNode——但收效甚微。尽管 SelectedCount 大于 1 并且 GetFirstSelected 返回 FocusedNode,但 'GetNextSelected` 返回 nil。
  • @Linas - 你如何让它与你的 svTrees 代码一起工作?当将此与您在“类树数据结构(用于 VirtualTreeview)”下发布的解决方案一起使用时,它似乎只更新了 VSTree 而不是基础数据结构
  • 此外,我发现以下与启用拖放相关的属性 - TreeOptions > MiscOptions > toAcceptOLEDrop=True 和 TreeOptions > MiscOptions > toFullRowDrag=True 以及设置 DragType=dtOLE
【解决方案2】:

多个节点拖放:

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;

【讨论】:

  • 名称具有误导性,但这是OnDragDrop的代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-08
  • 2015-03-14
  • 2010-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-04
相关资源
最近更新 更多