可以复制某个控件的所有属性? (C#窗体)
例如,我有一个DataGridView
控件与蓝色BackgroundColor
属性等..是否有一种方法,我可以传递或编程传递这些属性到另一个DataGridView
控件?
像这样的东西:
dtGrid2.Property = dtGrid1.Property; // but of course, this code is not working
谢谢…
你需要使用reflection。
您可以获取源控件中每个属性的引用(根据其types),然后“获取”其值 – 将该值分配给目标控件。
这是一个简单的例子:
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); } } }
您可以使用reflection来获取该types的所有公共属性,并将值从一个实例复制到另一个实例,但这是危险的,可能不会真正复制对象的整个状态。 可能有一些你不想复制的属性(例如,Parent,Site)以及其他不能直接设置的重要属性(如Columns,Rows)。 而且,可能有属性是引用types; 您复制的控件将最终引用与原始对象相同的对象,这可能是不可取的。 也可能有只能通过方法调用设置的状态信息,这些信息不会被这样复制。 总之,反思可能不是你正在寻找的解决scheme。
您可能只需手动复制所需的属性。 或者,您可以创build一个工厂方法,可以创build任意数量的类似网格。
我在codeproject上发布了一个关于如何在几年前复制粘贴或克隆控件的演示项目, http://www.codeproject.com/Articles/12976/How-to-Clone-Serialize-Copy-Paste-a-Windows-forms
我用这个代码来克隆控制,因为我想复制只有选定的属性。
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)); } }
这是我想出来的代码。 我只用Label,TextBox,Panel和DataGridView控件testing过它。 对于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); }
基于这个职位这里是一个版本
- 创build正确的控件types和
- 这样做是recursion的
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; } }
你仍然可能想testing是否应该过滤掉WindowTarget
属性。
有趣的是:如果要克隆的控件是( 未选定的 TabPage
,它将不可见。
我用这个:
Control NewControl=new Control(ControlToClone,ControlToClone.Name);