Author: Tomas Rutkauskas
I'd like to use the TreeView component for hierarchizing some data. For this, I
need to add to every node an integer property which will refer to the primary key
field of an associated database. Alas, I fear that the TreeView "SaveToFile" and
"LoadFromFile" methods save/ load only the Text property! Then, how can I save and
load this integer property (and by the way, the imageindex) for every node?
Answer:
By writing your own save and load routines. Untested! Don't forget to rewind the
stream before loading when you test this code.
1
2 procedure SaveTreeviewToStream(tv: TTreeview; S: TStream);
3 var
4 writer: TWriter;
5 node: TTreeNode;
6 begin
7 Assert(Assigned(tv));
8 Assert(Assigned(S));
9 writer := TWriter.Create(S, 4096);
10 try
11 node := tv.Items[0];
12 writer.WriteListBegin;
13 while node <> nil do
14 begin
15 writer.WriteInteger(node.level);
16 writer.WriteString(node.Text);
17 writer.WriteInteger(node.Imageindex);
18 writer.WriteInteger(Integer(node.data));
19 node := node.GetNext;
20 end;
21 writer.WriteListEnd;
22 writer.FlushBuffer;
23 finally
24 writer.Free;
25 end;
26 end;
27
28 procedure LoadTreeviewFromStream(tv: TTreeview; S: TStream);
29 var
30 reader: TReader;
31 node: TTreeNode;
32 level: Integer;
33 begin
34 Assert(Assigned(tv));
35 Assert(Assigned(S));
36 tv.Items.BeginUpdate;
37 try
38 tv.Items.Clear;
39 reader := TReader.Create(S, 4096);
40 try
41 node := nil;
42 reader.ReadListBegin;
43 while not Reader.EndOfList do
44 begin
45 level := reader.ReadInteger;
46 if node = nil then
47 {create root node, ignore its level}
48 node := tv.Items.Add(nil, '')
49 else
50 begin
51 if level = node.level then
52 node := tv.Items.Add(node, '')
53 else if level > node.level then
54 node := tv.Items.AddChild(node, '')
55 else
56 begin
57 while Assigned(node) and (level < node.level) do
58 node := node.Parent;
59 node := tv.Items.Add(node, '');
60 end;
61 end;
62 node.Text := Reader.ReadString;
63 node.ImageIndex := Reader.ReadInteger;
64 node.Data := Pointer(Reader.ReadInteger);
65 end;
66 reader.ReadListEnd;
67 finally
68 reader.Free;
69 end;
70 finally
71 tv.items.Endupdate;
72 end;
73 end;
I'd rather suggest to use the data pointer as a pointer to a real object, not as integer (in the SaveTreeviewToStream procedure). You could add more complex info inside this object, like type information, or even the data objects itself. Type information is essential if your treeview browses through different tables of your database.
|