Save and load a TTreeView to / from a stream (Views: 29)
Problem/Question/Abstract: 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. procedure SaveTreeviewToStream(tv: TTreeview; S: TStream); var writer: TWriter; node: TTreeNode; begin Assert(Assigned(tv)); Assert(Assigned(S)); writer := TWriter.Create(S, 4096); try node := tv.Items[0]; writer.WriteListBegin; while node <> nil do begin writer.WriteInteger(node.level); writer.WriteString(node.Text); writer.WriteInteger(node.Imageindex); writer.WriteInteger(Integer(node.data)); node := node.GetNext; end; writer.WriteListEnd; writer.FlushBuffer; finally writer.Free; end; end; procedure LoadTreeviewFromStream(tv: TTreeview; S: TStream); var reader: TReader; node: TTreeNode; level: Integer; begin Assert(Assigned(tv)); Assert(Assigned(S)); tv.Items.BeginUpdate; try tv.Items.Clear; reader := TReader.Create(S, 4096); try node := nil; reader.ReadListBegin; while not Reader.EndOfList do begin level := reader.ReadInteger; if node = nil then {create root node, ignore its level} node := tv.Items.Add(nil, '') else begin if level = node.level then node := tv.Items.Add(node, '') else if level > node.level then node := tv.Items.AddChild(node, '') else begin while Assigned(node) and (level < node.level) do node := node.Parent; node := tv.Items.Add(node, ''); end; end; node.Text := Reader.ReadString; node.ImageIndex := Reader.ReadInteger; node.Data := Pointer(Reader.ReadInteger); end; reader.ReadListEnd; finally reader.Free; end; finally tv.items.Endupdate; end; 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. |