使用 gridrow 的数据查找 Treeview 的节点

Find node of Treeview using data of gridrow

首先,我有一个数据库:它可以是文件,也可以是包含这些项目的 folder/map(更多列在 table 中,但我怀疑它们是否需要这样做)

id | name | parent_id
----------------------------
1  | A    | nil
2  | A1   | 1
3  | A2   | 1
4  | A21  | 2
5  | B    | nil
6  | C    | nil
7  | C1   | 6

我已经通过使用递归查询和函数成功地创建了树。 添加节点需要参数(aParent, aString, aPointer):

Treeview.Items.AddObject(nil, qry.FieldByName('name').AsString, Pointer(qry.FieldByName('id').AsInteger))
Treeview.Items.AddChildObject(aParent, qry.FieldByName('name').AsString, Pointer(qry.FieldByName('id').AsInteger))

一切正常(当然实际代码更大,但我的问题如下。我有一个正在使用的数据网格,它显示了我的文件和文件夹。在我的数据网格或树视图中打开 folder/map刷新我的数据网格并显示其中的正确项目。但是,当我更改文件夹时,我希望我的树视图也发生变化,select 正确的节点也是如此。

我所发现的是我可以通过索引 select 个节点,但我不知道我想去的节点的索引。我在加载时执行此操作,因此它始终从第一个节点开始:

tvProjectDocuments.FullCollapse;
tvProjectDocuments.Selected:=tvProjectDocuments.Items[0];
tvProjectDocuments.Items[0].Selected:=true;

现在我的问题是,我可以使用节点的指针在数据网格中获取正确的数据,但是是否可以通过指针 (id) 找到节点?

更新: 我现在设法找到了节点

function TForm.FindNode(id: integer): TTreeNode;
var
  i: integer;
  found: boolean;
begin
  Result:=nil;
  i:=0;
  found:=false;
  while (i<Treeview.Items.Count-1) and not found do
  begin
    if Integer(Treeview.Items[i].Data)=id then
    begin
      result:=Treeview.Items[i];
      found:=True;
    end;
    inc(i);
  end;
end;

procedure TForm.tvProjectDocumentsChange(Sender: TObject; Node: TTreeNode);
begin
  if FFolderId = 0 then
  begin
    FFolderId:=Integer(Node.Data);

    //some code to get my grid filled data. works
    grid.Refresh;
    FFolderId:=0
  end;
end;

procedure TForm.GridCellDblClick(Sender: TObject; ACol, ARow: Integer);
begin
  FFolderId:=<CustomComponent>.FieldByName('proj_document_id').AsInteger;
  Treeview.Selected:=(FindNode(FFolderId));

  //other stuff happens
  FFolderId:=0;
end;

当涉及到最后一个 Treenode 时,我在调试时遇到了这个访问冲突:FFolderId:=Node.Data 在观察列表中它为零。

之后它确实加载了我的数据网格,但它没有 select 对应的节点应该是什么。 对于所有其他节点,如果我从数据网格打开一个文件夹,它会 select 并显示正确的节点。

我现在已经通过使用 FFolderId 避免了错误。但它仍然不是 select 我的最后一个节点。任何信息将不胜感激。

通过对象选择节点可以这样实现:

function TForm10.GetNodeFromObject(const pNodes: TTreeNodes;
  pObject: TObject): TTreeNode;
var
  i: Integer;
begin
  for i := 0 to pNodes.Count - 1 do
  begin
    Result := pNodes.Item[ i ];
    if Result.Data = pObject then
    begin
      exit;
    end;
  end;
  // else
  Result := nil;
end;

然后你会像这样使用它

var
  iNode : TTreeNode;
begin
  iNode := GetNodeFromObject( TreeView.Items, Pointer( qry.FieldByName('id').AsInteger));
  if assigned( iNode ) then
  begin
    iNode.Selected := TRUE;
  end;
end;

在你的情况下。当然功能比那个更通用