繁体   English   中英

是否可以复制某个控件的所有属性? (C# 窗口窗体)

[英]It is possible to copy all the properties of a certain control? (C# window forms)

例如,我有一个带有 Blue BackgroundColor属性等的DataGridView控件。有没有一种方法可以将这些属性以编程方式传输或传递给另一个DataGridView控件?

像这样:

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

谢谢...

你需要使用反射。

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

这是一个粗略的例子:

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

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

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

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

这是我想出的代码。 我只使用 Label、TextBox、Panel 和 DataGridView 控件对其进行了测试。 对于面板控件,您将获得所有包含的控件(克隆实例)。 对于 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);
}

我使用下面的代码来复制选定的属性。

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

基于这篇文章,这里有一个版本

  • 创建正确的控件类型和
  • 递归地这样做

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上,它将不可见。

我用这个:

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

在设计器中设置所有属性后,我想将所有这些配置复制到另一个 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;      

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM