This code seems really simple and straight to the point, it does pick up
every node in the tree, this is a good start for what I want to do.
The important part about that code is the recursion, which will be a
common element in any implementation that enumerates the tree completely..
I guess I will have to do as suggested,
save the tree in order, and restore it in the same order.
That is one way, yes.
I don't know how I will be
able to use the tag information for this,
You wouldn't. If you are taking advantage of the Tag property, it won't
matter what order the data is stored (though you'll probably still wind up
with a reliably reproducible order...it would be silly to intentionally
randomize the order of the data as stored
).
As an example, you could create a new Guid for each TreeNode and assign it
to the Tag property. Then when saving, you'd include for each node the
Guid of the _parent_ of that node (stored in the Tag property of the
parent, of course). Then reconstructing the tree is as simple as looking
at the parent Guid stored with each node's data (not that node's own Guid,
in the Tag property), and using that to find the parent for the node.
I am thinking about storing data attached to each node when I attach to
a db.
I'm no database expert. But my understanding is that you can create a
database where one of the columns is a unique identifier, and optionally
where the unique identifier is automatically generated when you add a
record to the database.
In this case, instead of creating a new unique identifier in the context
of your TreeView with each TreeNode, you could wait until you've writtena
given node to the database to find out what the unique identifier in the
database is for that node, and then store that identifier for each child
of the node as part of the child node's database record (root nodes would,
of course, have to have some sort of null value).
I don't know how the specific database code would look, but in pseudocode
the basic idea would be something like this:
void AddNodesToDatabase(TreeNodeCollection nodes, int DBParentID)
{
foreach (TreeNode node in nodes)
{
int DBNodeID = AddNodeToDatabase(node, DBParentID);
AddNodesToDatabase(node.Nodes, DBNodeID);
}
}
The assumption being that the method "AddNodeToDatabase" will save the
node data along with the parents database ID as a single record in the
database, and then return the database's unique identifier for that
newly-added node. The ID can then be used to add the children nodes for
that node.
In this way, the tree structure is represented in the database. Of
course, you still need to reconstitute the tree from that information
later. That will be a matter of tracking, at least temporarily, the
database ID for each node as they are read out. For example (again,
pseudo-code):
Dictionary<int, TreeNode> NodeLookup = new Dictionary<int, TreeNode>();
void GetNodesFromDatabase(TreeNodeCollection nodes)
{
// Obviously we need to enumerate each record in the database
foreach (TreeNodeRecord record in Database)
{
// These three lines represent the basic functionality you'll
need to figure out
// with respect to the database. From the database record,
you need to be able
// to construct a node, retrieve the ID for that node, as well
as the ID for the
// parent node.
TreeNode node = TreeNodeFromRecord(record);
int DBParentID = ParentIDFromRecord(record);
int DBNodeID = NodeIDFromRecord(record);
if (DBParentID != DBNullID)
{
// If the parent node is in your dictionary, add the new
// node as a child of the parent node
NodeLookup[DBParentID].Nodes.Add(node);
}
else
{
// Otherwise, add it as a root note
nodes.Add(node);
}
// Store the new node in the lookup dictionary, so that its
children
// can be added
NodeLookup.Add(DBNodeID, node);
}
}
The above code assumes that parents are always written before their
children. It's not a requirement that is strictly necessary, but it makes
the code simpler and more efficient and is easy enough to implement (it
comes naturally from the previous code example).
And as far as I understand the tag property is normally
used for storing your structs, that is as far as I have read from many
other posts.
The Tag property can be used for attaching any user-defined data you like
to the TreeNode. That could be run-time specific data, or some kind of
unique identifier for the node, or whatever. It's up to the application
to decide how to use the Tag property.
The previous thread I mentioned, I wrote a simple demo of saving and
restoring a TreeView. The code is all in-memory...it doesn't save
anything to persistent storage. But the basic ideas are going to be the
same. The post in which I included that sample is here:
http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/msg/018a8db8e8a6033e
You may find that post, or even the entire thread, useful. Or not. You
might as well look to see though.
Pete