Можно ли скопировать все свойства определенного элемента управления? (C # оконные формы) - PullRequest
8 голосов
/ 13 августа 2010

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

Примерно так:

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

Спасибо ...

Ответы [ 7 ]

5 голосов
/ 13 августа 2010

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

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

Вот пример:

    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);
            }
        }
    }
3 голосов
/ 13 августа 2010

Вы можете использовать рефлексию, чтобы получить все открытые свойства типа и скопировать значения из одного экземпляра в другой, но это опасно и может не полностью дублировать все состояние объекта.Могут быть некоторые свойства, которые вы не хотите копировать (например, Parent, Site), и другие важные свойства, которые вы не можете установить напрямую (например, Columns, Rows).Кроме того, могут быть свойства, которые являются ссылочными типами;ваш скопированный элемент управления в конечном итоге будет ссылаться на тот же объект, что и ваш оригинал, что может быть нежелательно.Также может быть информация о состоянии, которая может быть установлена ​​только через вызовы методов, которые не будут скопированы таким образом.Короче говоря, возможно, отражение - это не то решение, которое вам нужно.

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

2 голосов
/ 18 октября 2013

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

1 голос
/ 18 января 2017

Вот код, который я придумал.Я тестировал его только с помощью элементов управления 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);
}
0 голосов
/ 24 октября 2017

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

 Control NewControl=new Control(ControlToClone,ControlToClone.Name);
0 голосов
/ 31 мая 2017

На основании этого поста вот версия, в которой

  • создает правильные типы элементов управления, а
  • делает это рекурсивно

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 будет невидимым ..

0 голосов
/ 27 декабря 2016

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

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));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...