Introduction
In .NET, if you set ComboBox.DataSource = ComboBox.Items
and then later try to add a new item, .NET will throw an exception. The only way to add a new item to this simple binding (without implementing a more complex data source) is to remove the binding, recreate the Items
collection, and rebind.
Additionally, if you simply do ComboBox.DataSource = null
to clear the binding, the items in ComboBox.Items
are cleared. Thus, you either recreate every item or copy the ComboBox.Items
to a new array, unbind the data source, re-insert the original items, add the new item, and rebind the data source.
To get around this problem, in .NET, you can write Extensions that will add functions to existing classes, without having to fully extend the original class and then implement the extended class in various places in your projects.
This tip shows how to add a function called 'AddItem
' to the base ComboBox
class which will automate all of this, and make it so you don't have to go through your code and place all instances of ComboBox
controls with a new extended version. Additionally, a simple sort functionality has been included as part of the extension method.
Using the Code
The example project included can be compiled to create a DLL that can be referenced in your projects, or you can simply copy the code into your existing projects. Source code for both C# and VB are included (and a simple test project). Along with two separate ways to handle doing the simple sorting.
Sorting methods:
- Extended Combo Box - Extensions currently don't natively support properties, so you can't add properties to an existing class without extending the actual class. This project extends the
ComboBox
and adds a SortedDS
Boolean property. An alternative to this would be to store a Boolean in the ComboBox.Tag
, but this breaks if something else is stored in the Tag
property. One advantage of this route over the alternative #2 is that the SortedDS
property will show up in the Visual Studio Designer (in the Properties docker). - Extended Property - Thanks to a very informative article by Oleg Shilo titled "Extension Properties" Revised (http://www.codeproject.com/Articles/399932/Extension-Properties-Revised) this project adds a
GetSortedDS
and SetSortedDS
method to all ComboBox
es automatically. The pro is that all your combo box controls will automatically have this property. The con is that it doesn't show up in the Designer.
This article only covers AddItem
with sorting method #1 above. Download the example project to see method #2. The AddItem
code can be easily copied and modified to provide additional useful functions such as AddItemRange
, EditItem
, InsertItem
, and RemoveItem
.
Step 1
Add a static
class (or Module in VB) to your project named ComboBoxAddItem
.
Copy and paste the following code:
public int AddItem(this System.Windows.Forms.ComboBox cbo, object item)
{
if (cbo.DataSource == null)
{
return cbo.Items.Add(item);
}
else if (cbo.DataSource is System.Windows.Forms.ComboBox.ObjectCollection)
{
object[] items = new object[cbo.Items.Count + 1];
string dm, vm;
object selectedItem = cbo.SelectedItem;
bool enabled = cbo.Enabled;
dm = cbo.DisplayMember;
vm = cbo.ValueMember;
cbo.Enabled = false;
cbo.BeginUpdate();
cbo.Items.CopyTo(items, 0);
items[items.Length - 1] = item;
cbo.DataSource = null;
cbo.Items.AddRange(items);
cbo.DisplayMember = dm;
cbo.ValueMember = vm;
if (cbo is SortedDSComboBox && ((SortedDSComboBox)cbo).SortedDS)
{
cbo.Sorted = true;
cbo.Sorted = false;
cbo.DataSource = cbo.Items;
cbo.SelectedItem = selectedItem;
cbo.EndUpdate();
cbo.Enabled = enabled;
return cbo.Items.IndexOf(item);
}
else
{
cbo.SelectedItem = selectedItem;
cbo.EndUpdate();
cbo.Enabled = enabled;
return cbo.Items.Count - 1;
}
}
else
{
throw new InvalidOperationException("DataSource is not null or cbo.Items - " +
"any other data source needs to be handled explicitly.");
}
}
The gist of it is:
- If the data source is
null
, just the item - nothing extra needed. - If the data source is the
cbo.Items
, then:
- Copy certain necessary properties from the combo box.
- Copy the items into a new array that is 1 size larger than the current number of items.
- Add the new item to the end of the array.
- Resort the array if need be.
- Reset the copied properties and data source.
- Throw an error if the data source is not the simple
cbo.Items
.
Step 2
Add a SortedDSComboBox
that extends the System.Windows.Forms.ComboBox
to your project, and paste in the following code:
public class SortedDSComboBox : System.Windows.Forms.ComboBox
{
private bool _sortedDS = false;
[DefaultValue(false)]
[Category("Behavior")]
[Description("Indicates whether the data source is sorted or not. " +
"Used in conjunction with AddItem extension.")]
public bool SortedDS { get { return _sortedDS; } set { _sortedDS = value; } }
}
Step 3
If you need or want the extra functionality such as AddRange
or InsertItem
, copy the AddItem
method above, rename it to the appropriate method name, and make any minor modifications you need to have it perform that particular function.
For more information on how to do the Extended
property, download the example project and read over the article by Oleg Shilo titled "Extension Properties" Revised (http://www.codeproject.com/Articles/399932/Extension-Properties-Revised).
History
- 20th November 2015: Initial version