locked
multiple use of a TreeNode RRS feed

  • Question

  • Hej

    I´m trying to dynamically create a TreeView.

    When the TreeNodes have been created they are stored in a list, and then I will add some of them to the TreeView.

    My problem is that some TreeNodes should be able to be used in more than one node of the TreeView.

    I have tried to put them into different sub-nodes, at the same level, but they all end up in the last used sub-node.

    If I make a clone of the TreeNode and use the clone they all end up as I wish but I loose the control over the clone, as i want to update the TreeNodes in my list and have all nodes in the TreeView updated.

     

    Hope anyone could give me some help on this!

    • Moved by CoolDadTx Friday, September 17, 2010 1:38 PM Winforms related (From:Visual C# General)
    Friday, September 17, 2010 11:17 AM

Answers

  • Here's how I'd do it (if you really want 2 nodes to be connected):

    class SharedData : INotifyPropertyChanged
    {
       public event PropertyChangedEventHandler PropertyChanged;

       public string TextValue
       {
          get { return m_text ?? ""; }
          set
          {
             if (m_text != value)
             {
                m_text = value;
                OnPropertyChanged("TextValue");
             };
          }
       }

       private void OnPropertyChanged ( string propertyName )
       {
          var hdlr = PropertyChanged;
          if (hdlr != null)
              hdlr(this, new PropertyChangedEventArgs(propertyName);
       }
    }

    public class SharedDataTreeNode : TreeNode
    {
       public SharedDataTreeNode ( SharedData data ) : base(data.TextValue)
       {
          Tag = data;
          data.PropertyChanged += (o,e) => Text = data.TextValue;
       }
    }

    //Later
    SharedData data1 = new SharedData();
    data1.TextValue = "Some Text";

    SharedDataTreeNode node1 = new SharedDataTreeNode(data1);
    myTree.Nodes.Add(node1);
    SharedDataTreeNode node2 = new SharedDataTreeNode(data1);
    myTree.Nodes.Add(node2);

    This would be the most maintainable approach.  Note that the above code doesn't handle error conditions nor does it handle the case of the shared data being changed on a non-UI thread.  If those are concerns then you'll need to fix up the code.

    Michael Taylor - 9/23/2010
    http://msmvps.com/blogs/p3net

    • Proposed as answer by Helen Zhou Friday, September 24, 2010 3:48 AM
    • Marked as answer by Helen Zhou Monday, September 27, 2010 3:00 AM
    Thursday, September 23, 2010 1:31 PM

All replies

  • The situation you describe is not of a tree, more of a graph, and no, that is not a control in net, is  data structure.  Choices are:

    1. Clone as you where and keep a link between them so when you update one, you update the other.
    2. Create/find your own control that support what you want

    Regards

    Friday, September 17, 2010 12:08 PM
  • You can use a TreeView for this because you aren't really interested in the nodes themselves being duplicates but the data within them.  Each node can have an object associated with it.  The Tag property is available for this purpose although most people create a strongly-typed node instead.  When you need to "clone" a node you just create a new node and assign it the same Tag object.  You can then insert the node anywhere in the tree.  If your data object supports INotifyPropertyChanged then you can get notifications when data changes.  I'm not sure how the treenode works with INPC but in the worse case you can handle the event explicitly.  This is where a custom treenode type would really pay off as each node could handle its data's INPC event and update itself accordingly.

    Michael Taylor - 9/17/2010
    http://msmvps.com/blogs/p3net

    Friday, September 17, 2010 1:37 PM
  • I tried this:

    ...

    TreeNode myNode = new TreeNode("My text");

    TreeNode clone1 = (TreeNode)myNode.Clone();

    clone1.Tag = myNode;

    TreeNode clone2 = (TreeNode)myNode.Clone();

    clone2.Tag = myNode;

    myTreeView.Nodes.Add(clone1);

    myTreeView.Nodes.Add(clone2);

    ...

    so far so good.

    But later when I try to change my node:

    ...

    myNode.Text = "New text";

    ...

    None of my clones will change.

     

    Do you know what I am doing wrong?

     

    Thursday, September 23, 2010 9:41 AM
  • They are clones, they have free will :)  The information at the beginning will be the same but they are not connected anymore.

    You can as @CoolDadTx said use the INotifyPropertyChanged property for that, using a custom treenode that implements it and that will keep all the clones updated.

    Regards

    Thursday, September 23, 2010 12:19 PM
  • Here's how I'd do it (if you really want 2 nodes to be connected):

    class SharedData : INotifyPropertyChanged
    {
       public event PropertyChangedEventHandler PropertyChanged;

       public string TextValue
       {
          get { return m_text ?? ""; }
          set
          {
             if (m_text != value)
             {
                m_text = value;
                OnPropertyChanged("TextValue");
             };
          }
       }

       private void OnPropertyChanged ( string propertyName )
       {
          var hdlr = PropertyChanged;
          if (hdlr != null)
              hdlr(this, new PropertyChangedEventArgs(propertyName);
       }
    }

    public class SharedDataTreeNode : TreeNode
    {
       public SharedDataTreeNode ( SharedData data ) : base(data.TextValue)
       {
          Tag = data;
          data.PropertyChanged += (o,e) => Text = data.TextValue;
       }
    }

    //Later
    SharedData data1 = new SharedData();
    data1.TextValue = "Some Text";

    SharedDataTreeNode node1 = new SharedDataTreeNode(data1);
    myTree.Nodes.Add(node1);
    SharedDataTreeNode node2 = new SharedDataTreeNode(data1);
    myTree.Nodes.Add(node2);

    This would be the most maintainable approach.  Note that the above code doesn't handle error conditions nor does it handle the case of the shared data being changed on a non-UI thread.  If those are concerns then you'll need to fix up the code.

    Michael Taylor - 9/23/2010
    http://msmvps.com/blogs/p3net

    • Proposed as answer by Helen Zhou Friday, September 24, 2010 3:48 AM
    • Marked as answer by Helen Zhou Monday, September 27, 2010 3:00 AM
    Thursday, September 23, 2010 1:31 PM