可以复制某个控件的所有属性吗? (C#窗口形式)

时间:2010-08-13 03:01:23

标签: c# winforms

例如,我有DataGridView控件,其中包含蓝色BackgroundColor属性等等。有没有一种方法可以将这些属性以编程方式传输或传递给另一个DataGridView控件?

这样的事情:

dtGrid2.Property = dtGrid1.Property; // but of course, this code is not working

...谢谢

8 个答案:

答案 0 :(得分:5)

你需要使用反射。

您获取源控件中每个属性的引用(基于其类型),然后“获取”其值 - 将该值分配给目标控件。

这是一个粗略的例子:

    private void copyControl(Control sourceControl, Control targetControl)
    {
        // make sure these are the same
        if (sourceControl.GetType() != targetControl.GetType())
        {
            throw new Exception("Incorrect control types");
        }

        foreach (PropertyInfo sourceProperty in sourceControl.GetType().GetProperties())
        {
            object newValue = sourceProperty.GetValue(sourceControl, null);

            MethodInfo mi = sourceProperty.GetSetMethod(true);
            if (mi != null)
            {
                sourceProperty.SetValue(targetControl, newValue, null);
            }
        }
    }

答案 1 :(得分:3)

您可以使用反射来获取该类型的所有公共属性,并将值从一个实例复制到另一个实例,但这很危险,并且可能无法真正复制对象的整个状态。可能有一些您不想复制的属性(例如Parent,Site)以及您无法直接设置的其他重要属性(例如Columns,Rows)。此外,可能存在引用类型的属性;您复制的控件最终将引用与原始对象相同的对象,这可能是不合需要的。还可能存在只能通过方法调用设置的状态信息,这些信息不会以这种方式复制。简而言之,反思可能不是您正在寻找的解决方案。

您可能只需手动复制所需的属性即可。或者,您可以创建一个可以创建任意数量的类似网格的工厂方法。

答案 2 :(得分:2)

我在codeproject上发布了一个关于如何在几年前复制和粘贴或克隆控件的演示项目, http://www.codeproject.com/Articles/12976/How-to-Clone-Serialize-Copy-Paste-a-Windows-Forms

答案 3 :(得分:1)

这是我提出的代码。我只使用Label,TextBox,Panel和DataGridView控件进行了测试。对于Panel控件,您将获得所有包含的控件(克隆实例)。对于DataGridView控件,您将获得数据绑定,它将与绑定到源DataGridView控件的完全相同的数据。当然,如果没有绑定,那么克隆的实例将没有绑定。这些行为是否合适取决于您的需求。

private Control CloneControl(Control srcCtl)
{
    var cloned = Activator.CreateInstance(srcCtl.GetType()) as Control;
    var binding = BindingFlags.Public | BindingFlags.Instance;
    foreach(PropertyInfo prop in srcCtl.GetType().GetProperties(binding))
    {
        if (IsClonable(prop))
        {
            object val = prop.GetValue(srcCtl);
            prop.SetValue(cloned, val, null);
        }
    }

    foreach(Control ctl in srcCtl.Controls)
    {
        cloned.Controls.Add(CloneControl(ctl));
    }

    return cloned;
}

private bool IsClonable(PropertyInfo prop)
{
    var browsableAttr = prop.GetCustomAttribute(typeof(BrowsableAttribute), true) as BrowsableAttribute;
    var editorBrowsableAttr = prop.GetCustomAttribute(typeof(EditorBrowsableAttribute), true) as EditorBrowsableAttribute;

    return prop.CanWrite
        && (browsableAttr == null || browsableAttr.Browsable == true)
        && (editorBrowsableAttr == null || editorBrowsableAttr.State != EditorBrowsableState.Advanced);
}

答案 4 :(得分:0)

我在下面的代码中使用了复制选定的属性。

public static void CloneControl(Control SourceControl, Control DestinationControl)
{
    String[] PropertiesToClone = new String[] { "Size", "Font", "Text", "Tag", "BackColor", "BorderStyle", "TextAlign", "Width", "Margin" };
    PropertyInfo[] controlProperties = SourceControl.GetType().GetProperties();

    foreach (String Property in PropertiesToClone)
    {
        PropertyInfo ObjPropertyInfo = controlProperties.First(a => a.Name == Property);
        ObjPropertyInfo.SetValue(DestinationControl, ObjPropertyInfo.GetValue(SourceControl));
    }
}

答案 5 :(得分:0)

基于this post这是

的版本
  • 创建正确的控件类型和
  • 以递归方式执行
public static class ControlExtensions
{
    public static T Clone<T>(this T controlToClone)  where T : Control
    {
        PropertyInfo[] controlProperties = 
          typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        //T instance = Activator.CreateInstance<T>();
        Control instance = (Control) Activator.CreateInstance(controlToClone.GetType());

        foreach (PropertyInfo propInfo in controlProperties)
        {
            if (propInfo.CanWrite)
            {
                if (propInfo.Name != "WindowTarget")
                    propInfo.SetValue(instance,
                                      propInfo.GetValue(controlToClone, null), null);
            }
        }

        foreach(Control ctl in controlToClone.Controls)
        {
            instance.Controls.Add( ctl.Clone() );
        }
        return (T) instance;
    }
}

您仍然可能想要测试是否应过滤掉WindowTarget以上的属性..

有趣的是:如果要克隆的控件是 未选中 TabPage,它将是不可见的..

答案 6 :(得分:0)

我用过这个:

 Control NewControl=new Control(ControlToClone,ControlToClone.Name);

答案 7 :(得分:0)

在Designer中设置了所有属性之后,我想要将所有这些配置复制到另一个DataGridView中,并且遇到了相同的问题。 我通过检查InitializeComponent()解决了它;表格的一部分。 可以轻松找到我设置的所有属性,然后通过代码将其再次设置到另一个DataGridView控件。

例如,我设置了:

DataGridViewCellStyle dgvCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
dgvCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dgvCellStyle1.BackColor = System.Drawing.SystemColors.Window;
dgvCellStyle1.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
dgvCellStyle1.ForeColor = System.Drawing.SystemColors.ControlText;
dgvCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dgvCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dgvCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
dgv.DefaultCellStyle = dgvCellStyle1;
dgv.GridColor = System.Drawing.SystemColors.ControlLight;
dgv.Location = new System.Drawing.Point(258, 315);                    
dgv.ReadOnly = true;
dgv.RowHeadersVisible = false;
dgv.RowTemplate.Height = 18;
dgv.ShowEditingIcon = false;