tags:

views:

853

answers:

6

I have been working on an application which allows the user to make a label template for printing purposes by adding label controls to a panel(which I use as a container). I have reached the point where I need to be able to save the template to a file which I can load into memory later for printing. Since the form is not serializable does anyone have suggestions on how I can save the form or container(with added label controls) to a file that can be reused later?

Thanks.

+1  A: 

Personally, I would serialize it as JSON. When bringing it back you can use a generic method that loops through and sets the properties through reflection. Also take notice that the library I've linked to will automatically serialize objects that you pass to it.

JSON

JSON.NET

[{ "Label": [{"Top": 102}, {"Left": 105}, {"Text": "blah, blah"}] }]

From JSON.NET

Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };

string json = JsonConvert.SerializeObject(product);
//{
//  "Name": "Apple",
//  "Expiry": new Date(1230422400000),
//  "Price": 3.99,
//  "Sizes": [
//    "Small",
//    "Medium",
//    "Large"
//  ]
//}

Product deserializedProduct = JsonConvert.DeserializeObject<Product>(json);
ChaosPandion
Never used JSON but I am not opposed to learning new things.
Nathan
A: 

You can get the position, size and other properties about the form's controls at runtime and save that state in an XML or JSON file.

Rulas
+1  A: 

This isn't trivial, but personally I would set up a function that can be called recursively that would add nodes to an XML file.

I don't have actual code, but pseudo-code looks like this: (you will need to do some clean-up, because I'm doing this off the top of my head without the aid of Intellisense.)

XmlDocument doc;

function SaveForm()
{
   doc = new XmlDocument("FormInfo");
   foreach(Control ctrl in this.Controls)
   {
      AddControlToXml(ctrl, doc.Documentelement);
   }
}

function AddControlToXml(Control ctrl, XmlNode currentNode)
{
   XmlNode n = new XmlNode;
   Node.InnerText = ctrl.Name;
   foreach(Control ctrl2 in ctrl.Controls)
   {
      AddControlToXml(ctrl2);
   }

}
David Stratton
Looks like C# to me. (Except for the JavaScript function declaration.)
ChaosPandion
I don't see the recursion here... this is first level iteration
jmayor
well two level iteration.. you are not going further that the first container..
jmayor
Um.. AddControlToXml calling AddControlToXml... A subroutine calling itself as needed based on child controls of the control passed to it... What's the definition of recursion again?
David Stratton
http://en.wikipedia.org/wiki/Recursion
David Stratton
@ChaosPandion - thanks for the edit. I was on the way out the door for a meeting as I was finishing that up. I didn't se that I forgot to format it as code.
David Stratton
+1  A: 

Try this. It uses the ISerializationSurrogate interface to get around the problem of the form object not being serializable:

How to serialize an object which is NOT marked as 'Serializable' using a surrogate. http://www.codeproject.com/KB/dotnet/Surrogate_Serialization.aspx

Robert Harvey
+3  A: 

I wouldn't directly serialize a form to a file. Sounds like you need to create a class that will hold the state of the user's work. You should then serialize that class to and from a file. There are built in methods for that using either Binary or XML Serialization.

OG
@Nathan: Note that if you use this method, you must create your controls dynamically again based on the data present in the state class.
Robert Harvey
That probably wouldn't be a problem. I would just have get the important property information from each control and then serialize it to file correct?
Nathan
+1  A: 
  1. Create a struct that contains enough information (and no more) about each Label that you can reconstitute the Label from it.

  2. Write a method that takes a List<MyStruct> and populates a Panel from your structs.

  3. Write methods to serialize and deserialize this list.

  4. Encapsulate the whole thing in a class.

Robert Rossney
That is exactly what I thinking after reading OG's answer. Thanks!
Nathan
Got it all coded up and it is working perfectly now. Thanks so much everyone.
Nathan