【发布时间】:2011-05-05 20:43:43
【问题描述】:
我在 Visual Studio 2008 中使用 winforms。
我会创建一个包含控件和所有事件以及所有与我相同的代码的表单的精确副本。
这可以在运行时进行吗?我该怎么做?
是否应该有某种类解决方案,例如:
Form form2 = new Form();
form2 = form1 ???
【问题讨论】:
我在 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!
}
* 编辑 *
实际上这里有一个很好的例子,它创建了一个通用的对象复制器。非常好!
Deep cloning objects
* 编辑 *
序列化表单的问题在于并非所有值都可以真正序列化......它们没有意义,例如各个控件上的句柄。
要使表单可序列化,您需要实现 ISerializable 接口,并实现正确的构造函数和 GetObjectData() 方法。在 GetObjectData 中,您需要枚举控件,并存储要复制的属性(例如文本或值)。构造函数将它们读回。它看起来像这样:
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 流中,并在创建新对象时将其拉回。这将允许我用于克隆的原始代码工作。
【讨论】: