C# 序列化 WinForm

问题描述 投票:0回答:2

我正在尝试序列化 winform,最终目标是能够重新创建表单的各个控件中的值。我的表单包含典型的控件,按钮/单选按钮/复选框/文本框/列表框/选项卡控件。

我收到此错误:

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'.

我为每个要保存的值设置属性:

    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

在班级的顶部我有装饰:

    [Serializable]
    public partial class Client_NCQ : Form

最后,这是我执行序列化的代码:

            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();
        }

到目前为止,我尝试了两种不同的方法,首先,我将装饰 [XmlIgnore] 添加到 List<> 属性,这没有什么区别。其次,我尝试确保构造函数为空并且没有参数。

c# xml winforms serialization
2个回答
3
投票

序列化整个

Form
是一个坏主意,因为它并不意味着被序列化:

  • 它有很多不应该序列化的属性(例如显示相关属性)
  • 即使它工作正常,你也会有很多与你的应用程序状态无关的数据

正确的解决方案是将所有状态信息保留在自定义对象中,并使用 WinForm 的数据绑定功能绑定到这些对象。如果这意味着您的应用程序会发生巨大变化,请尝试仅序列化与构造状态相关的数据。

如何知道哪些数据与应用程序状态相关?

在构建和显示表单之前,我希望您从数据库、文件等加载数据。所有这些信息都应包含在用

[Serializable]
属性标记的类型的明确定义的对象中。这样就可以很方便的随意序列化和反序列化了。

此外,重要的是要考虑版本容忍序列化或当表单/状态信息更改(例如添加字段)并且使用较旧的 XML 来恢复状态时会发生什么情况。


0
投票

每个表单都有自己的存储和检索(序列化和反序列化)数据的机制,并且它会自动执行此操作。但是,要自动使用此功能,需要满足以下条件。

  • 所有需要序列化的属性都必须具有公共 get 和 set 访问器。
  • 如果某个属性代表自定义对象,例如用户定义的类或结构,则该对象必须用 [Serialized] 属性修饰。
  • 需要序列化的属性不得将 [DesignerSerializationVisibility] 属性设置为隐藏。默认情况下它是可见的,因此根本不指定此属性就足以达到目的。

考虑这个例子:

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; }
    }
}

现在,MyForm 将自动序列化 MyCooperatives 对象,但是...

  • 只有属性 X 才会被序列化,因为它符合必要条件 状态有资格自动序列化。
  • 由于 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),属性 Y 无法序列化
  • 属性 Z 无法自动序列化,因为它确实 没有公共设置访问器。

为了序列化 Y 和 Z,需要自定义序列化代码。在大多数情况下,不会出现自定义序列化的需要,并且可以通过多种方式完成自定义序列化,但这是一个广阔的主题。

© www.soinside.com 2019 - 2024. All rights reserved.