-1

I'd like to add information to the nodes everytime I populate a Treeview. I mean for instance, when I create a ChildNode I'd like to link it with its degree of kinhsip. Maybe the property data is made for this but I don't know how to handle it.

  • And have you tried something? – Frazz Mar 27 '17 at 09:16
  • 1
    Pretty vague and unclear. We don't even know what control you are using. There's the VCL treeview, the FMX treeview, virtual tree view. And we don't know what you link by "link with its degree of kinship". Please edit the question to make it clearer. Start by reading these articles at the [help] more carefully. – David Heffernan Mar 27 '17 at 09:19
  • Your comments to the one answer you have got sofar, indicate that your question is not complete. The `Data` property is most likely the easiest and the correct way, but there's really no idea to answer your question before you fill in all missing details in your question. Details that determine whether the answer will be accepted by you. Btw, what data type is the "degree of kinship". – Tom Brunberg Mar 27 '17 at 10:32
  • Thks for your reply. Could you explain me how to handle the data property? As you can read in my answer the content of the info is not important. Consider it as 'the age' of the node supposing each node represents a person if you prefer. The type may be integer, string or double, no matter. –  Mar 27 '17 at 11:43
  • I'd like to add one property to all nodes of my treeview. Let's call it 'toto' and of real type. I wish I filled in all useful details. Thks beforehand. –  Mar 27 '17 at 13:00
  • When you address a comment to another commenter who is not the poster of a question or an answer, precede the name with an at sign (@), that way the addressee gets notified. I guess the two comments above are responses to my previous comment. However, I asked you to fill in the missing info **in your question** where they belong. Maybe you haven't payed attention to the "edit" button just below the tags of your question. Please, take [**The Tour**](http://stackoverflow.com/tour) for a brief intro on Stack Overflow, and then read [**Asking**](http://stackoverflow.com/help/asking) – Tom Brunberg Mar 27 '17 at 14:59

2 Answers2

5

Assuming you are using the VCL's TTreeView component, and not FireMonkey's TTreeView component, or some other 3rd party tree view, then the best way to handle this situation is to derive a new class from the VCL's TTreeNode class and add a custom field to it to hold your desired value, and then you can use the TTreeView.OnCreateNodeClass event to let TTreeView create instances of your class:

type
  TMyTreeNode = class(TTreeNode)
  public
    Toto: Real;
  end;

procedure TMyForm.TreeView1CreateNodeClass(Sender: TCustomTreeView; var NodeClass: TTreeNodeClass);
begin
  NodeClass := TMyTreeNode;
end;

Then, any time you add a new node, or need to retreive the custom value of an existing node, you can simply type-cast a TTreeNode pointer to TMyTreeNode to access your custom field:

Node := TreeView1.Items.Add(nil, '...');
TMyTreeNode(Node).Toto := ...;

Node := TreeView1.Items.AddChild(Node, '...');
TMyTreeNode(Node).Toto := ...;

...

Value := TMyTreeNode(TreeView1.Items.Item[index]).Toto;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • your solution is the best. Definitely. –  Mar 27 '17 at 18:33
  • Add What about if i want to save the Tree with the extra Values to a file and read it? – icinema gr Sep 18 '19 at 20:58
  • The `TTreeView.SaveTo...()` and `TTreeView.LoadFrom...()` methods do not support streaming of custom node fields. You would have to save/load the tree nodes manually. – Remy Lebeau Sep 18 '19 at 21:52
  • suppose i save them into a stream how i will assign them back when i load the tree nodes again? – icinema gr Sep 19 '19 at 14:09
  • 1
    @icinemagr that is for you to decide, since you would be the one saving the data to begin with. So choose a format that allows you to determine how to reconstruct the tree layout. – Remy Lebeau Sep 19 '19 at 17:42
0

You could use the TTreeView's OnAddition event to do this:

procedure TForm1.TreeView1Addition(Sender: TObject; Node: TTreeNode);
begin
  Caption := 'Added ' + Node.Text + ', child count: ' +IntToStr(Node.Count);
  if Node.Parent <> Nil then 
    Node.Text := Node.Text + ', child of ' + Node.Parent.Text;

end;

Update It seems from your comments that TTreeView isn't really the right place to start from for what you might want to do in terms of adding to a TreeNode's properties. The point is, TTreeView is a quite thin wrapper around one of Windows' common controls.

You would have far greater control if you use TVirtualStringTree instead - it is one of the components in this library:

https://github.com/Virtual-TreeView/Virtual-TreeView

because the tree node data is completely user-defined.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
MartynA
  • 30,454
  • 4
  • 32
  • 73
  • Thks MArtynA. I tried your code it displayed the info in the form's caption. What I 'd like is when I select a node to know the precise info about him. I wrote about 'degree of kinship' no matter what it is, it could be the age for instance. I could write this info in node.text but I'd prefer to write only the name in the text property. –  Mar 27 '17 at 09:31
  • yes, that's what I intended it to do, but see update. – MartynA Mar 27 '17 at 09:31
  • I'd like to keep the node.text as the original name of the node and not add the info in it. –  Mar 27 '17 at 09:41
  • I read that one solution was to add my own property to the class TTreeNode or use the data pointer. I'd prefer the latter but It seems not easy to handle pointers. –  Mar 27 '17 at 09:52
  • "I'd like to keep the node.text" Sure, I was just showing the sort of thing you could do in the `OnAddition` event. – MartynA Mar 27 '17 at 10:26
  • "but It seems not easy to handle pointers" Well, bear in mind that a Delphi object, e.g. `Button1` is really a pointer, so you can do things like `Node.Data := Button1`. But if you do that then you need to cast the `Data` pointer back to the type of the object to use it. – MartynA Mar 27 '17 at 10:35