2

I am writing a program in C#, which assigns data to a class, then assigns that class to the Tag Value of treeview nodes.

I am able to serialize my treeview to file using an answer I found here: Saving content of a treeview to a file and load it later.

However, the Tag of all the nodes is lost using this method when de-serializing the file, or more likely, they are not even being serialized in the first place.

Is it possible to preserve the Tag value of the Nodes when serialized using this method? If so, how?

Community
  • 1
  • 1
PoTheCoder
  • 23
  • 3

2 Answers2

0

To be serialized successfully by BinaryFormatter, your Tag object must be marked as [Serializable], which indicates that it can be successfully serialized and deserialized by serializing its public and private fields. If it is so marked, then it will be serialized as part of a TreeNode, as is shown by the reference source:

[TypeConverterAttribute(typeof(TreeNodeConverter)), Serializable,
DefaultProperty("Text"),    
SuppressMessage("Microsoft.Usage", "CA2240:ImplementISerializableCorrectly")]
public class TreeNode : MarshalByRefObject, ICloneable, ISerializable {

    object userData;

    protected virtual void Serialize(SerializationInfo si, StreamingContext context) {

        // SNIP storage of irrelevant fields.

        if (userData != null && userData.GetType().IsSerializable) {
            si.AddValue("UserData", userData, userData.GetType());
        }
    }

    public object Tag {
        get {
            return userData;
        }
        set {
            userData = value;
        }
    }
 }

Note that, if your Tag object is not serializable, it will be silently skipped; no exception will be thrown.

dbc
  • 104,963
  • 20
  • 228
  • 340
  • Exactly what I was needing. Thank you very much, I hope the question was up to par with the standards expected here. Just to clarify, all I needed to do was mark the class I was assigning TO the Tag as [Serializable()], it was inherited to Tag. – PoTheCoder Sep 17 '15 at 05:07
0

I'd like to improve upon this answer.

It's important that [Serializable()] be used before the class and that the class is derived from ISerializable.

Additionally, the presence of the overloaded constructor function that can accept the arguments from deserialization and the GetObjectData function were important.

In essence, the GetObjectData function provides the ability for the serializer to access all information as a string while the overloaded NodeTag constructor can re-interpret that serialized string data and load it back into the object.

I had to construct my class in the following fashion (this is semi-pseudo code):

[Serializable()]
class NodeTag : ISerializable
    {
        public NodeTag(string Subnet)
        {
         Broadcast_Address = Stuff;
         Network_Name = Stuff;
         CIDR_Value = Stuff;
         }
        public string Network_Name { get; set; }
        public string CIDR_Value { get; set; }
        public string Broadcast_Address { get; set; }

        //Deserializer - loads back from file data
        //This is an overloaded function that defines the data object when it is being reconstituted
        public NodeTag(SerializationInfo info, StreamingContext context)
        {
            Network_Name = (String)info.GetValue("Network_Name", typeof(string));
            CIDR_Value = (String)info.GetValue("CIDR_Value", typeof(string));
            Broadcast_Address = (String)info.GetValue("Broadcast_Address", typeof(string));
        }
        //Serializer - loads into file data
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Network_Name", Network_Name);
            info.AddValue("CIDR_Value", CIDR_Value);
            info.AddValue("Broadcast_Address", Broadcast_Address);
        }
    }
Shrout1
  • 2,497
  • 4
  • 42
  • 65