4

我想允许用户按照自己的喜好排列 treeView 的节点,但我遇到了很多问题。例如:

  • 在我做了一些拖放后,树视图停止响应,我必须终止应用程序。此外,如果我开始拖动并放弃(按取消,或将其从我选择它的位置放回)应用程序挂起......我无能为力
  • 如果用户想要重新排列作为同一个主节点的子节点的 3 个节点的顺序,他不能像在其他应用程序中那样做。为什么?没有任何方法可以让用户将他的节点放在其他 2 个节点之间吗?Delphi 似乎只允许用户在另一个上面点头。

这不好。我想要这张照片中的行为

在此处输入图像描述

所以Node3的目的地,应该在Node1和Node2之间。当然,节点的放置在顶部应该可用,但是这个 BETWEEN NODES 功能也应该可用。

到目前为止,我的代码是:

procedure TForm3.FormCreate(Sender: TObject);
begin
  tv.FullExpand;
end;

procedure TForm3.tvDragDrop(Sender, Source: TObject; X, Y: Integer);
var
  TargetNode, SourceNode : TTreeNode;
begin
  with TV do
  begin
    TargetNode := GetNodeAt(X,Y); // Get target node
    SourceNode := Selected;
    if (TargetNode = nil) then
    begin
      EndDrag(False);
      Exit;
    end;
    MoveNode(TargetNode,SourceNode);
    SourceNode.Free;
  end;
end;

procedure TForm3.tvDragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  if (Sender = TV) then // If TRUE than accept the draged item
  begin
    Accept := True;
  end;
end;
procedure TForm3.tvEndDrag(Sender, Target: TObject; X, Y: Integer);
begin
  TV.Repaint;
end;

procedure TForm3.tvMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  tv.BeginDrag(false,-1);
end;

Procedure TForm3.MoveNode(TargetNode, SourceNode : TTreeNode);
var
  nodeTmp : TTreeNode;
  i : Integer;
begin
  with TV do
  begin
    nodeTmp := Items.AddChild(TargetNode,SourceNode.Text);
    for i := 0 to SourceNode.Count -1 do
    begin
      MoveNode(nodeTmp,SourceNode.Item[i]);
    end;
  end;
end;

当然,电视是 TTreeView。

4

1 回答 1

13

首先,扔掉你目前拥有的所有代码。漏洞太多,不值得讨论。

为此所需的最少代码如下:

procedure TMyForm.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
  Src, Dst: TTreeNode;
begin
  Src := TreeView1.Selected;
  Dst := TreeView1.GetNodeAt(X,Y);
  Src.MoveTo(Dst, naAdd);
end;

procedure TMyForm.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
var
  Src, Dst: TTreeNode;
begin
  Src := TreeView1.Selected;
  Dst := TreeView1.GetNodeAt(X,Y);
  Accept := Assigned(Dst) and (Src<>Dst);
end;

您需要为树视图设置DragMode为。dmAutomatic而且您还需要将这两个事件连接到OnDragDropOnDragOver

如果您希望在 drop 中实现不同的逻辑来处理作为兄弟(之前或之后)添加,或者作为子添加,请为 的第二个参数传递不同的值MoveTo

此处列出了可能性:

type
  TNodeAttachMode = (naAdd, naAddFirst, naAddChild, naAddChildFirst, naInsert);

这些选项在文档中进行了描述。

于 2013-09-17T18:50:27.867 回答