Recently asked on Yahoo! Answers:
ComboBox Question in Visual Basic?
I am trying to create a combobox dropdown list of countries. When user click on a country, it should add to the listbox. I manage to do it. But I want to enhance some form of checking. If the country is already added in the listbox, the user should not be able to select the same country again. These are my codes, but it won’t work. I don’t know what’s wrong. Can someone please help? Thanks!
For Each country As String In lstCountry.Items
If country Is cbxCountries.SelectedItem Then
MsgBox(“County already selected.”, MsgBoxStyle.Information, )
Thanks to .NET’s totally object-oriented approach to programming — especially its modularity, encapsulation and polymorphism — moving the selected value of a ComboBox (in ASP.NET, a DropDownList) control to a ListBox control takes three lines of code. And removing that same item from the ComboBox takes just one more line.
Because I want to demo this, I’ll be writing this in ASP.NET. However, it will translate just fine to Windows Forms, as well; the questioner doesn’t state which he’s using, but my guess is it’s Windows Forms, since he’s using a ComboBox control.
The Power Of Object-Oriented Code
Some quick notes before we start with the coding.
Most of what I am about to do will translate fine to Windows Forms. However, ASP.NET and Windows Forms aren’t the same thing. Most important, the ComboBox and ListItem controls in Windows Forms can basically use any object as their options; but in ASP.NET, both a DropDownList and a ListBox use the ListItem class.
That might seem like a huge problem for demonstration purposes, but thanks to encapsulation and polymorphism, it doesn’t really matter.
In the case of Windows Forms, options in a ComboBox or ListBox are stored in an ObjectCollection; in ASP.NET, options for DropDownList and ListBox controls are stored in a ListItemCollection. Those collections pretty much share the same methods and properties; the parent controls have the same methods and properties for addressing those collections, too.
So while the controls we will use are different between ASP.NET and Windows Forms, the code we use in either case is almost exactly the same. That’s the strength of object-oriented programming.
Finally, from here on out, unless I state otherwise, I will be using “ComboBox” and “DropDownList” interchangeably.
OK, on with the code.
Step 1: The ComboBox And ListBox Controls
As I just noted, we need to create the ComboBox (DropDownList) control that contains our initial values, plus a ListBox control. You do this as you normally would in Windows Forms: Most people drag the controls from the toolbox onto the form, then set the properties as required.
In the case of ASP.NET, we simply declare a DropDownList and ListBox control on our ASPX page, and add ListItem controls to the DropDownList.
We need to have, as the first item in the ComboBox / DropDownList, a non-selectable item. (You can read my previous entry on non-selectable ListItems for exotic ways to accomplish this task; here, it’s simply an option with no value).
We need to do this because we’ll be removing the selected options from the ComboBox, which will reset the selected index of the ComboBox to be the first item. That means, if we have a list of 10 things, we could only move nine of them; the 10th item would be selected once we remove the 9th item, and therefore, we wouldn’t be able to fire the SelectedIndexChanged event; there aren’t any other options to select.
<asp:DropDownList runat="server" ID="cbxCountries" AutoPostBack="true"> <asp:ListItem Text="Select ..." Value="" /> <asp:ListItem Value="USA" /> <asp:ListItem Value="Canada" /> <asp:ListItem Value="Mexico" /> <asp:ListItem Value="Guatemala" /> <asp:ListItem Value="Belize" /> <asp:ListItem Value="El Salvador" /> <asp:ListItem Value="Honduras" /> <asp:ListItem Value="Nicaragua" /> <asp:ListItem Value="Costa Rica" /> <asp:ListItem Value="Panama" /> </asp:DropDownList> <asp:ListBox runat="server" ID="lstCountries" Rows="10" />
(Note that I have to add an AutoPostBack attribute to the DropDownMenu control, so that changing the selected index of the DropDownList will make the page post back to the server. Of course, there’s no such property for a ComboBox.)
Step 2: The Code
As noted above, doing what the questioner wants is as simple as creating an OnSelectedIndexChanged event handler for the ComboBox control.
And as previously noted, we can use fundamentally the same code to accomplish this task in ASP.NET or Windows Forms. In the case of ASP.NET, we’re working with a ListItem control; in Windows Forms, a generic Object. The code below is set for ASP.NET, just comment out its line and comment in the correct one.
Sub cbxCountries_selectedIndexChanged(ByVal Sender As Object, ByVal E As EventArgs) Handles cbxCountries.SelectedIndexChanged If Not String.IsNullOrEmpty(cbxCountries.SelectedValue) Then 'reset selected index for listbox; this is required for adding new listitems lstCountries.SelectedIndex = -1 'ASP.NET version: add selected listitem to listbox Dim lsiSelected As ListItem = cbxCountries.Items(cbxCountries.SelectedIndex) 'Windows Forms version: add selected listitem to listbox 'Dim lsiSelected As Object = cbxCountries.Items(cbxCountries.SelectedIndex) lstCountries.Items.Add(lsiSelected) 'remove selected from combobox cbxCountries.Items.RemoveAt(cbxCountries.SelectedIndex) End If End Sub
The code above does the following:
- We first check to see if the value of the selected option is an empty string. We do that because we don’t want to insert the “Select …” option into our ListBox. Again, the “Select …” item exists to ensure our OnSelectedIndexChanged event fires.
- We clear the selected index of the ListBox. Every time we add a ListItem to the ListBox, it becomes the selected index of the ListBox control. If our ListBox is set to be a single-selection ListBox — the default behavior, and the case in this demo — an error will be thrown if an option was already selected in the ListBox, because there would then be two selected options. If your ListBox is set to multiple-selection, you need not reset the selected index of the ListBox. There are also ways to retain the selected index of the ListBox when adding a new ListItem to it; I will demo that if asked.
- We declare a generic ListItem or Object control and set it to be whichever ListItem or Object is selected in the ComboBox.
- We use the Add method of the ListItemCollection / ObjectCollection to append the selected option to the ListBox. There are ways to place the inserted item at the top of the list, and I will demo that if there is interest.
- We use the RemoveAt method of the ListItemCollection / ObjectCollection to remove the selected option from the ComboBox.
And that’s all there is to it. You can see this in action here: