2010-08-13 23 views
8

Ví dụ, tôi có điều khiển DataGridView với thuộc tính Xanh BackgroundColor vv .., có cách nào tôi có thể chuyển hoặc chuyển các thuộc tính này theo chương trình sang điều khiển DataGridView khác không?Có thể sao chép tất cả các thuộc tính của một điều khiển nhất định không? (C# window forms)

Something như thế này:

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

Thanks ...

Trả lời

4

Bạn sẽ cần sử dụng sự phản chiếu.

Bạn lấy tham chiếu đến từng thuộc tính trong điều khiển nguồn (dựa trên loại của nó), sau đó "nhận" giá trị của nó - gán giá trị đó cho điều khiển đích của bạn.

Dưới đây là một ví dụ thô:

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

Lưu ý nhận xét theo câu trả lời của CodeSawyGeek - mã này sao chép một cách mù quáng mọi thuộc tính. Có thể nguy hiểm. –

+1

Hm, bạn kiểm tra phương thức thiết lập nhưng không phải cho phương thức get (mặc dù tôi thừa nhận thuộc tính chỉ ghi là hiếm). Nhưng lưu ý rằng mã của bạn sẽ sao chép các thuộc tính như 'Parent',' Name' và 'Location' có thể không được mong muốn. – Timwi

+0

Sử dụng phản chiếu theo cách này có thể sẽ không cung cấp cho bạn kết quả mong muốn. Một DataGridView là một đối tượng rất phức tạp và bạn có thể không hoàn toàn (hoặc chính xác) sao chép nó bằng cách sao chép một cách mù quáng các giá trị thuộc tính của nó. –

2

Bạn có thể sử dụng phản ánh để có được tất cả các tài sản công cộng của các loại và sao chép các giá trị từ một trường hợp khác, nhưng điều này rất nguy hiểm và có thể không thực sự sao chép toàn bộ trạng thái của đối tượng. Có thể có một số thuộc tính mà bạn không muốn sao chép (ví dụ: Phụ huynh, Trang web) và các thuộc tính quan trọng khác mà bạn không thể đặt trực tiếp (ví dụ: Cột, Hàng). Ngoài ra, có thể có các thuộc tính là các kiểu tham chiếu; điều khiển được sao chép của bạn sẽ kết thúc tham chiếu cùng một đối tượng như đối tượng gốc của bạn, điều này có thể không mong muốn. Cũng có thể có thông tin trạng thái chỉ có thể được đặt thông qua các cuộc gọi phương thức, sẽ không được sao chép theo cách này. Tóm lại, phản ánh có lẽ không phải là giải pháp bạn đang tìm kiếm.

Bạn chỉ cần sao chép thủ công thuộc tính bạn muốn. Ngoài ra, bạn có thể tạo phương thức nhà máy có thể tạo bất kỳ số lượng lưới tương tự nào.

+1

... Tuy nhiên, bạn cần phải cẩn thận bởi vì nếu bạn làm điều đó một cách mù quáng, bạn sẽ kết thúc sao chép các thuộc tính như 'Parent',' Name' và 'Location' mà bạn có thể không muốn. – Timwi

+0

@Timwi: Tôi đã sửa đổi câu trả lời của mình để chỉ ra các mối nguy hiểm khi sử dụng phản chiếu theo cách này. –

+0

+1 Đối với phương pháp nhà máy, mặc dù có thể sẽ có nhiều khả năng được cấu hình điều khiển đã được khởi tạo để không đúng nhà máy, nhưng ý tưởng tương tự và đó là cách tôi muốn đi về nó. – andyhasit

0

Tôi Đã sử dụng mã này clone kiểm soát, bởi vì tôi chỉ muốn sao chép các thuộc tính đã chọn.

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

Đây là mã mà tôi đã đưa ra. Tôi đã chỉ thử nghiệm nó với các điều khiển Label, TextBox, Panel và DataGridView. Đối với một Panel điều khiển, bạn sẽ nhận được tất cả các điều khiển chứa (nhân bản trường hợp). Đối với một điều khiển DataGridView bạn sẽ nhận được các ràng buộc dữ liệu và nó sẽ được chính xác cùng một dữ liệu đó là ràng buộc với nguồn DataGridView kiểm soát. Tất nhiên, nếu không có ràng buộc thì cá thể nhân bản sẽ không có ràng buộc. Cho dù những hành vi này là mong muốn hay không phụ thuộc vào nhu cầu của bạn.

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

'System.ComponentModel.DefaultValueAttribute' và' System.ComponentModel.CategoryAttribute' là 2 mục khác để kiểm tra; nếu họ có mặt, tài sản có nghĩa là để hiển thị trong nhà thiết kế. Nhiều thuộc tính của DGV không có trình duyệt hoặc trình chỉnh sửa có thể duyệt được, nhưng có một hoặc cả hai thuộc tính này, ví dụ: các thuộc tính 'AllowUserTo *'. –

0

Dựa trên this post đây là một phiên bản

  • tạo ra các loại kiểm soát chính xác và
  • làm như vậy một cách đệ quy

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

Bạn vẫn có thể muốn kiểm tra nếu nhiều hơn th e WindowTarget thuộc tính cần được lọc ra ..

vui sang một bên: Nếu điều khiển để clone (trên) một không được chọnTabPage nó sẽ là vô hình ..

0

i sử dụng này:

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

Đám mây bạn giải thích giải pháp của mình một chút. Có vẻ ok nhưng không giải thích thêm câu trả lời có thể bị xóa do chất lượng thấp. Giúp khách truy cập đồng nghiệp hiểu câu trả lời và đưa ra lý do để sử dụng nó. –

Các vấn đề liên quan