First of all, I have a database: It can be either file or folder/map with these items (more columns are in the table, but I doubt they are required for this)
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
I have succeeded in making the tree by using a recursive query and function. Adding a node requires the parameters of (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))
This all works fine (of course the actual code is larger, but my question is the following. I have a datagrid in use which shows my files and folders. Opening a folder/map in my datagrid or treeview refreshes my datagrid and shows the correct items within. However when I change folder i want my treeview to change and select the correct node as well.
All I have found is that I can select nodes by index, but I dont know the index of the node I want to go to. I do this at load so it always starts at the first node:
tvProjectDocuments.FullCollapse;
tvProjectDocuments.Selected:=tvProjectDocuments.Items[0];
tvProjectDocuments.Items[0].Selected:=true;
Now my question, I am able to use the pointer of my node to get the correct data in my datagrid, but is it possible to find a node by pointer(id)?
UPDATE: I managed to find the node by now
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;
When it comes to the last Treenode, i get this access violation while debugging: FFolderId:=Node.Data in the Watch list it nil.
Afterwards it does load my datagrid, but it does not select the node corresponding to what should be. With all other nodes if i open a folder from datagrid, it does select and show the proper node.
I have prevented the error for now by using the FFolderId. But it still doesnt select my last node. Any info would be appreciated.
Selecting a node via its object can be achieved like this:
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;
You would then use it something like this
var
iNode : TTreeNode;
begin
iNode := GetNodeFromObject( TreeView.Items, Pointer( qry.FieldByName('id').AsInteger));
if assigned( iNode ) then
begin
iNode.Selected := TRUE;
end;
end;
in your case. Of course the function is more general than that.