Most beginner and even intermediate level programmers, coming out of languages before .NET, often use comboboxes or listboxes to simply list strings of choices, items etc. Then they go through the headache of detecting a user’s choice out of the listbox and fetch information to construct a simple object, possibly displaying that information in other controls related close by. There is an easier way of forming the “master to detail” relationship between a listbox/combo and its related textbox controls. You can build a custom object (if you haven’t already) and store it IN the listbox/combobox. It is a nice feature of the .NET framework. I will show you an example of this using VB.NET … right here on the Programmers Underground!
Before we begin I am going to say that while the example here is in VB.NET, it can certainly work in any .NET related language. The concept is the goal of this entry and after seeing how it works with one language, you can certainly see its value in others. I came up with the idea for writing this entry as I was answering a question on the board several days ago. They were looking to build something similar to our example where they could handle contact information.
So to put this into context, lets assume the following situation has come up…. You have been asked to create a small application which could store contacts. Much like you would have in an address book. The user sees a list of names in a combobox and when they select one, the contact’s name, email and telephone number popup in related textboxes located on the same screen. Where you actually store and retrieve this information is up to you, but you must only load the data once (when the application starts up) and you can’t make repeated calls to your external source because the user may or may not always be connected. The idea here is that we want to get the info and keep it moving in the application without heavily relying on external data which may not always be available.
The typical programmer may find something like this a bit tedious if they can’t always get at the information. Some may even ask if they could download the information to a file and access the file as needed. More clever programmers may opt for an array of contacts which is a good solution, but if you need only the basics an array could be a little overkill. The trick is that we will use the combobox as the actual array of objects (aka collection). But how is this accomplished?
1) First we construct a custom object to hold our contact information. Build the class to hold all the data for a single contact person. In our example it will have three fields, name, address, and telephone. It will also have all the properties to get access to the data and we could use them to even change the contact’s information on the fly.
2) We override the method “ToString()” which was passed down to our object from “Object” at the top of the object hierarchy tree. It is important that we override this method so that we can control what is displayed in the combobox.
3) We add our object to the ComboBox using the classic “Add” method.
4) We access the objects as we would any text items we added before using the Items collection and perhaps an index number.
5) To get back at the object and use it as our Contact class, we cast it back to the appropriate class using CType().
These five steps will be demonstrated as we move through the code pieces. At the end hopefully all of them will come together and make sense. The first piece we will start with is the construction of our custom Contact object.
Public Class Contact Private Thename As String Private Thetelephone As String Private Theemail As String ' Constructor Public Sub New(ByVal name As String, ByVal telephone As String, ByVal email As String) Thename = name Thetelephone = telephone Theemail = email End Sub ' Property we can use to set the Telephone number Public Property Telephone() Get Return Thetelephone End Get Set(ByVal value) Thetelephone = value End Set End Property ' Notice this "overrides" the ToString to create our own ToString Public Overrides Function ToString() As String Return Thename & " - " & Thetelephone & " - " & Theemail End Function End Class
The code above is not fully complete in that it doesn’t provide a property for email or name, but you can model those after the Telephone property I did put in. I wanted to keep this code short and to the point. In the code you also see we override the ToString() function. Here I have created it so that when we store the object in our combobox it will show the person’s name, telephone, and email address as the text. We could have simply made it just display the contact’s name, but for those copying and pasting the code I wanted you to see how this part works.
The next step will be to create an instance of our contact, give it the contact information as part of its constructor and then add it to the combobox.
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim jimmy As New Contact("Jimmy", "1234 567 890", "email@example.com") ComboBox1.Items.Add(jimmy) End Sub [/vbet] In the code above, when the form loads we create a new Contact object we call "jimmy" and populate it with Jimmy's information including his name, phone, and email address. After the line is complete, we have a full contact object ready to add to our combobox. So using the item collection's add method, we add the object. When this line is finished executing, we should see Jimmy's information in the combobox. Now when the user selects an item from the combobox, we want to pull out the object, cast it back to a Contact object (because the combobox only knows its elements as "objects") and use the properties/methods of the object to update it and/or display its contents. Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged Dim blankContact As Contact blankContact = CType(ComboBox1.Items.Item(ComboBox1.SelectedIndex), Contact) MessageBox.Show(blankContact.Telephone) End Sub
Here we detect if the user has selected a contact through the SelectedIndexChanged event. We read the SelectedIndex value (assuming they can only choose one item in the combo) and we construct a new Contact variable, cast the choice back to a Contact object using CType and then use the property “Telephone” to get at their telephone number. Here we show the telephone number in a simple messagebox, but we could have set a textbox to this information. Assuming that the user chose “Jimmy” it would take that contact object out of the combo, cast it to a contact object, put it in “blankContact” and showed Jimmy’s phone number in a messagebox.
Going back to our original problem, if we load up all the contacts when the application starts, make them into objects and store them into the combo, our application can read the contacts using these objects instead of sending query after query to an external source such as a database or file. If we then need to sync the information later, we can read the combobox and compare its object data to an external source (might be an idea for a future blog entry).
The reason that .NET allows this is because of polymorphism. Since your custom object “IS A” object the combo can treat it as so using its basic Object functionality like “ToString()” without knowing the real type of object it is. You could essentially have Contact objects, User Objects, Thingamajig objects all mixed in the combobox and it would only know that it has a list full of Objects.
So this brings up one critical point you have to watch out for, making sure that the objects you store are the type you expect them to be. If you attempt to store a thingamajig object in the combo and then cast it back out as a contact object, you will get an error about illegal casting. You can prevent this by first checking the object’s type using “GetType()” which belongs to the “Object” class. Check it to make sure that it is a Contact object before attempting to cast it to Contact.
My best advice is just to keep all objects the same type in the combo so you don’t have to worry about it in the future.
I hope this article has proved useful to you. Feel free to use the code you see here in your own projects and I hope you come back to read more of my blog entries. Thanks again for all your support and for reading. 🙂