我在visual studio 2008中使用winforms。
我想创建一个包含控件和所有事件的表单的EXACT副本,以及与我相同的所有代码。
这可以在运行时做吗?我该怎么做?
不应该有某种类解决方案,如:
Form form2 = new Form();
form2 = form1 ???
答案 0 :(得分:5)
只需创建同一个类的另一个实例。使用类的实际名称而不是基类Form
。
Form form2 = new Form1();
form2.Show();
答案 1 :(得分:1)
从臀部拍摄,序列化表格并将其反序列化为第二个变量。 :)我会尝试研究这个问题并提出更多答案。
要注意的一些事项......你想要一个浅或深的副本吗? I.E.,如果表单有一个对象的引用,你想复制引用(所以两个表单都指向同一个对象),还是制作该对象的副本?你必须要小心......对于包含对其他对象的引用的对象,不能保证它们将被反序列化
您不需要,但从ICloneable继承是一种好习惯,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上有一个很好的例子,可以创建一个通用的对象复制器。非常好!
Deep cloning objects
*编辑*
序列化表单的问题在于,并非所有值都可以真正序列化......它们没有意义,例如各个控件上的句柄。
要使表单可序列化,您需要实现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流中,并在创建新对象时将其拉出。这将允许我的克隆原始代码工作。