简体   繁体   中英

C# Serialize WinForm

I am trying to serialize a winform, with the end goal of being able to recreate the values in the various controls of the form. My form contains the typical controls, buttons/radio buttons/checkboxes/textboxes/listbox/tab control.

I am receiving this error:

An exception of type 'System.InvalidOperationException' occurred 
in System.Xml.dll but was not handled in user code

Additional information: There was an error reflecting type 
'Receptionist_Program.Objects.Client.Client_NCQ'.

I setup properties for each value I want to save:

    public bool CbMedTreat
    {
        get { return cbMedTreat.Checked; }
        set { cbMedTreat.Checked = value; }
    }

    public List<Client_AddDoctor> TxtDocExplain // Client_AddDoctor is another form
    {
        get { return listDoctors; }
        set { listDoctors = value; }
    }
    // etc, variety of string and bool properties

At the top of the class I have the decoration:

    [Serializable]
    public partial class Client_NCQ : Form

Finally, here is my code doing the serialization:

            Client_NCQ badname = new Client_NCQ();
        badname.Initialize();
        badname.ShowDialog();

        string result = "";

        XmlSerializer xmlSerializer = new XmlSerializer(typeof(Client_NCQ));
        // Error occurs here on above line: new XmlSerializer(typeof(Client_NCQ))
        using (StringWriter textWriter = new StringWriter())
        {
            xmlSerializer.Serialize(textWriter, badname);
            result = textWriter.ToString();
        }

I tried two different things so far, first, I added the decoration [XmlIgnore] to the List<> property, this made no difference. Second, I tried ensuring that the constructor was empty and had no parameters.

Serializing an entire Form is a bad idea because it is not meant to be serialized:

  • it has a lot of properties that should not be serialized (eg displaying related properties)
  • even if it works properly, you will have a lot of data that is not relevant for your application's state

The correct solution is to keep all state information in your custom objects and bind to those objects using WinForm's databinding capabilities. If this means great changes to your application, try to serialize only the data that is relevant to constructing the state.

How can you know which data is relevant for application state?

Before constructing and showing the form, I expect that you are loading the data from a database, file etc. All that information should be contained in clearly defined objects of types marked with [Serializable] attribute. This way, it is easy to serialize and deserialize it at will.

Also, it is important to take into consideration version tolerant serialization or what happens when the form / state information is changed (eg a field is added) and an older XML is used to restore state.

Every form has its own mechanism to store and retrieve (serialize and deserialize) data and it does this automatically. However, the following conditions are to be met in order to use this feature automatically.

-  All properties which are desired to be serialized must have public get and set accesor.
 - If a certain property represents custom object such as user defined class or struct, the object must be adorned with [Serializable] attribute.
 - Property which is desired to be serialized must not have [DesignerSerializationVisibility] attribute set to Hidden. By default it is Visible so not specifying this attribute at all is sufficiently serves the purpose.

Consider this example:

namespace MnM.Drawing
{
    [Serializable, TypeConverter(typeof(ExpandableObjectConverter))]
    public class Coordinates
    {
        public int X { get; set; }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int Y { get; set; }

        public int Z { get; protected set; }
    }

    public class MyForm : Form
    {

        [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
        public Coordinates MyCoordinates { get; set; }
    }
}

Now, MyForm will automatically serialize MyCoordinates object but...

  • Only property X will get serialized because it fits the requisite status to qualify for auto serialization.
  • Property Y can not be serialized because of DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
  • Property Z can not get serialized automatically because it does not have public set accesor.

In order to serialize Y and Z, custom serialization code is required. In most cases, need of custom serialization does not arise and custom serialization can be done in many ways but its a vast topic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM