2017-08-25 60 views
2

組合框控件接受一個對象作爲其收集成員,是否有辦法限制該對象以實現某個接口?如何覆蓋winforms組合框項目集合以實現特定接口

所以不是

public int Add(object item) 

我想重寫add方法沿東西線以下

public int Add<T>(T item) : where T : ICustomInterface 

我寫的是從ComboBox繼承自己的自定義控制,但我我不太清楚如何讓自定義組合框只處理實現特定界面的項目。

謝謝

回答

1

您可以使用以下技巧來做到這一點。我發現RefreshItems()和構造函數是實現這一點的關鍵地方。

using System; 
using System.Reflection; 

namespace WindowsFormsApplication2 
{ 
    interface ICustomInterface 
    { 
    } 

    public class ArrayList : System.Collections.ArrayList 
    { 
     public override int Add(object value) 
     { 
      if (!(value is ICustomInterface)) 
      { 
       throw new ArgumentException("Only 'ICustomInterface' can be added.", "value"); 
      } 
      return base.Add(value); 
     } 
    } 

    public sealed class MyComboBox : System.Windows.Forms.ComboBox 
    { 
     public MyComboBox() 
     { 
      FieldInfo fieldInfo = typeof(System.Windows.Forms.ComboBox.ObjectCollection).GetField("innerList", BindingFlags.NonPublic | BindingFlags.Instance); 
      fieldInfo.SetValue(this.Items, new ArrayList()); 
     } 

     protected override void RefreshItems() 
     { 
      base.RefreshItems(); 

      FieldInfo fieldInfo = typeof(System.Windows.Forms.ComboBox.ObjectCollection).GetField("innerList", BindingFlags.NonPublic | BindingFlags.Instance); 
      fieldInfo.SetValue(this.Items, new ArrayList()); 
     } 
    } 

} 

也就是說,ComboBox.ObjectCollection包含一個內部列表。我們所要做的就是重寫它。不幸的是,我們必須使用反射,因爲此字段是私人的。這裏是檢查它的代碼。

using System; 
using System.Windows.Forms; 

namespace WindowsFormsApplication2 
{ 
    public partial class Form1 : Form 
    { 
     class MyClass : ICustomInterface 
     { 
     } 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     protected override void OnLoad(EventArgs e) 
     { 
      this.myComboBox1.Items.Add(new MyClass()); 
      this.myComboBox1.Items.Add(new MyClass()); 

      //Uncommenting following lines of code will produce exception. 
      //Because class 'string' does not implement ICustomInterface. 

      //this.myComboBox1.Items.Add("FFFFFF"); 
      //this.myComboBox1.Items.Add("AAAAAA"); 

      base.OnLoad(e); 
     } 
    } 
}