"It's the little things that make life such a big deal" - Timbuk3
With VB7 we can write real Windows services in less than a minute, deploy complex distributed apps with XCOPY and an XML file and save the universe in 4 lines of code ... but while the big things we could never do before are easy now, it'll take some time and repeated exposure to get our fingers to start doing all of the workhorse code in the new ways.
Take filling a combobox.
You used to just add text items to a combo with a single easy method, and if you needed to use a mapped index value (as in a code value like CA = 1, WA = 2) you'd set the new items' ItemData property to the code value like:
Private Sub butFillCombo_Click()
With Combo1
.AddItem "CA"
.ItemData(.NewIndex) = 1
.AddItem "WA"
.ItemData(.NewIndex) = 2
.ListIndex = 0
End With
End Sub
And you could check both of the values easily with:
Private Sub Combo1_Click()
MsgBox Combo1.List(Combo1.ListIndex) & vbCrLf & _
Combo1.ItemData(Combo1.ListIndex)
End Sub
Now the combobox is all OOP-ed out and you have to fill it with real objects.
Most of the examples out there show filling the combo with databinding and if you're filling from an ADO.net datasource then do a Google for any of the many examples of using the .DataSource, .DisplayMember and .ValueMember properties.
If, however, you just want to populate the list dynamically or with hard coded options, you don't have to go whole-hog using an Arraylist as the MSDN examples (and the clones of the MSDN examples) show ... but you will have to make a class for the items.
For instance, to fill a DropDownList style combo with a list of status values ("Pending = 1", "Processing = 2", "Successful = 3", "Failed = 4"), define a class:
Public Class StatusCode
Public CodeText As String = ""
Public CodeValue As Short = 0
Public Overrides Function ToString() As String
Return CodeText
End Function
End Class
Note: Don't forget to have an Overriden ToString, that is how the combo will set the text value. Also, this brings up a nice part of the move to VB7; you can now define a class within a class. In the above example we defined the StatusCode class as being Public, and even though we can type its' definition in the same file as the form (just after the forms' "End Class") in most cases there is no need to have a combo or listbox items class be available to code out side of that form. In such cases, you can define the items class inside the Form class definition region, and declare the new class (in our example, the StatusCodes class) as Private.
Now, in the form_load or other event, call a routine to initialize the Combo:
Private Sub InitGUI()
Dim SC As StatusCode
With combo1
SC = New StatusCode()
SC.CodeText = "[choice required]"
SC.CodeValue = 0
.Items.Add(SC)
SC = New StatusCode()
SC.CodeText = "Pending"
SC.CodeValue = 1
.Items.Add(SC)
SC = New StatusCode()
SC.CodeText = "Processing"
SC.CodeValue = 2
.Items.Add(SC)
SC = New StatusCode()
SC.CodeText = "Successful"
SC.CodeValue = 3
.Items.Add(SC)
SC = New StatusCode()
SC.CodeText = "Failed"
SC.CodeValue = 4
.Items.Add(SC)
.SelectedIndex = 0
End With
End Sub
And you can check the values with:
Private Sub combo1_SelectedIndexChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles combo1.SelectedIndexChanged
Dim sc As StatusCode
sc = combo1.SelectedItem
MsgBox(sc.CodeText & vbCrLf & _
sc.CodeValue)
End Sub
So what's the reason for all the examples showing the use of an ArrayList? Options. You can feel free to mix and match as you see fit. For instance, the above example used 4 lines of code to add each StatusCode object to the combobox, That code is very easy to read as it's extremely explicit, but the more lines of code you add the more there is a chance that in one of the items you'll forget to set a required property. You could have defined the StatusCode class as:
Public Class MyForm
...
Private Class StatusCode
Public CodeText As String = ""
Public CodeValue As Short = 0
Public Sub New()
End Sub
Public Sub New(byval Text as String, byvalValue as Short)
CodeText = Text
CodeValue = Value
End Sub
Public Overrides Function ToString() As String
Return CodeText
End Function
End Class
...
End Class 'The MyForm Class
Now, with the custom constructor you can streamline the initialization of the combobox items and Intellisense will prompt you for the required properties:
Private Sub InitGUI()
With combo1
.Items.Add(SC = New StatusCode("[choice required]",0)
.Items.Add(SC = New StatusCode("Pending", 1)
.Items.Add(SC = New StatusCode("Processing, 2)
.Items.Add(SC = New StatusCode("Successful", 3)
.Items.Add(SC = New StatusCode("Failed", 4)
.SelectedIndex = 0
End With
End Sub
The reviews mostly say that "once you get the hang of it" you'll like it better. You do have to admit that it's more flexible in that you can attach any type of object and work directly with the object as you want rather than using an index to search some other collection/array.
You could make a very generic class that itself accepts any kind of object and lets you set the value of the overridden ToString, with that you dont bulk up your app with a "StatusCodes" class and a "PickANumber" class and, and and.
But the main thing is that you don't have to do the oft-exampled ArrayList of custom objects plus the .DataSource and .DisplayMember properties ... you can just add the objects directly as shown here.
Hope it helps!
Robert Smith
Kirkland, WA
added June 2002