This is a migrated thread and some comments may be shown as answers.

How to re-assign the parent node

5 Answers 208 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Mark Kucera
Top achievements
Rank 1
Mark Kucera asked on 25 Mar 2015, 12:48 AM
Hello,

I have a RadTreeView with a series of nodes.  Each node can have it's own nodes, which could have their own nodes etc.  Currently if i delete a node from the tree, by calling RadTreeView.SelectedNode.Remove(), the node is removed but all of the nodes in the RadTreeView.SelectedNode.Nodes collection are also removed.  Ideally instead of removing the entire branch from the tree i'd just like to remove the single node, and shift that nodes sub-nodes up a level.

Currently if i had a tree like this:

A
|
B
|
C
 \
  D
   \
    E
|
F

Removing Node C results in a tree that looks like:
A
|
B
|
F


ideally i'd like it to look like:
A
|
B
|
D
 \
 E
|
F

Here you can see that only the selected node was removed, it's sub-nodes are still available. I see that the node has a server-side .Parent property, but this is not set-able.   When a node is removed, it could have 0 sub-nodes, or it could have multiple sub-nodes which in turn could have 0 or more sub-nodes each.  it's unknown how many sub-nodes or sub-node-nodes etc are contained in any given node that is being removed. The only other thing to note is that each of my nodes contains a fairly complex user-control that has several comboboxes and/or text boxes loaded with custom data.  This makes a recursive solution where we attempt to recreate each node by making a copy of the node and adding it to the parent problematic.  

Any assistance you can provide about how i could achieve this goal would be much appreciated.  I'm open to achieving this goal with either a server or client-side solution. 

Thanks!
-Mark

5 Answers, 1 is accepted

Sort by
0
Ivan Danchev
Telerik team
answered on 27 Mar 2015, 02:04 PM
Hello Mark,

Thank you for contacting Telerik Support.

Please, find attached a sample project, which demonstrates how to move the child nodes with the help of the RadTreeNodeCollection before you delete their parent node.

Feel free to contact us again if you need further assistance.

Regards,
Ivan Danchev
Telerik
 

See What's Next in App Development. Register for TelerikNEXT.

 
0
Mark Kucera
Top achievements
Rank 1
answered on 31 Mar 2015, 10:05 PM
Ivan, thanks for sending this sample over.  On first pass it looks like it does what i'm looking for, but when i actually tried to implement this in my solution i found that it doesn't work.  The issue is that content of my RadTreeNode is a UserControl which i mentioned in my original post.  The user control is specified using the <NodeTemplate> tag.  

<NodeTemplate>
      <uc5:wucExpression ID="wucExpression1" runat="server" />
</NodeTemplate>

This control has a number of RadComboBoxes, RadListBoxes and TextBoxes and buttons etc which are bound to various data sources. In this control the user makes a series of selections which drives the data binding options for each of the following fields found on the control.    When i tried your solution using the .Clone() method, i was able to get the child node into the correct position in the tree but the state of my node, i.e. all the comboboxes and lists box selections/values are wiped out.  The "cloned" node that has been added is completely empty, moreover any child nodes of the cloned node have this same issue. 

I recorded a quick video that demonstrates what we're seeing.

https://www.youtube.com/watch?v=x4X1pmlhQvs

I can see that the RadTreeNode.ParentNode property is just a wrapper for RadTreeNode.Owner, and RadTreeNode.Owner is defined as:

[Browsable(false)]
public IRadTreeNodeContainer Owner
{
    get
    {
        return this._owner;
    }
    internal set
    {
        this._owner = value;
    }
}


It's that blasted internal access modifier that is causing me such a headache.  Why isn't this Property exposed as public? It seems like if that was public it would fix all my problems since i could just re-assign the parent node that already exists, that is in the state that i want it to be in...  Either that, or the Clone() needs to fire some event that i can bind to in my user control that would let me copy the state of the user control so it isn't lost.

I'm at a loss of how to proceed. 

-Mark
0
Accepted
Ivan Danchev
Telerik team
answered on 03 Apr 2015, 03:53 PM
Hello Mark,

Thank you for recording a video.

Please find attached the same project, but modified to show transferring a node that has a UserControl in its NodeTemplate and preserving the selected RadComboBox item in the cloned node.

Regards,
Ivan Danchev
Telerik
 

See What's Next in App Development. Register for TelerikNEXT.

 
0
Mark Kucera
Top achievements
Rank 1
answered on 06 Apr 2015, 07:27 PM

Ivan, thanks for this.  Unfortunately this isn't really much better because the combo box items in the user control are all static, and it doesn't really account for copying over any settings from any subnode->nodes or subnode->nodes->nodes...  But before you lose any more sleep i wanted to let you know that i think i figured out a way to accomplish my objective.  It's a little bit of a PITA but it looks like it works.  I'm going to post the relevant code portions here in case anyone else wants to implement similar functionality. However i will repeat my previous comment that this would be so much easier if the Parent property was simply settable. That would make this workaround completely unnecessary and you could accomplish this task w/ a single line of code.  Since it's not settable you have to use the approach that Ivan explored using the RadTreeNode.Clone() method to create a copy of the subnodes and then you have to implement your own functionality to copy the correct state of your user control from the old node to the newly cloned node.

 So here it is... 

if (RadTreeView1.SelectedNode.Nodes.Count > 0)
{
    for (int i = 0; i < RadTreeView1.SelectedNode.Nodes.Count; i++)
    {
        RadTreeNode nodeToInsert = RadTreeView1.SelectedNode.Nodes[i].Clone();
                                 
        if (RadTreeView1.SelectedNode.ParentNode != null)
        {
            RadTreeView1.SelectedNode.ParentNode.Nodes.Insert(RadTreeView1.SelectedNode.Index + i, nodeToInsert);
        }
        else
        {
            RadTreeView1.Nodes.Insert(RadTreeView1.SelectedNode.Index + i, nodeToInsert);
        }
 
        CopyNodeSettings(nodeToInsert, RadTreeView1.SelectedNode.Nodes[i]);
    }
}
 
RadTreeView1.SelectedNode.Remove();

When you remove a node, and that node contains sub-nodes you include a little for loop to go through each of the sub-nodes.

 The RadTreeNode.Clone() method does a good job to clone any further subnodes but it doesn't copy any of the settings or state from your user control (that is being used as the node template).  You have to do the copying by hand, which is where: 

CopyNodeSettings(nodeToInsert, RadTreeView1.SelectedNode.Nodes[i]);

comes into play.  Before i get to the details of that method, i wanted to note that it's important that you call CopyNodeSettings() after you add the node to the correct location in the tree. Calling Nodes.Insert(RadTreeNode) is what triggers your RadTreeNode to have the NodeTemplate (your control) applied.  It is here that you can also bind any custom EventHandlers you need for your custom control. 

Now, on to CopyNodeSettings().    The two nodes passed into this method contain an identical node structure...  i.e. if the current node looks like

                A

            /          \

         B             E

     /       \

  C          D

 then nodeToInsert will also have the same structure, by virtue of having called the clone() method.

CopyNodeSettings looks like this:

private void CopyNodeSettings(RadTreeNode nodeToInsert, RadTreeNode nodeToCopy)
{
    wucExpression wucNew = (wucExpression)nodeToInsert.FindControl("wucExpression1");
    wucExpression wucOld = (wucExpression)nodeToCopy.FindControl("wucExpression1");
 
    if (wucNew == null)
    {
        return;
    }
 
   //copy settings from wucOld to wucNew until every setting, every control, every value etc is the same..
   //i.e.  wucNew.MyProperty1 = wucOld.MyProperty1
   //i.e.  wucNew.MyProperty2 = wucOld.MyProperty2 ...
   //if you have dropdown lists, comboboxes whatever you should be able to iterate through old and transfer items / values / selection preferences to new.
 
    //now we need to copy the node settings for each child node, if present, using recursion. we know the nodes map 1-1
    for (int i = 0; i < nodeToCopy.Nodes.Count; i++)
    {
        CopyNodeSettings(nodeToInsert.Nodes[i], nodeToCopy.Nodes[i]);
    }
}

 Hopefully this makes sense and if anyone else is looking to implement this, it will put you on the correct path.  Ivan, thanks for the time you spent trying to help.  i do appreciate the effort.

-Mark

 

0
Ivan Danchev
Telerik team
answered on 09 Apr 2015, 08:40 AM
Hello Mark,

Thank you for the detailed explanation and for sharing your solution.

Regards,
Ivan Danchev
Telerik
 

See What's Next in App Development. Register for TelerikNEXT.

 
Tags
TreeView
Asked by
Mark Kucera
Top achievements
Rank 1
Answers by
Ivan Danchev
Telerik team
Mark Kucera
Top achievements
Rank 1
Share this question
or