How to populate a tree structure based on a flat list with "levels"?

I have a list of objects populated from a third-party project file. The way this file was designed is that each element is at the "level" of the hierarchy. So, the very first element is at level 0, all its children are at level 1, etc.

As an example:

1. Node 1 (Level 0) 2. Node 1.1 (Level 1) 3. Node 1.2 (Level 1) 4. Node 1.3 (Level 1) 5. Node 1.3.1 (Level 2) 6. Node 1.4 (Level 1) 7. Node 2 (Level 0) 8. Node 2.1 (Level 1) 9. Node 2.1.1 (Level 2) 10. Node 3 (Level 0) 

This will lead to the creation of such a hierarchy:

 - Node 1 --- Node 1.1 --- Node 1.2 --- Node 1.3 ----- Node 1.3.1 --- Node 1.4 - Node 2 --- Node 2.1 ----- Node 2.1.1 - Node 3 

My problem is how to populate this structure in a TTreeView VCL based on these "Level" properties for each listed object. If I developed this third-party file structure, I would use the parent property instead of the level property.

The objects in this list can be repeated as follows:

 var I: TMyItem; N: TTreeNode; begin for X := 0 to MyList.Count - 1 do begin I := MyList[X]; //TMyItem has property "Level" which specifies hierarchy // as well as "Title" property for the node caption //How to create node based on Level? N.Data := I; end; end; 

Based on this structure, how do I populate this in a tree view?

+5
delphi hierarchy treeview
source share
2 answers

Try something like this:

 var Item: TMyItem; Node: TTreeNode; NodeLevel: Integer; X: Integer; begin Node := nil; NodeLevel := 0; for X := 0 to MyList.Count-1 do begin Item := MyList[X]; if (Node = nil) or (Item.Level <= 0) then begin Node := TreeView1.Items.AddObject(nil, Item.Text, Item); NodeLevel := 0; end else if Item.Level = NodeLevel then begin Node := TreeView1.Items.AddObject(Node, Item.Text, Item); end else begin while Item.Level <= NodeLevel do begin Node := Node.Parent; Dec(NodeLevel); end; Node := TreeView1.Items.AddChildObject(Node, Item.Text, Item); Inc(NodeLevel); end; // set Node properties as needed... end; end; 
+7
source share

Create a list that will contain the last parent node for each level. This list will initially be empty.

Now go through the linear list. Whenever you add an item at the N level to the list, you do the following:

  • Add it as a child of the last parent at level N-1 and
  • set the last parent at level N as the item you just added.

You will need to handle the case where N = 0, for which the above algo will require you to have the last parent at level -1, whatever that means. Does your tree have a common root node? If so, then by definition, the last parent at level -1 is the root of the node. Otherwise, if there is no root node, you need to do what your tree view component requires in order to add a node at the top level, and not as a child of another node.

Assuming there is no root node, then the code would look like this:

 var Item: TItem; LatestParents: TList<TTreeNode>; Parent, NewNode: TTreeNode; begin LatestParents := TList<TTreeNode>.Create; try LatestParents.Add(nil); for Item in Items do begin Parent := LatestParents[Item.Level]; NewNode := TreeView.Items.AddChild(Parent, Item.Text); LatestParents.Count := Max(LatestParents.Count, Item.Level+2); LatestParents[Item.Level+1] := NewNode; end; finally LatestParents.Free; end; end; 

You might want to introduce some error into the code if there is a chance that your code will encounter an incorrect tree description. For example, if the first node you encounter is not level 0, then this code will not be executed.

+8
source share

All Articles