Re: Unique identifier in every treenode?

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



On Thu, 03 Jan 2008 13:29:32 -0800, Rob Stevens <robbstephens@xxxxxxxxxx> wrote:

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 written a 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
.



Relevant Pages

  • RE: Parent-Child relations in a dataset
    ... How do I keep pending parent and children in synch? ... that actually exist in the database. ... use those placeholder values for your pending child rows. ... "SELECT SCOPE_IDENTITY" query to retrieve the last identity ...
    (microsoft.public.dotnet.framework.adonet)
  • Re: Updating and Retrieving Data
    ... How do I keep pending parent and children in synch? ... that actually exist in the database. ... use those placeholder values for your pending child rows. ... "SELECT SCOPE_IDENTITY" query to retrieve the last identity ...
    (microsoft.public.dotnet.framework.adonet)
  • Re: JTree & database: ID column ?
    ... > from database and for it I use ID1 column which is unique ... > and every number in a code represents the place in a parent node. ... And if you can construct a tree ... reverse-index is NOT an auto-inserted id value, although it has to be unique ...
    (comp.lang.java.gui)
  • Re: Parsing and storing formulas
    ... you could easily store different views/stored ... >I was wondering how I can parse a mathematical formula in a storable way. ... > be stored for in the database. ... > The second idea is to represent the formula as a tree. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Managing Genealogy Relationships in FMP 8.5
    ... the database (the file has tables for managing photos, documents, ... family tree, he's variously a brother, husband, grandfather, son, ... but a complete map is hella more efficient. ... Replace a Sort field to 1. ...
    (comp.databases.filemaker)