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

发布于 2024-10-01 05:28:03 字数 213 浏览 0 评论 0原文

我正在使用 winforms 和 Visual Studio 2008。

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

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

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

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

i am using winforms with visual studio 2008.

i would to create an EXACT replica of my form with controls and all events, and all the same code as i have.

is this possible to do at runtime? how would i do it?

shouldnt there be some kind of class solution like:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

皇甫轩 2024-10-08 05:28:03

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

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

Just create another instance of the same class. Use the actual name of the class instead of the base class Form.

Form form2 = new Form1();
form2.Show();
三岁铭 2024-10-08 05:28:03

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

有些事情需要注意...您想要浅拷贝还是深拷贝?即,如果表单具有对对象的引用,您是否要复制该引用(因此两个表单都指向同一个对象),或者也复制该对象?您必须小心...无法保证包含对其他对象的引用的对象将被反序列化的顺序

您不需要这样做,但最好从 ICloneable 继承,它只有一个方法 克隆()。使用类似于以下的代码覆盖此方法:

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!
}

* 编辑 *
实际上这里有一个很好的例子,它创建了一个通用的对象复制器。非常好!
深度克隆对象

* 编辑 *
序列化表单的问题在于,并非所有值都可以真正序列化......它们没有意义,例如各个控件上的句柄。

要使表单可序列化,您需要实现 ISerialized 接口,并实现正确的构造函数和 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 流中,并在创建新对象时将其拉出。这将使我的原始克隆代码能够工作。

Shooting from the hip, serialize the form and deserialize it into the second variable. : ) I'll try to look into this and come up with more of an answer.

Some things to watch out for... do you want a shallow or deep copy? I.E., if the form has a reference to an object, do you want to copy the reference (so both forms are pointing to the same object), or make a copy of that object, also? You have to be careful... there's no guarantee with objects that contain references to other objects which order they will be deserialized

You don't need to, but it's good practice to inherit from ICloneable, which has only one method, Clone(). Override this method with code similar to the following:

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);

}

To use:

MyForm form2 = form1.Clone() as MyForm;
if (form2 != null) {
    // yahoo!
}

* Edit *
There's actually an excellent example here on SO that creates a generic object copier. Very nice!
Deep cloning objects

* Edit *
The problem with serializing the form is that not all the values can really be serialized... they make no sense, e.g. the handles on the individual controls.

To make the form serializable, you will need to implement the ISerializable interface, and implement the proper constructor and GetObjectData() method. In GetObjectData, you will need to enumerate your controls, and store the properties (e.g. Text or Value) that you want to copy. The constructor reads them back out. It looks like this:

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);
        }

    }

}

The idea is, enumerate the form, put every value into SerializationInfo stream, and pull it back out when you create a new object. This will allow my original code for Cloning to work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文