none
TreeNodes/TreeView serialization RRS feed

  • Domanda

  • Hi,

    I have an abstract class NodeModel which inherits from TreeNode. I have classes A to E which inherits from NodeModel, and they are related to eachother this way in the node structure:
    • A
      • B
        • C
          • D
            • E

    So, basically I wanted to serialize my treeview, and I tried this code: http://www.codeproject.com/KB/tree/loadandsave.aspx

    This didnt work out for me, as it failed to serialize my additonal fields (to TreeNode) in NodeModel. The additional fields are some strings and ints, and a List<NodeModel> which I need.

    I then tried to serialize the A's (top nodes) instead, using GetObjectData, but when I serialize the List<NodeModel> it wont recursively serialize these nodes. The A nodes work out fine, but the child nodes dont.

    Serialize:
    Code Snippet

    foreach (A tn in tree.Nodes)
    {

    bf.Serialize(file, tn);

    }


    Deserialize:
    Code Snippet

    while(file.Position!=file.Length)

    tree.Nodes.Add((NodeModel)bf.Deserialize(file));


    What should I do? Did I maybe miss a easier way to solve this (with serialization)? I've read that serialization might not be a very good solution in general for TreeViews, but I hope I can make use of the work I've spent on serialization now instead of starting from scratch with another technique like DataBinding or something.

    Thanks in advance!

    Code Snippet

    public NodeModel(SerializationInfo info, StreamingContext ctxt)


                Name = (String)info.GetValue("Name", typeof(string));
                Description = (String)info.GetValue("Descr", typeof(string));
                ImageIndex = (int)info.GetValue("index", typeof(int));
                _children = (List<NodeModel>)info.GetValue("children", typeof(List<NodeModel>));
       
    }

    public A(SerializationInfo info, StreamingContext ctxt) : base(info, ctxt)
    {   
    // Have similiar constructors for B to E
    }

    public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
    {
                info.AddValue("Name", Name);
                info.AddValue("Descr", Description);
                info.AddValue("index", ImageIndex);
                info.AddValue("children", _children);
               
    }


    lunedì 31 marzo 2008 13:42

Risposte

  • VingeFaan,

     

    My approach would be totally different to the one your trying figure, for which there is a solution, but requires intervention to modify the serialization process to support your extended properties. I am sure someone else could explain that process better than I.

     

    Put simply as possible, my approach to this problem would be to create a Struct or Class to contain the various values I need for each node, and use the default TreeNode class. setting it's Tag property with my Struct.

     

    To retrieve the Struct/Class, simply cast your TreeNode.Tag property back to your Struct/Class

     

    If you think about it, you could easily create a collection for your Struct/Class. Your node struct itself can be made fully serializable, with two simple recurrsive methods to serialize (store nodes) and deserialize (populate nodes).

     

    (I will try to explain this a little better shortly!)

     

    Steve

     

     

    lunedì 31 marzo 2008 14:00
  • Thanks!

    My solution is as follows.

    Code Snippet

    public abstract class NodeModel : TreeNode, ISerializable
    {

    // Where I get all my attributes
    public NodeModel(SerializationInfo info, StreamingContext ctxt)
    {
    Description = (String)info.GetValue("Descr", typeof(string));
    // Removed the rest
    }

    //
    public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
    {
    info.AddValue("Descr", Description);
    // Removed the rest
    }


    }

    [Serializable]
    public class A: NodeModel
    {

    // Contains no code, calls NodeModel constructor, same for B to E

    public A(SerializationInfo info, StreamingContext ctxt) : base(info, ctxt)


    }



    Thats it I think. Nothing special I guess?


    Edit:
    Im saving the serialization to "file.osl", but I find it kinda annoying to have an .exe AND a .osl file when I have all other files as embedded resources. But I cannot write to embedded resources right? I guess there is no way other than a local file? I cannot use a remote file as every user should have its own serialization information.


    mercoledì 2 aprile 2008 09:37

Tutte le risposte

  • VingeFaan,

     

    My approach would be totally different to the one your trying figure, for which there is a solution, but requires intervention to modify the serialization process to support your extended properties. I am sure someone else could explain that process better than I.

     

    Put simply as possible, my approach to this problem would be to create a Struct or Class to contain the various values I need for each node, and use the default TreeNode class. setting it's Tag property with my Struct.

     

    To retrieve the Struct/Class, simply cast your TreeNode.Tag property back to your Struct/Class

     

    If you think about it, you could easily create a collection for your Struct/Class. Your node struct itself can be made fully serializable, with two simple recurrsive methods to serialize (store nodes) and deserialize (populate nodes).

     

    (I will try to explain this a little better shortly!)

     

    Steve

     

     

    lunedì 31 marzo 2008 14:00
  • Thanks Steve!

    I actually tried to delete the thread since it suddenly worked. But I guess it can be done much easier, and I look forward to your explanation if you still want to provide it! Smile


    lunedì 31 marzo 2008 14:07
  • If you have got it working then I'll leave it....'if it ain't broke....'

    I am interested to learn how you did this!

     

    lunedì 31 marzo 2008 14:09
  • Gonna let you know when I figure it out myself haha!
    lunedì 31 marzo 2008 14:13
  • My theory was'nt so hot after all, it took more code than I thought...

     

    It does work and does not require modification to the TreeView, TreeNode or TreeNodeCollection classes and does not use the Tag Property.

     

    Essentially, my solution uses a class called Node which contains a few basic properties for a tree node and some static methods to persist the Node class to file using serialization.

     

    I did not add properties for Checked, Tag or keys etc but the expanded state of the view persists.

     

    On the form hosting a TreeView control, nodes can be loaded using

     

    Node.Load(treeView1);

     

    and saved using:

     

    Node.Save(treeView1);

     

    In the example provided I am prompting for file but this could be handled internally and totally differently.

     

    http://www.itedge.co.uk/troubleshooter/treenodeserializer.zip

    lunedì 31 marzo 2008 15:49
  • Thanks!

    My solution is as follows.

    Code Snippet

    public abstract class NodeModel : TreeNode, ISerializable
    {

    // Where I get all my attributes
    public NodeModel(SerializationInfo info, StreamingContext ctxt)
    {
    Description = (String)info.GetValue("Descr", typeof(string));
    // Removed the rest
    }

    //
    public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
    {
    info.AddValue("Descr", Description);
    // Removed the rest
    }


    }

    [Serializable]
    public class A: NodeModel
    {

    // Contains no code, calls NodeModel constructor, same for B to E

    public A(SerializationInfo info, StreamingContext ctxt) : base(info, ctxt)


    }



    Thats it I think. Nothing special I guess?


    Edit:
    Im saving the serialization to "file.osl", but I find it kinda annoying to have an .exe AND a .osl file when I have all other files as embedded resources. But I cannot write to embedded resources right? I guess there is no way other than a local file? I cannot use a remote file as every user should have its own serialization information.


    mercoledì 2 aprile 2008 09:37