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

Ire*_*311 1 c# serialization clone deep-copy winforms

如何克隆或序列化 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;
}
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

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

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

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

请任何人......

nev*_*ets 5

就像@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");
}
Run Code Online (Sandbox Code Playgroud)