c#我如何以编程方式创建表单的副本?

时间:2010-11-05 22:13:08

标签: c# .net winforms .net-3.5

我在visual studio 2008中使用winforms。

我想创建一个包含控件和所有事件的表单的EXACT副本,以及与我相同的所有代码。

这可以在运行时做吗?我该怎么做?

不应该有某种类解决方案,如:

Form form2 = new Form();
form2 = form1 ???

2 个答案:

答案 0 :(得分:5)

只需创建同一个类的另一个实例。使用类的实际名称而不是基类Form

Form form2 = new Form1();
form2.Show();

答案 1 :(得分:1)

从臀部拍摄,序列化表格并将其反序列化为第二个变量。 :)我会尝试研究这个问题并提出更多答案。

要注意的一些事项......你想要一个浅或深的副本吗? I.E.,如果表单有一个对象的引用,你想复制引用(所以两个表单都指向同一个对象),还是制作该对象的副本?你必须要小心......对于包含对其他对象的引用的对象,不能保证它们将被反序列化

您不需要,但从IClo​​neable继承是一种好习惯,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流中,并在创建新对象时将其拉出。这将允许我的克隆原始代码工作。