Question

I have one class and I set [Serializable] attribute to that class.

in this class I define one font class member.but when I am trying to serialize it gives me an error like "system.drawing.font cannot be serialized"

Was it helpful?

Solution

I did this in a recent project:

[XmlIgnore()]
public Font Font {
  get { return mFont; }
  set { mFont = value; }
}

[Browsable(false)]
public string FontHidden {
  get { return FontSerializationHelper.Serialize(mFont); }
  set { mFont = FontSerializationHelper.Deserialize(value); }
}

The FontSerializationHelper class is as follows:

using System.Windows.Forms;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Text.RegularExpressions;
using System.Xml.Serialization;

[TypeConverter(typeof(FontConverter))]
internal class FontSerializationHelper
{
    public static Font Deserialize(string value)
    {
        object m = Regex.Match(value, "^(?<Font>[\\w ]+),(?<Size>(\\d+(\\.\\d+)?))(,(?<Style>(R|[BIU]{1,3})))?$", RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase);

        if (m.Success) 
        {
            if (m.Groups.Count < 4 || m.Groups(3).Value == "R") 
            {
                return new Font(m.Groups("Font").Value, Single.Parse(m.Groups("Size").Value));
            } 
            else 
            {
                object fs = m.Groups(3).Value.IndexOf("B") >= 0 ? FontStyle.Bold : FontStyle.Regular | m.Groups(3).Value.IndexOf("I") >= 0 ? FontStyle.Italic : FontStyle.Regular | m.Groups(3).Value.IndexOf("U") >= 0 ? FontStyle.Underline : FontStyle.Regular;
                return new Font(m.Groups("Font").Value, Single.Parse(m.Groups("Size").Value), fs);
            }
        } 
        else 
        {
            throw new FormatException("Value is not properly formatted.");
        }
    }

    public static string Serialize(Font value)
    {
        string str;

        str = value.Name + "," + value.Size.ToString() + ",";
        if (value.Style == FontStyle.Regular) 
        {
            str += "R";
        } 
        else 
        {
            if (value.Bold) str += "B";
            if (value.Italic) str += "I";
            if (value.Underline) str += "U";
        }

        return str;
    }
}

Note that I'm just saving Font Family, Size and Style information. You may want to add more to it.

OTHER TIPS

Even if this question is old, here are my solutions:

Solution #1 (this one lose GdiCharSet and GdiVerticalFont parameter):

private Font font = new Font("Arial", 13f, FontStyle.Regular, GraphicsUnit.Pixel, 0, false);

[XmlIgnore()]
public Font Font {
    get { return font; }
    set { font = value; }
}

[Browsable(false)]
public string FontSerialize {
    get { return TypeDescriptor.GetConverter(typeof(Font)).ConvertToInvariantString(font); }
    set { font = TypeDescriptor.GetConverter(typeof(Font)).ConvertFromInvariantString(value) as Font; }
}

Solution #2 (utilizing all Font constructor parameter):

Properties:

[XmlIgnore()]
public Font Font {
    get { return font; }
    set { font = value; }
}

[Browsable(false)]
public string FontSerialize {
    get { return FontSerializationHelper.ToString(font); }
    set { font = FontSerializationHelper.FromString(value); }
}

FontSerializationHelper class:

[TypeConverter(typeof(FontConverter))]
static public class FontSerializationHelper {

    static public Font FromString(string value) {
        var parts = value.Split(':');
        return new Font(
            parts[0],                                                   // FontFamily.Name
            float.Parse(parts[1]),                                      // Size
            EnumSerializationHelper.FromString<FontStyle>(parts[2]),    // Style
            EnumSerializationHelper.FromString<GraphicsUnit>(parts[3]), // Unit
            byte.Parse(parts[4]),                                       // GdiCharSet
            bool.Parse(parts[5])                                        // GdiVerticalFont
        );
    }

    static public string ToString(Font font) {
        return font.FontFamily.Name
                + ":" + font.Size
                + ":" + font.Style
                + ":" + font.Unit
                + ":" + font.GdiCharSet
                + ":" + font.GdiVerticalFont
                ;
    }
}

EnumSerializationHelper class:

[TypeConverter(typeof(EnumConverter))]
static public class EnumSerializationHelper {

    static public T FromString<T>(string value) {
        return (T)Enum.Parse(typeof(T), value, true);
    }
}

You can't serialize a Font. You can't serialize most GDI resources.

You can try to use the FontConverter class to serialize it to a string for you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top