使用 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;
在你的情况下。当然功能比那个更通用
首先,我有一个数据库:它可以是文件,也可以是包含这些项目的 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;
在你的情况下。当然功能比那个更通用