【问题标题】:c# how do i programmatically create a replica of my form?c# 如何以编程方式创建表单的副本?
【发布时间】:2011-05-05 20:43:43
【问题描述】:

我在 Visual Studio 2008 中使用 winforms。

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

    • @guffa 我认为如何在该表单上运行方法?比如我想在新的form2上触发click事件,我该怎么做呢?
    • 新的 form2 自己会处理自己的点击事件。如果您想从 form2 外部触发新 form2 上的方法,请将方法设为公共(或内部等)并通过调用 form2.YourMethodName() 来触发它。
    • @jay 你能举个例子吗
    • @jay 我如何填写 form2 上的文本框?
    • 如果您想在 form2 之外执行此操作,您可以将 TextBox 的 Modifiers 属性更改为 public,然后通过调用 form2.YourTextBox.Text = "my text"; 来设置您的 TextBox 文本;跨度>
    【解决方案2】:

    从臀部开始,序列化表单并将其反序列化为第二个变量。 :) 我会尝试对此进行调查并提出更多答案。

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

    您不需要,但最好从 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 流中,并在创建新对象时将其拉回。这将允许我用于克隆的原始代码工作。

    【讨论】:

    • @james 谢谢,但我需要从基本表单运行方法,我该怎么做
    • 实际上,我必须收回我的答案并重新考虑......你不能将表单标记为可序列化,所以我的方法不起作用:(
    • 好的,添加了有关如何序列化表单的信息。我不确定您所说的“需要从基本表单运行方法”是什么意思?
    • 为什么要经历这些麻烦?
    • 因为如果您想要一个表单的副本,这意味着您想要一个所有控件、它们的值等的副本。以及您为表单提供的任何成员级变量。制作这些副本的唯一方法是在 Clone() 或 Copy() 方法中从表单中枚举它们。从类内部进行序列化意味着您不必将每个控件公开为公共属性,如果您想从外部进行复制,则必须这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2013-11-04
    • 2015-12-05
    • 2010-11-25
    相关资源
    最近更新 更多