Можно ли скопировать все свойства определенного элемента управления? (Формы окна C# )

например, у меня есть DataGridView управление с синей BackgroundColor свойство etc.., есть ли способ, которым я могу передать или передать программно эти свойства другому DataGridView контроля?

что-то вроде этого:

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

спасибо...

7 ответов


вам нужно будет использовать отражение.

вы берете ссылку на каждое свойство в исходном элементе управления (на основе его типа), а затем "получаете" его значение - присваивая это значение целевому элементу управления.

вот грубый пример:

    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), и другие важные свойства, которые вы не можете установить напрямую (например, столбцы, строки). Кроме того, могут быть свойства, являющиеся ссылочными типами; скопированный элемент управления будет ссылаться на тот же объект, что и твой оригинал, что может быть нежелательно. Также может быть информация о состоянии, которая может быть установлена только через вызовы методов, которые не будут скопированы таким образом. Короче говоря, отражение, вероятно, не является решением, которое вы ищете.

возможно, Вам просто придется вручную скопировать нужные свойства. Кроме того, можно создать заводской метод, который может создавать любое количество аналогичных сеток.


Я опубликовал демо-проект на codeproject о том, как копировать и вставлять или клонировать contorl несколько лет назад, http://www.codeproject.com/Articles/12976/How-to-Clone-Serialize-Copy-Paste-a-Windows-Forms


вот код, который я придумал. Я тестировал его только с элементами управления 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 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 свойство должно быть отфильтровано..

смешно в сторону: если элемент управления для клонирования (on)невыбранные TabPage он будет невидим..


я использовал этот:

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

я использовал ниже код для копирования выбранных свойств.

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