Home > Net >  Best way to persist TreeView tag that has an object attached to it
Best way to persist TreeView tag that has an object attached to it

Time:09-29

I've created a TreeView, in which some of the nodes have the Tag property set as an object Machine which contains an IP address, FQDN and a friendly name as strings

I can persist the TreeView, keeping the structure of the tree when reloading the program using XML. However, the Tag value is just Project.Machine and obviously doesn't contain the data.

The program works by asking the user to input the data into textboxes, which are then created into the machine object, and then tied to the selected nodes Tag property.

Should I serealize the class and then add the Tag property to the node when the program initiates?

Here's the class to persist the TreeView

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace PRTG_Ripoff
{
    internal class TreeViewSerializer
    {
        // Constants
        // Xml tag for node
        private const string XmlNodeTag = "node";

        // Xml attributes for node
        private const string XmlNodeTextAtt = "text";
        private const string XmlNodeTagAtt = "tag";
        private const string XmlNodeImageIndexAtt = "imageindex";

        public void DeserializeTreeView(TreeView tv, string filename)
        {
            XmlTextReader reader = null;

            try
            {
                // disable re-drawing of tree view till nodes are added
                tv.BeginUpdate();
                reader = new XmlTextReader(filename);
                TreeNode parentNode = null;

                while(reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        if (reader.Name == XmlNodeTag)
                        {
                            TreeNode newNode = new TreeNode();
                            bool isEmptyElement = reader.IsEmptyElement;

                            // loading node attributes
                            int attributeCount = reader.AttributeCount;
                            if (attributeCount > 0)
                            {
                                for (int i = 0; i < attributeCount; i  )
                                {
                                    reader.MoveToAttribute(i);
                                    SetAttributeValue(newNode,
                                                 reader.Name, reader.Value);
                                }
                            }
                            // add new node to Parent Node or TreeView
                            if (parentNode != null)
                                parentNode.Nodes.Add(newNode);
                            else
                                tv.Nodes.Add(newNode);

                            // making current node 'ParentNode' if its not empty
                            if (!isEmptyElement)
                            {
                                parentNode = newNode;
                            }
                        }
                    }


                    // moving up to in TreeView if end tag is encountered
                    else if (reader.NodeType == XmlNodeType.EndElement)
                    {
                        if (reader.Name == XmlNodeTag)
                        {
                            parentNode = parentNode.Parent;
                        }
                    }
                    else if (reader.NodeType == XmlNodeType.XmlDeclaration)
                    {
                        //Ignore Xml Declaration                    
                    }
                    else if (reader.NodeType == XmlNodeType.None)
                    {
                        return;
                    }
                    else if (reader.NodeType == XmlNodeType.Text)
                    {
                        parentNode.Nodes.Add(reader.Value);
                    }
                    
                }
            }

            finally
            {
                // enabling redrwaing of treeview
                tv.EndUpdate();
                reader.Close();
            }
        }

        /// Used by Deserialize method for setting properties of
        /// TreeNode from xml node attributes
        private void SetAttributeValue(TreeNode node,
                           string propertyName, string value)
        {
            if (propertyName == XmlNodeTextAtt)
            {
                node.Text = value;
            }
            else if (propertyName == XmlNodeImageIndexAtt)
            {
                node.ImageIndex = int.Parse(value);
            }
            else if (propertyName == XmlNodeTagAtt)
            {
                node.Tag = value;
            }
        }

        public void SerializeTreeView(TreeView treeView, string fileName)
        {
            XmlTextWriter textWriter = new XmlTextWriter(fileName,
                                          System.Text.Encoding.ASCII);
            // writing the xml declaration tag
            textWriter.WriteStartDocument();
            //textWriter.WriteRaw("\r\n");
            // writing the main tag that encloses all node tags
            textWriter.WriteStartElement("TreeView");

            // save the nodes, recursive method
            SaveNodes(treeView.Nodes, textWriter);

            textWriter.WriteEndElement();

            textWriter.Close();
        }

        private void SaveNodes(TreeNodeCollection nodesCollection, XmlTextWriter textWriter)
        {
            for (int i = 0; i < nodesCollection.Count; i  )
            {
                TreeNode node = nodesCollection[i];
                textWriter.WriteStartElement(XmlNodeTag);
                textWriter.WriteAttributeString(XmlNodeTextAtt,
                                                           node.Text);
                textWriter.WriteAttributeString(
                    XmlNodeImageIndexAtt, node.ImageIndex.ToString());
                if (node.Tag != null)
                    textWriter.WriteAttributeString(XmlNodeTagAtt,
                                                node.Tag.ToString());
                // add other node properties to serialize here  
                if (node.Nodes.Count > 0)
                {
                    SaveNodes(node.Nodes, textWriter);
                }
                textWriter.WriteEndElement();
            }
        }
    }
}

And how I'm creating the object

        private void Details_Btn_Click(object sender, EventArgs e)
        {
            // If the text boxes aren't empty
            if (FQDN_Txt.Text != "" && IP_Txt.Text != "" && Name_Txt.Text != "")
            {
                if(mainTree.SelectedNode == null)
                {
                    // If no node is selected
                    MessageBox.Show("Select a node!");
                } else
                {
                    // Create new machine object using data from the text boxes
                    Machine machine = new Machine(FQDN_Txt.Text, Name_Txt.Text, IP_Txt.Text);
                    // Set the tag as the machine object
                    mainTree.SelectedNode.Tag = machine;
                }
            } else
            {
                MessageBox.Show("these are empty mate");
            }
        }

And how I'm retrieving the data from the Tag property

        private void mainTree_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            mainTree.SelectedNode = e.Node;
            TreeNode tn = mainTree.SelectedNode;

            infoPanel.Visible = true;
            MachineName_lbl.Text = tn.Text;

            if (mainTree.SelectedNode.Tag != null)
            {
                IP_Lbl.Text = ((Machine)mainTree.SelectedNode.Tag).MachineIP;
            }
        }

CodePudding user response:

As you don't currently use the Machine object instance anywhere else, then rather than create a complete instance and save it in Tag you could instead just create either a Tuple or KeyValuePair and save that in the Tag.

Then you can easily Serialise these values when you write your nodes in SaveNodes. (and then read it again and create and add the Tuple / KeyValuePair).

If you later need to use the Machine object, then you could just seralise the key and then do a look-up from your collection of Machine. Either do this when you need it, or at the time you create your Treeview Nodes (and asign it to Tag).

  • Related