Reputation: 43
I created a class
[Serializable]
public class clsCategories
{
public static List<infoCategories> listCategories = new List<infoCategories>();
public void serialize()
{
BinaryFormatter bf = new BinaryFormatter();
FileStream fs = new FileStream("categories.dat", FileMode.Create);
bf.Serialize(fs, listCategories);
fs.Close();
}
[Serializable]
public class infoCategories
{
public PictureBox img { get; set; }
public Label lbl { get; set; }
}
}
Now when calling this method...
private void btnDone_Click(object sender, EventArgs e)
{
objCategories.serialize();
this.Hide();
}
I got this error:
An unhandled exception of type 'System.Runtime.Serialization.SerializationException' occurred in mscorlib.dll
Additional information: Type 'System.Windows.Forms.PictureBox' in Assembly 'System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.
Where am i mistaking?
Upvotes: 3
Views: 1763
Reputation: 125332
It's said in comments and Kuba's answer that PictureBox
and Label
are not serializable and that's the reason for error. It's not enough to decorate a class with Serializable
attribute, all it's properties should be Serializable
too.
Instead you can create a class containing a string and an Image and try to serialize it. But unfortunately Image
isn't serializable too.
Note: I didn't used Bitmap
because the image of PicturebBox
maybe a gif or something else.
How Can I serialize a class containing an Image and a string?
For the image, you should serialize it as byte[]
. So you can create a class like this:
using System;
using System.Drawing;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable]
public partial class MyData
{
public string Label { get; set; }
byte[] bytes;
[NonSerialized]
Image image;
public Image Image
{
get
{
if (image == null && bytes != null)
image = (Image)((new ImageConverter()).ConvertFrom(bytes));
return image;
}
set
{
image = value;
bytes = (byte[])new ImageConverter().ConvertTo(value, typeof(byte[]));
}
}
}
Then to serialize and deserialize it, you can add a Save
and Load
method to the class.
public partial class MyData
{
public void Save(string file)
{
using (Stream stream = File.Open(file, FileMode.Create))
{
BinaryFormatter bin = new BinaryFormatter();
bin.Serialize(stream, this);
}
}
public static MyData Load(string file)
{
using (Stream stream = File.Open(file, FileMode.Open))
{
BinaryFormatter bin = new BinaryFormatter();
return (MyData)bin.Deserialize(stream);
}
}
}
And here is an example usage:
var m1 = new MyData() { Label = label1.Text, Image = pictureBox1.Image };
m1.Save(@"d:\m1.dat");
var m2 = MyData.Load(@"d:\m1.dat");
label2.Text = m2.Label;
pictureBox2.Image = m2.Image;
Upvotes: 2
Reputation: 6221
When serializing the list of objects of type infoCategories
- all properties of these objects are serialized. So is the img
property, which happens to be of type PictureBox
. Since PictureBox
is not serializable itself - you get the error.
The same would happen to Label lbl
by the way. No window control can be serialized this way AFAIK.
What are your options?
First: mark all non-serializable fields in your class with [NonSerialized]
. This makes the serializer skip the property during read and write. But, since this essentially would lead to an empty class - this is probably not good option here.
Another option is to serialize the very plain data needed to save and restore the objects as you use them. So instead of serializing Label
you serialize the string
which happens to be this label's text. After deserialization you could recreate a list of labels from the list of strings. The same applies to image contained in picture box (which could be i.e. base64 encoded to string).
The last option is serialization surrogate (Is it possible to do .NET binary serialization of an object when you don't have the source code of the class?) but this would rather be an overkill here.
Upvotes: 4