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

c#如何以编程方式创建表单的副本?,c#,.net,winforms,.net-3.5,C#,.net,Winforms,.net 3.5,我正在visual studio 2008中使用winforms 我想创建一个与我的表单完全相同的副本,包括控件和所有事件,以及所有与我相同的代码 这可以在运行时执行吗?我该怎么做 难道不应该有一些类解决方案,如: Form form2 = new Form(); form2 = form1 ??? 只需创建同一类的另一个实例。使用类的实际名称,而不是基类表单 Form form2 = new Form1(); form2.Show(); 从头开始,序列化表单并将其反序列化到第二个变量中。:

我正在visual studio 2008中使用winforms

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

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

难道不应该有一些类解决方案,如:

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

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

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!
}
*编辑*
这里有一个很好的例子,可以创建一个通用的对象复制器。非常好


*编辑*
序列化表单的问题是并非所有的值都可以真正序列化。。。它们毫无意义,例如单个控件上的手柄

要使表单可序列化,需要实现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流,并在创建新对象时将其取出。这将允许我的原始克隆代码工作。

@guffa我认为如何在该表单上运行方法?例如,如果我想在新表单2上触发点击事件,我将如何做?新表单2本身将处理自己的点击事件。如果您想从form2 itseld外部启动新form2上的方法,请将该方法公开(或内部等),然后通过调用form2.YourMethodName()来启动它。@jay您能给我举个例子吗please@jay我如何在form2上填写文本框?如果你想在form2之外填写,您可以将文本框的Modifiers属性更改为public,然后通过调用form2.YourTextBox.text=“我的文本”来设置文本框文本@james谢谢你,但我需要从基本表单运行方法,我该怎么做呢?实际上,我必须收回我的答案并重新思考。。。您不能将表单标记为可序列化,因此我的方法不起作用:(好的,添加了关于如何序列化表单的信息。我不确定你所说的“需要从基表单运行方法”是什么意思?为什么要经历这些麻烦?因为如果你想要一个表单的副本,这意味着你想要一个所有控件、它们的值等的副本,以及你给表单的任何成员级变量的副本。唯一的方法是复制其中的一个是从Clone()或Copy()方法的表单中枚举它们。从类中序列化意味着您不必将每个控件作为公共属性公开,如果您想从外部创建副本,则必须这样做。