Sign in Join
Wiki copytemporary

TTreeView: what changed

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

OldNewLine
11A **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.
22
33An item can be expanded to reveal subitems, if any exist, and collapsed to hide subitems.
44
55## A Short example of using TTreeview
66
77Here is a simple example:
88
99- Create a new application.
1010- Add an empty treeview to the form, a button1 with caption "Add Child" and a button2 with caption "Delete"
1111- Assign the following code to the buttons' OnClick events. Compile and run.
1212
1313``` pascal
1414procedure TForm1.Button1Click(Sender: TObject);
1515var
1616 n: integer;
1717 s: string;
1818begin
1919 // If there are no nodes, create a root node with a parent of nil
2020 if TreeView1.Items.Count = 0 then
2121 begin
2222 Treeview1.Items.Add(nil,'Root Node');
2323 exit;
2424 end;
2525
2626 // Set up a simple text for each new node - "Node1", "Node2" etc
2727 n := Treeview1.Items.Count;
2828 s := 'Node ' + IntToStr(n);
2929
3030 // Add a new node to the currently selected node
3131 if TreeView1.Selected <> nil then
3232 Treeview1.Items.AddChild(Treeview1.Selected, s);
3333end;
3434
3535procedure TForm1.Button2Click(Sender: TObject);
3636
3737 // A procedure to recursively delete nodes
3838 procedure DeleteNode(ANode: TTreeNode);
3939 begin
4040 while ANode.HasChildren do
4141 DeleteNode(ANode.GetLastChild);
4242 TreeView1.Items.Delete(ANode);
4343 end;
4444
4545begin
4646 if TreeView1.Selected = nil then
4747 exit;
4848
4949 // If the selected node has child nodes, first ask for confirmation
5050 if Treeview1.Selected.HasChildren then
5151 if MessageDlg('Delete node and all children?', mtConfirmation, [mbYes,mbNo], 0 ) <> mrYes then
5252 exit;
5353 DeleteNode(TreeView1.Selected);
5454end;
5555```
5656
5757When 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.
5858
5959The "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.
6060
6161## Adding a new item in code
6262
6363To add a sibling node to pre-existing node, use TTreeView.ITems.Add.
6464
6565``` pascal
6666TreeView1.Items.Add(ATreeNode, 'Added node');
6767```
6868
6969To add the first node, it becomes:
7070
7171``` pascal
7272TreeView1.Items.Add(nil, 'First node');
7373```
7474
7575Use TTreeView.Items.AddChild or AddChildObject to add child node.
7676
7777``` pascal
7878TreeView1.Items.AddChild(ATreeNode, 'Child node');
7979```
8080
8181## Creating a TreeView which loads items only when expanding
8282
8383To add the expansion symbol to a node without subitems use:
8484
8585``` pascal
8686MyNode.HasChildren := True;
8787```
8888
8989And 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.
9090
9191## How to move a node in TTreeview
9292
9393Assuming you have UP and Down buttons to move the selected node in the TTreeview, these procedures will achieve moving the selected node.
9494
9595``` pascal
9696procedure TForm1.UpBtnClick(Sender: TObject);
9797begin
9898 // Ensure a node is selected
9999 if(Treeview1.Selected <> nil) then
100100 // Ensure there is a previous sibling node
101101 if Treeview1.Selected.GetPrevSibling <> nil then
102102 // If we have made it this far, move it UP
103103 Treeview1.Selected.MoveTo(Treeview1.Selected.GetPrevSibling, naInsert);
104104end;
105105
106106procedure TForm1.DownBtnClick(Sender: TObject);
107107begin
108108 // Ensure a node is selected
109109 if(Treeview1.Selected <> nil) then
110110 // Ensure there is a next sibling node
111111 if Treeview1.Selected.GetNextSibling <> nil then
112112 // If we have made it this far, move it DOWN
113113 Treeview1.Selected.MoveTo(Treeview1.Selected.GetNextSibling, naInsertBehind);
114114end;
115115```
116116
117117Note: These procedures will only move nodes which are at the same level in the TTreeview.
118118
119119<thead>
120120
121121</thead>
122122<tbody>
123123
124124</tbody>
125125
126126## Using multiple node selection
127127
128128To 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`.
129129
130130To get a list of selected nodes from code, you can use the `TreeView1.Selections` property:
131131
132132``` pascal
133133procedure TForm1.Button1Click(Sender: TObject);
134134var
135135 i: integer;
136136begin
137137 Memo1.Lines.Clear;
138138 for i := 0 to TreeView1.SelectionCount - 1 do
139139 Memo1.Lines.Add(TreeView1.Selections[i].GetTextPath);
140140end;
141141```
142142
143143## Freeing TreeNode Data
144144
145145Use the TreeView's OnDeletion event to free your object.
146146
147147``` pascal
148148procedure TForm1.TreeView1Deletion(Sender: TObject; Node: TTreeNode);
149149begin
150150 TMyObject(Node.Data).Free;
151151 Node.Data := nil;
152152end;
153153```
154154
155155## Using Drag and Drop in a TreeView
156156
157157If you want to allow a drag and drop function in your treeview, you need to :
158158
1591591. Set to DmAutomatic, the property "Drag Mode" of your treeview
1601602. Create events for `onDragDrop` and `OnDragOver`:
161161
162162``` pascal
163163...
164164
165165Var
166166 Node: TTreeNode;
167167
168168...
169169
170170procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
171171begin
172172 Treeview1 := TTreeView(Sender); { Sender is TreeView where the data is being dropped }
173173 Node := Treeview1.GetNodeAt(x,y); { x,y are drop coordinates (relative to the Sender) }
174174 { since Sender is TreeView we can evaluate }
175175 { a tree at the X,Y coordinates }
176176 if Source = Sender then { drop is happening within a TreeView }
177177 begin
178178 if Assigned(Treeview1.Selected) and { check if any node has been selected }
179179 (Node <> Treeview1.Selected) then { and we're dropping to another node }
180180 begin
181181 if Node <> nil then
182182 Treeview1.Selected.MoveTo(Node, naAddChild) { complete drop, by moving selected node }
183183 else
184184 Treeview1.Selected.MoveTo(Node, naAdd); { complete drop, by moving selected node in root }
185185 end;
186186 end;
187187end;
188188
189189procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
190190begin
191191 Accept := true;
192192end;
193193```
194194
195195## Comments on Events
196196
197197Event handlers are convenient places for developing LCL applications. There are some peculiar events for TTreeview.
198198
199199**When selected node is changed**
200200
201201``` pascal
202202procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
203203```
204204
205205The `OnChange` event is fired when another node is selected. It can be used in a program to update some data.
206206
207207``` pascal
208208procedure TForm1.TreeView1Changing(Sender: TObject; Node: TTreeNode; var AllowChange: Boolean);
209209```
210210
211211The `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.
212212
213213Please 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.
214214
215215In both events, the `Node` and `Selected` can be equal to `nil` (if there was no selection or it is being removed).
216216
217217**When a node is inserted**
218218
219219When a new node is inserted, related events occur in the following order.
220220
221-`      1) OnNodeChanged`\
222-`      2) (OnChanging): This is called if there was a previously selected node.`\
223-`      3) OnSelectionChanged`\
224-`      4) OnChange`
221+```text
222+ 1) OnNodeChanged
223+ 2) (OnChanging): This is called if there was a previously selected node.
224+ 3) OnSelectionChanged
225+ 4) OnChange
226+```
225227
226228**When deleting a node**
227229
228230When the selected node is deleted, the following events occur.
229231
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. `
232+```text
233+ 1) OnDelete
234+ 2) OnChanging
235+ 3) SelectionChanged
236+ 4) OnChange : This is called because when you delete a node, another node is selected.
237+```
234238
235239If an unselected node is deleted, e.g. programmatically, then only the OnDelete event handler is called.
236240
237241**When Form is Closed**
238242
239243OnChanging 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.
240244
241245**When Drag&Drop is done**
242246
243247When you drag a node to another node and drop, the following events occur.
244248
245-`     1) OnSelectionChanged`\
246-`     2) OnNodeChanged`\
247-`     3) OnChange`
249+```text
250+ 1) OnSelectionChanged
251+ 2) OnNodeChanged
252+ 3) OnChange
253+```
248254
249255## See also
250256
251257- [[Drag and Drop sample]]
252258- [[doc:/lcl/comctrls/ttreeview.html|TTreeView doc]]
253259- [[TListView]]
254260- [[VirtualTreeview]]
255261
256262---
257263*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