Sign in Join
Wiki copytemporary

TTreeView: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: TTreeView

OldNewLine
1+A **TTreeView** ![](/wiki-images/a/a3/Ttreeview.png) is a graphical control element that presents a hierarchical view of information. Each item can have a number of subitems.
2+
3+An item can be expanded to reveal subitems, if any exist, and collapsed to hide subitems.
4+
5+## A Short example of using TTreeview
6+
7+Here is a simple example:
8+
9+- Create a new application.
10+- Add an empty treeview to the form, a button1 with caption "Add Child" and a button2 with caption "Delete"
11+- Assign the following code to the buttons' OnClick events. Compile and run.
12+
13+``` pascal
14+procedure TForm1.Button1Click(Sender: TObject);
15+var
16+ n: integer;
17+ s: string;
18+begin
19+ // If there are no nodes, create a root node with a parent of nil
20+ if TreeView1.Items.Count = 0 then
21+ begin
22+ Treeview1.Items.Add(nil,'Root Node');
23+ exit;
24+ end;
25+
26+ // Set up a simple text for each new node - "Node1", "Node2" etc
27+ n := Treeview1.Items.Count;
28+ s := 'Node ' + IntToStr(n);
29+
30+ // Add a new node to the currently selected node
31+ if TreeView1.Selected <> nil then
32+ Treeview1.Items.AddChild(Treeview1.Selected, s);
33+end;
34+
35+procedure TForm1.Button2Click(Sender: TObject);
36+
37+ // A procedure to recursively delete nodes
38+ procedure DeleteNode(ANode: TTreeNode);
39+ begin
40+ while ANode.HasChildren do
41+ DeleteNode(ANode.GetLastChild);
42+ TreeView1.Items.Delete(ANode);
43+ end;
44+
45+begin
46+ if TreeView1.Selected = nil then
47+ exit;
48+
49+ // If the selected node has child nodes, first ask for confirmation
50+ if Treeview1.Selected.HasChildren then
51+ if MessageDlg('Delete node and all children?', mtConfirmation, [mbYes,mbNo], 0 ) <> mrYes then
52+ exit;
53+ DeleteNode(TreeView1.Selected);
54+end;
55+```
56+
57+When running, the treeview is empty. If you click "Add Child", a root node is created. After that a child will be added to any selected node by clicking "Add Child" again.
58+
59+The "Delete" button will delete the currently selected node. If it doesn't have children, it will delete it immediately, but if it has children, it will first ask.
60+
61+## Adding a new item in code
62+
63+To add a sibling node to pre-existing node, use TTreeView.ITems.Add.
64+
65+``` pascal
66+TreeView1.Items.Add(ATreeNode, 'Added node');
67+```
68+
69+To add the first node, it becomes:
70+
71+``` pascal
72+TreeView1.Items.Add(nil, 'First node');
73+```
74+
75+Use TTreeView.Items.AddChild or AddChildObject to add child node.
76+
77+``` pascal
78+TreeView1.Items.AddChild(ATreeNode, 'Child node');
79+```
80+
81+## Creating a TreeView which loads items only when expanding
82+
83+To add the expansion symbol to a node without subitems use:
84+
85+``` pascal
86+MyNode.HasChildren := True;
87+```
88+
89+And then set an event handler for the OnExpanding event. In this even you should return if the expansion can actually be made or not and when yes, you should add subitems to the node. If the expansion cannot be done, the expansion symbol will be automatically removed even if you have previously set HasChildren to true.
90+
91+## How to move a node in TTreeview
92+
93+Assuming you have UP and Down buttons to move the selected node in the TTreeview, these procedures will achieve moving the selected node.
94+
95+``` pascal
96+procedure TForm1.UpBtnClick(Sender: TObject);
97+begin
98+ // Ensure a node is selected
99+ if(Treeview1.Selected <> nil) then
100+ // Ensure there is a previous sibling node
101+ if Treeview1.Selected.GetPrevSibling <> nil then
102+ // If we have made it this far, move it UP
103+ Treeview1.Selected.MoveTo(Treeview1.Selected.GetPrevSibling, naInsert);
104+end;
105+
106+procedure TForm1.DownBtnClick(Sender: TObject);
107+begin
108+ // Ensure a node is selected
109+ if(Treeview1.Selected <> nil) then
110+ // Ensure there is a next sibling node
111+ if Treeview1.Selected.GetNextSibling <> nil then
112+ // If we have made it this far, move it DOWN
113+ Treeview1.Selected.MoveTo(Treeview1.Selected.GetNextSibling, naInsertBehind);
114+end;
115+```
116+
117+Note: These procedures will only move nodes which are at the same level in the TTreeview.
118+
119+<thead>
120+
121+</thead>
122+<tbody>
123+
124+</tbody>
125+
126+## Using multiple node selection
127+
128+To allow multiple selection, you need to set the `tvoAllowMultiSelect` flag of the `Options` property. This will allow you to select additional nodes by `Ctrl`+`Mouse click`.
129+
130+To get a list of selected nodes from code, you can use the `TreeView1.Selections` property:
131+
132+``` pascal
133+procedure TForm1.Button1Click(Sender: TObject);
134+var
135+ i: integer;
136+begin
137+ Memo1.Lines.Clear;
138+ for i := 0 to TreeView1.SelectionCount - 1 do
139+ Memo1.Lines.Add(TreeView1.Selections[i].GetTextPath);
140+end;
141+```
142+
143+## Freeing TreeNode Data
144+
145+Use the TreeView's OnDeletion event to free your object.
146+
147+``` pascal
148+procedure TForm1.TreeView1Deletion(Sender: TObject; Node: TTreeNode);
149+begin
150+ TMyObject(Node.Data).Free;
151+ Node.Data := nil;
152+end;
153+```
154+
155+## Using Drag and Drop in a TreeView
156+
157+If you want to allow a drag and drop function in your treeview, you need to :
158+
159+1. Set to DmAutomatic, the property "Drag Mode" of your treeview
160+2. Create events for `onDragDrop` and `OnDragOver`:
161+
162+``` pascal
163+...
164+
165+Var
166+ Node: TTreeNode;
167+
168+...
169+
170+procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
171+begin
172+ Treeview1 := TTreeView(Sender); { Sender is TreeView where the data is being dropped }
173+ Node := Treeview1.GetNodeAt(x,y); { x,y are drop coordinates (relative to the Sender) }
174+ { since Sender is TreeView we can evaluate }
175+ { a tree at the X,Y coordinates }
176+ if Source = Sender then { drop is happening within a TreeView }
177+ begin
178+ if Assigned(Treeview1.Selected) and { check if any node has been selected }
179+ (Node <> Treeview1.Selected) then { and we're dropping to another node }
180+ begin
181+ if Node <> nil then
182+ Treeview1.Selected.MoveTo(Node, naAddChild) { complete drop, by moving selected node }
183+ else
184+ Treeview1.Selected.MoveTo(Node, naAdd); { complete drop, by moving selected node in root }
185+ end;
186+ end;
187+end;
188+
189+procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
190+begin
191+ Accept := true;
192+end;
193+```
194+
195+## Comments on Events
196+
197+Event handlers are convenient places for developing LCL applications. There are some peculiar events for TTreeview.
198+
199+**When selected node is changed**
200+
201+``` pascal
202+procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
203+```
204+
205+The `OnChange` event is fired when another node is selected. It can be used in a program to update some data.
206+
207+``` pascal
208+procedure TForm1.TreeView1Changing(Sender: TObject; Node: TTreeNode; var AllowChange: Boolean);
209+```
210+
211+The `OnChanging` event is called before `OnChange`, which allows you to prevent node selection under certain conditions. To do this, just set `AllowChange` to `false`. It is not necessary to set to `true` as this is the default value.
212+
213+Please note that in Delphi the `Node` variable points to the node that leaves the selection. In Lazarus, the `Node` variable points to the node receiving the selection, but you can use the `Selected` property to find out the "previous" node.
214+
215+In both events, the `Node` and `Selected` can be equal to `nil` (if there was no selection or it is being removed).
216+
217+**When a node is inserted**
218+
219+When a new node is inserted, related events occur in the following order.
220+
221+`      1) OnNodeChanged`\
222+`      2) (OnChanging): This is called if there was a previously selected node.`\
223+`      3) OnSelectionChanged`\
224+`      4) OnChange`
225+
226+**When deleting a node**
227+
228+When the selected node is deleted, the following events occur.
229+
230+`     1) OnDelete`\
231+`     2) OnChanging`\
232+`     3) SelectionChanged`\
233+`     4) OnChange :  This is called because when you delete a node, another node is selected. `
234+
235+If an unselected node is deleted, e.g. programmatically, then only the OnDelete event handler is called.
236+
237+**When Form is Closed**
238+
239+OnChanging event occurs, as the selected node is "de"selected. But OnChanging eventhander is executed AFTER the form is closed. This means that you cannot access the form's other data (other controls, other variables, etc.) within the OnChanging event handler procedure.
240+
241+**When Drag&Drop is done**
242+
243+When you drag a node to another node and drop, the following events occur.
244+
245+`     1) OnSelectionChanged`\
246+`     2) OnNodeChanged`\
247+`     3) OnChange`
248+
249+## See also
250+
251+- [[Drag and Drop sample]]
252+- [[doc:/lcl/comctrls/ttreeview.html|TTreeView doc]]
253+- [[TListView]]
254+- [[VirtualTreeview]]
255+
256+---
257+*From the Free Pascal wiki, page "TTreeView", as it stood on 2024-02-24 after a change by N7800, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history