c# - 即使具有不可序列化的属性,如何克隆 Windows 窗体控件?

标签 c# winforms serialization clone deep-copy

如何克隆或序列化 Windows 窗体控件?
当我尝试使用此代码“CloneControl(Control ct1)”克隆 Windows 窗体控件时,它允许我复制具有某些可序列化属性的控件,而不是所有属性。

public Form1()
{
    InitializeComponent();
        Columns = new DataGridViewTextBoxColumn[2];
        for (int i = 0; i < 2; i++)
        {
            Columns[i] = new System.Windows.Forms.DataGridViewTextBoxColumn();
            // 
            // Columns[i]
            // 
            Columns[i].HeaderText = "j" + (i + 1);
            Columns[i].Name = "Column" + (i + 1);
            Columns[i].Width = 50;
        }
        dataGridView1 = new System.Windows.Forms.DataGridView();
        dataGridView1.Name = "dataGridView1";
        dataGridView1.Location = new System.Drawing.Point(100, 100);
        dataGridView1.RowHeadersWidth = 50;
        dataGridView1.RowTemplate.Height = 25;
        dataGridView1.Size = new System.Drawing.Size(55 + 50 * 2, 25 + dataGridView1.RowTemplate.Height * 2);
        dataGridView1.Anchor = System.Windows.Forms.AnchorStyles.None;
        dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
        dataGridView1.Columns.AddRange(Columns);
        dataGridView1.TabIndex = 3;
        dataGridView1.AllowUserToAddRows = false;
        dataGridView1.Rows.Add();
        dataGridView1.Rows.Add();
        dataGridView1.Rows[0].HeaderCell.Value = "i" + 1;
        dataGridView1.Rows[1].HeaderCell.Value = "i" + 2;
        dataGridView1.Rows[0].Cells[0].Value = "value1";
        Controls.Add(dataGridView1);

        Control cloned1 = CloneControl(dataGridView1); 
        cloned1.SetBounds(cloned1.Location.X, cloned1.Location.Y + 300, cloned1.Width, ct1.Height);
        Controls.Add(cloned1);
        cloned1.Show();
}    

public Control CloneControl(Control ct1)
{
    Hashtable PropertyList = new Hashtable();
    PropertyDescriptorCollection Properties = TypeDescriptor.GetProperties(ct1);
    Assembly controlAsm = Assembly.LoadWithPartialName(ct1.GetType().Namespace);
    Type controlType = controlAsm.GetType(ct1.GetType().Namespace + "." + ct1.GetType().Name);
    Control cloned1 = (Control)Activator.CreateInstance(controlType);
    foreach (PropertyDescriptor pr1 in Properties)
    {
        if (pr1.PropertyType.IsSerializable)
        {
            PropertyList.Add(pr1.Name, pr1.GetValue(ct1));
        }
        if (PropertyList.Contains(pr1.Name))
        {
            try
            {
                 Object obj = PropertyList[pr1.Name];
                 pr1.SetValue(cloned1, obj);
            }
            catch (Exception ex)
            {

            }
        }
    }
    return ct2;
}

如果你运行代码...你会得到

enter image description here

正如您在 main 方法中看到的,我创建了一个 dataGridView1 的克隆,它具有一些属性。
实际上,在克隆的 dataGridView 中,每个单元格值都是 null。 列的大小也不会被克隆!

你可能会有疑问:如果用C#编写的Visual Studio或者SharpDeveloper作为IDE能够解决这个问题,那么写出这样的代码或许是可以的!对吧?
在 Visual Studio 中,当您尝试拖放控件或复制粘贴控件时,它不仅会复制具有所有属性(包括可序列化或不可序列化)的控件,还会将控件本身的名称从“dataGridView1”更改为“dataGridView2”以及在 SharpDeveloper 中!

我该怎么办?
我应该创建什么样的方法?
也许另一个控件有很多不可序列化的属性!
如何复制所有这些?

请任何人......

最佳答案

就像@Hans 在评论中提到的,Clone 并不是那么容易。如果你想得到一些相同的控件,只有一点点不同,你最好使用一个函数来定义一般行为将不同的属性作为参数传递。例如,我们定义了一个具有一些适用于 DataGridView 的通用属性的函数:

private void InitDataGridView(DataGridView dataGridView, string name)
{
    dataGridView.Name = name;

    // configure other properties here
    dataGridView.Location = new System.Drawing.Point(100, 100);
    dataGridView.RowHeadersWidth = 50;
    dataGridView.RowTemplate.Height = 25;
    dataGridView.Size = new System.Drawing.Size(55 + 50 * 2, 25 + dataGridView1.RowTemplate.Height * 2);
    dataGridView.Anchor = System.Windows.Forms.AnchorStyles.None;
    dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
    // remember to initialize your columns, or pass it in as a parameter
    dataGridView.Columns.AddRange(Columns);
    dataGridView.AllowUserToAddRows = false;
    dataGridView.Rows.Add();
    dataGridView.Rows.Add();
    dataGridView.Rows[0].HeaderCell.Value = "i" + 1;
    dataGridView.Rows[1].HeaderCell.Value = "i" + 2;
    dataGridView.Rows[0].Cells[0].Value = "value1";
}

public Form1()
{
    InitializeComponent();

    var dataGridView1 = new DataGridView();
    var dataGridView2 = new DataGridView();

    InitDataGridView(dataGridView1, "dataGridView1");
    InitDataGridView(dataGridView2, "dataGridView2");
}

关于c# - 即使具有不可序列化的属性,如何克隆 Windows 窗体控件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25227969/

相关文章:

c# - c# Forms 应用程序中的 Google 地球 map

wcf - 基于 WCF 中的接口(interface)序列化数组的最佳方法是什么?

c# - 如何检查QueryContainer是否具有特定属性?

c# - 我可以使用 System.Reflection.Emit 为现有类型构建构造函数吗?

c# - ASP.NET MVC 5保存当前ApplicationUser

c# - 一次将datagridview的所有数据插入数据库

c# - Datagridview 列限制

c# - 可以将属性添加到我的类的 JSON 版本,而类中不存在它吗?

django-rest-framework - ForeignKey 不允许空值

c# - 使用其 setter 捕获属性更改