我正在使用Visual Studio 2008中的WinForms。
我想要创建一个完全复制我的窗体,包括所有控件和事件,以及与我现有代码相同的所有代码。
这在运行时是否可能?我该如何做?
难道不应该有某种类的解决方案,例如:
Form form2 = new Form();
form2 = form1 ???
只需创建同一类的另一个实例。使用类的实际名称代替基类Form
。
Form form2 = new Form1();
form2.Show();
直接将表单序列化并反序列化到第二个变量中。:)我会尝试研究一下并提供更详细的答案。
需要注意一些事项...您想要浅拷贝还是深拷贝?例如,如果表单引用对象,您想要复制引用(这样两个表单都指向同一个对象),还是也要复制该对象?您需要小心...包含对其他对象的引用的对象不能保证它们将被反序列化的顺序
您不需要这样做,但从ICloneable继承是一个好习惯,它只有一个方法Clone()
。覆盖此方法的代码类似于以下代码:
public object Clone() {
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
formatter.Serialize(stream, this);
stream.Seek(0, SeekOrigin.Begin);
return (MyForm) formatter.Deserialize(stream);
}
使用方法:
MyForm form2 = form1.Clone() as MyForm;
if (form2 != null) {
// yahoo!
}
* 编辑 *
实际上,这里在SO上有一个非常好的例子,可以创建一个通用的对象复制器。非常棒!
深度克隆对象
* 编辑 *
序列化表单的问题在于,并不是所有的值都能被序列化...它们没有意义,例如各个控件的句柄。
为了使表单可序列化,您需要实现ISerializable接口,并实现适当的构造函数和GetObjectData()方法。在GetObjectData中,您需要枚举您的控件,并存储您想要复制的属性(例如Text或Value)。构造函数将它们读回来。它看起来像这样:
public partial class MyForm : Form, ISerializable {
public MyForm() {}
public MyForm(SerializationInfo info, StreamingContext context) : base() {
foreach (Control control in Controls) {
control.Text = info.GetString(control.Name);
}
}
public void GetObjectData(SerializationInfo info, StreamingContext context) {
foreach (Control control in Controls) {
info.AddValue(control.Name, control.Text);
}
}
}
思路是枚举表单,将每个值放入SerializationInfo流中,并在创建新对象时将其拉回。这将使我的原始克隆代码起作用。