2017-08-25 13 views
2

コンボボックスコントロールはオブジェクトをコレクションメンバーとして受け取ります。特定のインターフェイスを実装するためにそのオブジェクトを制約する方法はありますか?特定のインターフェイスを実装するためにwinformsコンボボックスアイテムコレクションをオーバーライドする方法

ので、代わりに

public int Add(object item) 

の私は、コンボボックスから継承独自のカスタムコントロールを書いています

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

の下に線に沿って何かにaddメソッドをオーバーライドしたいが、私なりカスタムコンボボックスを特定のインターフェイスを実装するアイテムのみを扱うようにすることがどのように最善の方法であるのかよく分かりません。

ありがとうございました

答えて

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); 
     } 
    } 
} 
関連する問題