RichardFox
asked on
Dynamic treeview node manipulation problem (and dynamic controls in general)
i'd like to ask a side question about dynamic controls. I create a table and a bunch of controls locally in my own class (CBControlsSimple), and Add them to the Controls collection of panels on the main page
protected CBControlsSimple cbCont;
protected System.Web.UI.WebControls. Panel cbPanel;
protected System.Web.UI.WebControls. Panel zyPanel;
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack || Session.IsNewSession)
{
// create control sets
cbCont = new CBControlsSimple(cbPanel,z yPanel);
Session["CBCONT"] = cbCont;
}
else
{
cbCont = (CBControlsSimple)Session[ "CBCONT"];
cbCont.ReconnectToPanel(cb Panel,zyPa nel);
}
this.SmartNavigation = true;
}
And the CBControlsSimple::Reconnec t function
// Reconnect table to panel, for page reload
public void ReconnectToPanel(Panel cbpan, Panel zypan)
{
HttpContext.Current.Respon se.Write(" Reconnect controls to panel<br>");
cbPanel = cbpan;
cbPanel.Controls.Add(cbTab le);
zyCont.ReconnectToPanel(zy pan); // yet another of my internal controls classes
}
My question is this: I persist these objects by storing them in Session as you can see from my Page_Load(), specifically not creating the controls every time the page is loaded. But I am noticing strange behavior, such as when I try to add a TreeNode to my treeView (I add and remove nodes dynamically) I get an error stating
Attempted to add a TreeNode to a second TreeNodeCollection. A TreeNode can belong to only one TreeNodeCollection. Remove the TreeNode from its old collection before adding it to a new one.
What is going on!?
protected CBControlsSimple cbCont;
protected System.Web.UI.WebControls.
protected System.Web.UI.WebControls.
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack || Session.IsNewSession)
{
// create control sets
cbCont = new CBControlsSimple(cbPanel,z
Session["CBCONT"] = cbCont;
}
else
{
cbCont = (CBControlsSimple)Session[
cbCont.ReconnectToPanel(cb
}
this.SmartNavigation = true;
}
And the CBControlsSimple::Reconnec
// Reconnect table to panel, for page reload
public void ReconnectToPanel(Panel cbpan, Panel zypan)
{
HttpContext.Current.Respon
cbPanel = cbpan;
cbPanel.Controls.Add(cbTab
zyCont.ReconnectToPanel(zy
}
My question is this: I persist these objects by storing them in Session as you can see from my Page_Load(), specifically not creating the controls every time the page is loaded. But I am noticing strange behavior, such as when I try to add a TreeNode to my treeView (I add and remove nodes dynamically) I get an error stating
Attempted to add a TreeNode to a second TreeNodeCollection. A TreeNode can belong to only one TreeNodeCollection. Remove the TreeNode from its old collection before adding it to a new one.
What is going on!?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I'm not sure about this, but I think you need to actually remove the nodes from their original tree. The original tree for each is accessible from withing the node itself. Try something like this:
TreeNode found = (TreeNode)compHash[company _key];
TreeNode node = found.OwnerTree.Remove( found );
This is just a general direction. I can't recall the name of the owner tree property right now.
This problem is analogous to moving XmlNodes between different XmlDocuments. They need to be imported from one to the other and cannot simply be "moved" over.
Sorry I can't offer any more suggestions.
TreeNode found = (TreeNode)compHash[company
TreeNode node = found.OwnerTree.Remove( found );
This is just a general direction. I can't recall the name of the owner tree property right now.
This problem is analogous to moving XmlNodes between different XmlDocuments. They need to be imported from one to the other and cannot simply be "moved" over.
Sorry I can't offer any more suggestions.
Hey, trevorhartman's suggestion to Clone the node is probably a much better and simpler solution. I should have thought of that :)
Yes, that's a good idea. TreeView is the property to get the owner tree:
TreeNode found = (TreeNode)compHash[company _key];
TreeNode node = found.TreeView.Nodes.Remov e( found );
TreeNode found = (TreeNode)compHash[company
TreeNode node = found.TreeView.Nodes.Remov
ASKER
Hmm. THere is no TreeView property in my TreeNode, there is a TreeBase.parent property but it exposes a very limited number of properties itself, Nodes is not included.
I am using Microsoft.Web.UI.WebContro ls.TreeVie w docTree, not the generic treeview.
Clone() works, though, except aren't I then leaving a lot of dangling references of TreeNodes to TreeViews?
I am using Microsoft.Web.UI.WebContro
Clone() works, though, except aren't I then leaving a lot of dangling references of TreeNodes to TreeViews?
ok, i was looking at the System.Windows.Forms.TreeN ode documentation...
It shouldn't leave references if you are just pulling the nodes out of a HashTable
It shouldn't leave references if you are just pulling the nodes out of a HashTable
ASKER
I was thinking of the cloned nodes that I add to the docTree, and later remove. But I guess when I remove them they are gone, unless the framework keeps them on the heap somewhere. Which was my point. I just don't want to leave those cloned nodes floating out there. So you don't think it's a problem?
I don't see it as a problem, but test it out to see if it has any affect on the performance of your app.
It doesn't keep them anywhere. It has pretty smart garbage collection.
ASKER
public void DisplayNode(string company_key)
{
// note: nodes are stored in a hash table. key is company name from list box
if (compHash.Contains(company
{
// node found
found = (TreeNode)compHash[company
docTree.Nodes.Clear();
docTree.Nodes.Add(found); // my treeview
}
else
{
docTree.Nodes.Clear();
}
}