I have a four table dataset that I am binding to my tree. I have the relations set up and the tree displays as I would expect. I had some issues setting a key and tag but put the following code in that seems to have sorted that part out.
void treeDocumentType_InitializeDataNode(object sender, InitializeDataNodeEventArgs e){ switch (e.Node.BandName) { case "tblClass": e.Node.Key = ((DataRowView)e.Node.ListObject)["uidClass"].ToString(); break;
case "relClassMember": e.Node.Key = ((DataRowView)e.Node.ListObject)["uidMember"].ToString(); break;
case "relMemberSummary": e.Node.Key = ((DataRowView)e.Node.ListObject)["uidSummary"].ToString(); break;
case "relSummaryPhrase": e.Node.Key = ((DataRowView)e.Node.ListObject)["uidPhrase"].ToString(); break; }}
I suppose the first question is if this is the accepted way to set those variables or should I be doing something else.
The issue that I am having is reselecting a node after performing an operation. I can easily re-bind the tree which work, but I can't make the previously selected node re-select. I tried using
treeDocumentType.GetNodeByKey(e.MemberId.ToString());
where e.MemberId is the Guid that was previously selected. That result comes back as null. However if I set a breakpoint and then open up the immediate window I can make the following query
?treeDocumentType.Nodes[0].Nodes[0].Key
this will show the correct key. If I then re-execute the GetNodeByKey bit it will work. Is there a better way to do this?
Thanks, I appreciate any insight.
There's no built-in search feature in the tree, other than by key. So you would have to write code to iterate over the nodes in the tree (perhaps recursively) and find the node you want.
Or, as I said above, you could write a recursive loop that just goes over every node in the tree and checks it's Nodes.Count. This would force the tree to load all of the nodes, and then GetNodeByKey would work.
This is, of course, not very efficient, but it would be easier to code. And if your tree doesn't have a huge number of nodes, it might be an acceptable solution and save you some coding time.
I built another form that needed a tree and did it a little different. I bound the dataset to the tree the same way as before. Instead of editing the db and then re-binding, I edited the tree datasource directly and then updated the db right after. That method works great for me and I suspect is what most people would do. The tree reacts immediately with the edit and re-selecting is not necessary.
However I do have another question about reselecting a node. I will do my best to explain fully our layout. We have a hierarchy as follows class -> member -> summary -> phrase.
When editing the individual pieces there should be no issues. However there will be a button on a different area of the app that needs to link to a phrase. I will know the full path to the phrase, but I can't seem to access it. You explained why GetNodeByKey will not always work, but is there another way to select a specific node without iterating the tree until I find it?
Thanks Mike for all of your help. The support I have gotten is great so far, so much better than with our previous suite of controls. I really appreciate it.
indxlogic said:What would you recommend?
Well, it's hard to recommend anything when I don't know what you are trying to do. But typically, you would bind the control to a DataTable or DataSet. These classes have all sorts of support for loading and saving data to and from a database and there are even methods that allow you to merge data from two tables into one, I think.
If you bind the tree to any class which implements IBindingList (such as the DataSet, DataTable, UltraDataSource, BindingList<>, etc.), then the IBindingList and the BindingManager in DotNet will handle sending notifications to bound controls that tell it when rows are added, removed, or changed. So there's usually no reason to reload the entire set of data.
But again, I don't know what you are trying to do or the requirements of your application, so maybe there is some reason why you need to rebind.
Mike Saltzman"] So my first question is - why rebind?
So my first question is - why rebind?
That is a great question, and I don't have an answer for it. That is the way we had to do it with our previous tree control. Our previous method was to pull data out of the db, loop through and manually add in nodes. When saving we would write to the database and then clear out the nodes and start over. I agree it is not an effcient way of doing things, but our previous contol was not very useful when it came to binding options.
What would you recommend?
indxlogic said:I suppose the first question is if this is the accepted way to set those variables or should I be doing something else.
This is a good way to do it.
indxlogic said: The issue that I am having is reselecting a node after performing an operation. I can easily re-bind the tree which work, but I can't make the previously selected node re-select. I tried using treeDocumentType.GetNodeByKey(e.MemberId.ToString()); where e.MemberId is the Guid that was previously selected. That result comes back as null. However if I set a breakpoint and then open up the immediate window I can make the following query ?treeDocumentType.Nodes[0].Nodes[0].Key this will show the correct key. If I then re-execute the GetNodeByKey bit it will work. Is there a better way to do this? Thanks, I appreciate any insight.
It's typically best to avoid re-binding the control if you can avoid it. Re-binding means that the whole tree, all the nodes, and all of the ColumnSets are destroyed and a whole new set are created. So this is very inefficient and you will lose the active node, the selected node, the width and position of the columns, etc.
To answer your question, the reason it's not working is that the tree loads the nodes as it needs them. So if you bind the tree and immediately call GetNodeByKey, the node you are looking for probably has not been added to the tree, yet. You can force the tree to load the nodes by looping through the nodes recursively and checking the Count property, but this isn't very efficient.