Gus*_*ori 6 c# user-interface deserialization
我有一个程序集,其中包含几个UserControl我希望能够通过应用程序UI保存/加载的对象.为此,每个控件都实现ISerializable接口以自定义需要保存的字段.
这是该库的简化版本:
namespace LibraryProject
{
using System;
using System.Runtime.Serialization;
using System.Windows.Forms;
[Serializable]
public partial class UserControl1 : UserControl, ISerializable
{
public UserControl1()
{
InitializeComponent();
}
public UserControl1(SerializationInfo info, StreamingContext ctxt)
: this()
{
this.checkBox1.Checked = info.GetBoolean("Checked");
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Checked", this.checkBox1.Checked);
}
}
}
Run Code Online (Sandbox Code Playgroud)
客户端应用程序实例化其中的几个控件,并允许用户保存/加载各种UserControl配置.这是应用程序的简化版本:
namespace ApplicationProject
{
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Soap;
using System.Windows.Forms;
using LibraryProject;
public partial class Form1 : Form
{
private const string filename = @"test.xml";
//int hash1;
//int hash2;
public Form1()
{
InitializeComponent();
//hash1 = this.ctrl1.GetHashCode();
}
private void SaveClick(object sender, EventArgs e)
{
using (var stream = File.Open(filename, FileMode.Create))
{
var formatter = new SoapFormatter();
formatter.Serialize(stream, this.ctrl1);
}
}
private void LoadClick(object sender, EventArgs e)
{
using (var stream = File.Open(filename, FileMode.Open))
{
var formatter = new SoapFormatter();
this.ctrl1= (UserControl1)formatter.Deserialize(stream);
}
//hash2 = this.ctrl1.GetHashCode();
}
}
}
Run Code Online (Sandbox Code Playgroud)
在SaveClick,值正确保存到文件.On LoadClick,CheckBox.Checked在Debugger Watch列表中正确更新,但UI不反映新值.
我曾尝试加入通话Refresh(),Invalidate(),Update(),但似乎没有任何工作.
正如所料,hash1并且hash2是不同的,但Form1使用正确的实例.
我做错了什么,如何修复UI以显示正确(更新)的值?
编辑:另外,请注意我需要处理多个配置文件,用户必须能够保存/加载到她选择的路径
我不确定,但我猜这是因为InitializeComponent没有被调用。
但要解决您的问题,最好序列化代理。只需将小代理类标记为 [Serialized] 并在序列化之前将属性从 UserControl 复制到代理类即可。然后您不必乱搞GetObjectData- 序列化过程只是假设代理的每个属性都应该被序列化。
反序列化过程会给你一个代理返回。代理只需要知道如何实例化 UserControl 并将属性映射回它。
如果您定义了一个通用接口,则不必知道要反序列化的是哪种特定类型的 UserControl:
var surrogate = formatter.Deserialize(stream) as ISerializationSurrogate;
UserControl uc = surrogate.Create();
this.Controls.Add(uc);
Run Code Online (Sandbox Code Playgroud)
以下是代理人的外观示例:
[Serializable]
public class MySurrogate: ISerializationSurrogate
{
public MySurrogate() {}
public MySurrogate(MyControl control)
{
CB1Checked = control.checkBox1.Checked;
}
public bool CB1Checked { get; set; }
public Control Create()
{
var control = new MyControl();
control.checkBox1.Checked = CB1Checked;
return control;
}
}
Run Code Online (Sandbox Code Playgroud)
更新
实际上,我敢打赌问题在于您只是重新分配this.ctrl,这不会改变表单上的控件。你实际上需要做的是这样的:
this.Controls.Remove(existingControl); // if it exists
this.Controls.Add(newControl);
Run Code Online (Sandbox Code Playgroud)
但您仍然应该使用序列化代理。他们使这类事情变得更加容易。
| 归档时间: |
|
| 查看次数: |
516 次 |
| 最近记录: |