Reputation: 21
The combobox control accepts an object as its collection member, is there a way to constrain that object to implement a certain interface?
so instead of
public int Add(object item)
I would like to override the add method to something along the lines below
public int Add<T>(T item) : where T : ICustomInterface
I am writing my own custom control that inherits from the combobox, but I'm not quite sure how best to go about getting the custom combobox to only deal with items that implement a specific interface.
Thank you
Upvotes: 2
Views: 1065
Reputation: 3018
You can use following trick to do that. I found out that RefreshItems()
and the constructor are key places to achieve that.
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());
}
}
}
That is, ComboBox.ObjectCollection contains an inner list. All we have to do is to override it. Unfortunately we have to use reflection as this field is private. Here is code to check it.
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);
}
}
}
Upvotes: 1