Make ComboBox for a specific type only

I currently have a ComboBox in my Windows Forms Application. To specify what values ​​the ComboBox will contain, I set the DataSource property for the ComboBox to some array so that the ComboBox contains values ​​from that array. I could also use Items.Add()

to add new values ​​to the ComboBox. However, I want to make sure the ComboBox can be populated with objects of a specific type. So, if I have a class called X, then I want to make it so that only an array of type X can be used as a data source for the ComboBox. Now ComboBox accepts objects of the typeSystem.Object

... How can I achieve this? Is there a ComboBox property that I need to set equal to the name of my data type? Or is there an event that will check if the object added to my ComboBox is of the required type and will there be an exception if not?

I was thinking about creating a new class as a subtype of ComboBox and overriding the Add

property method Items

so that Add will check if its argument is of the correct type (not sure what or how I can do this). Even if I do, there are still other ways to add new values ​​to the ComboBox ( AddRange

, CopyTo

etc.), so I think there should be a more elegant solution to this problem.

+3


source to share


3 answers


You can hide a property Items

in your site with your own Items

custom property that takes as parameter original ItemsCollection

Example class for testing

public class Order
{
    public Int32 ID { get; set; }
    public string Reference { get; set; }

    public Order() { }
    public Order(Int32 inID, string inReference)
    {
        this.ID = inID;
        this.Reference = (inReference == null) ? string.Empty : inReference;
    }

    //Very important 
    //Because ComboBox using .ToString method for showing Items in the list
    public override string ToString()
    {
        return this.Reference;
    }

}

      

In the following class, I tried to wrap a collection of ComboBox items in my own type. If adding items should be of a specific type Here you can add other methods / properties that you need (Remove)

public class ComboBoxList<TCustomType>
{
    private System.Windows.Forms.ComboBox.ObjectCollection _baseList;

    public ComboBoxList(System.Windows.Forms.ComboBox.ObjectCollection baseItems)
    {
        _baseList = baseItems;
    }

    public TCustomType this[Int32 index]
    {
        get { return (TCustomType)_baseList[index]; }
        set { _baseList[index] = value; }
    }

    public void Add(TCustomType item)
    {
        _baseList.Add(item);
    }

    public Int32 Count { get { return _baseList.Count; } }

}

      



Here's a custom combobox class derived from ComboBox Added: generic type

public class ComboBoxCustomType<TCustomType> : System.Windows.Forms.ComboBox
{
    //Hide base.Items property by our wrapping class
    public new ComboBoxList<TCustomType> Items; 

    public ComboBoxCustomType() : base()
    {
        this.Items = new ComboBoxList<TCustomType>(base.Items);
    }

    public new TCustomType SelectedItem 
    { 
        get { return (TCustomType)base.SelectedItem; } 
    }
}

      

The following code used in the form

private ComboBoxCustomType<Order> _cmbCustom;

//this method used in constructor of the Form
private void ComboBoxCustomType_Initialize()
{
    _cmbCustom = new ComboBoxCustomType<Order>();
    _cmbCustom.Location = new Point(100, 20);
    _cmbCustom.Visible = true;
    _cmbCustom.DropDownStyle = ComboBoxStyle.DropDownList;
    _cmbCustom.Items.Add(new Order(0, " - nothing - "));
    _cmbCustom.Items.Add(new Order(1, "One"));
    _cmbCustom.Items.Add(new Order(2, "Three"));
    _cmbCustom.Items.Add(new Order(3, "Four"));
    _cmbCustom.SelectedIndex = 0;
    this.Controls.Add(_cmbCustom);
}

      

+1


source


If you want to control the type of an element that it can contain ComboBox

, you can try to create a new derived from the class ComboBox

, but you are faced with the problem that it still has a property ComboBox.ObjectCollection Items

that will take any type anyway! And (unfortunately for your overriding idea) the method is Add

not virtual.

The only practical solution I could think of was to distract somehow ComboBox

. If this is not generic code, I would recommend just creating a method that you would use to add items to ComboBox

. Something like:

// NOTE: All items that are added to comboBox1 need to be of type `SomeType`.
private void AddItemToComboBox(SomeType item)
{
    comboBox1.Items.Add(item);
}

      



Any attempt to add an object SomeType

to ComboBox

will fail with a compiler error. Unfortunately, there is no easy way to prevent the element from being added SomeType

to ComboBox.Items

directly.

Again, if this is not generic code, this shouldn't be a problem.

+2


source


Instead of overriding the ComboBox (which doesn't work as stated in itsme86 answer ), you can override the usercontrol, add a combobox to it, and then expose only the items you wish to work with. Something similar to

public partial class MyComboBox<T> : UserControl where T: class
{
    public MyComboBox()
    {
        InitializeComponent();
    }

    public void Add(T item)
    {
        comboBox1.Items.Add(item);
    }

    public IEnumerable<T> Items
    {
        get { return comboBox1.Items.Cast<T>(); }
    }
}

      

Note that some parts of automated software rely on access to basic controls, so this can cause some problems.

This approach never changes the Items

dropdown, so they will be kept like objects

, but when you access them, you cast them back to the type you want and only let them add that type. You can create a new combo box via

 var myCB = new MyComboBox<ItemClass>();

      

0


source







All Articles