1. Computing

ListBox, Dictionary, and ListView Example

A simple question needs a longer answer!

By

A reader wrote in with what initially seems to be a fairly simple question: "How do I generate a list (with just the keys) from a dictionary (with keys and values)?

This might be one of those examples of the old saying, "To err is human, but it takes a computer to really mess things up." This might look like a very simple question, but several things need to be clarified before I can provide an answer. To begin with:

-> Which type of dictionary?
-> Which type of list?
-> Which version of Visual Basic?

One of the things that I do when I first get a question like this is check to see if I have answered it before. When I did that here, I discovered that I had written something about a "Dictionary" object, but it was completely out of date. VB6 Collection, VBScript Dictionary, and VB.NET Hashtable. (I've been doing this page a long time!) Thanks to my reader, I added a few words about more current VB.NET versions and then left it on the site in case someone with that version of VB still needed it.) But the whole answer just isn't here, so I'm adding it now.

There are two things you can reference in VB.NET that are called a Dictionary object. The first is the old scripting object that the article above writes about. You probably shouldn't use that today. The second was added with generics. (See: Generics! Cleaner Data - Faster Code!) This is the dictionary you should use if you need a dictionary. But you would have to keep it in sync with a ListBox through your own program code. For example, use a sub to add and delete all items from both the dictionary and the ListBox so you can be sure that they have identical indexes.


Sub AddToDictionaryAndListBox(
    ByVal dict As String, ByVal list As String)
    theDictionary.Add(dict, list)
    ListBox1.Items.Add(dict)
End Sub

But you probably don't need a dictionary. A dictionary is a fast and flexible object that you can use for high performance, lots of data, and unusual requirements. You can get identical results without one, but not with a ListBox. Although a ListBox provides a MultiColumn property, it's really only useful to pack things in a little tighter. Quoting Microsoft, "A multicolumn ListBox places items into as many columns as are needed to make vertical scrolling unnecessary." You can't really keep track of more than one column in a row.

For that, you probably need a ListView instead. A ListView control has a lot more capability than this simple requirement needs too, but it will do the job. It is, however, slightly confusing.

In brief, a ListView maintains rows (ListViewItem objects) and columns (the Columns collection). Each row (ListViewItem) can have an Item and as many SubItems as you wish. So, if you use code like this:


ListView1.Columns.Add("Alpha Index", 100)
ListView1.Columns.Add("Word", 100)
ListView1.Columns.Add("Word Definition", -2)

You get three columns. In the Details view, the column headers are shown. The text fields above are the column headers. The -2 value expands the width of the last column to fill the space.

Adding information into the ListView isn't quite as straightforward. First, the code and then the explanation:


Dim item1 As New ListViewItem("A")
item1.SubItems.Add("Aardvark")
item1.SubItems.Add("burrowing mammal with a long snout")
ListView1.Items.Add(item1)

Note that there is one ListViewItem and two SubItems. It may seem like three columns to you, but that's not the way the ListView control works. The ListViewItem behaves like both the row and the first column. Here's the running program:

--------
Click Here to display the illustration
--------

But that's not quite what the reader asked for. The reader wanted the key to display in a list and the value associated with that key to be available when the key is selected. To produce just a single column, code the width of the column you don't want to display as zero:


ListView1.Columns.Add("Key", -2)
ListView1.Columns.Add("Value", 0)

AddItemsToListView("1", "Value for Item 1")
AddItemsToListView("2", "Value for Item 2")
AddItemsToListView("3", "Value for Item 3")
AddItemsToListView("4", "Value for Item 4")
AddItemsToListView("5", "Value for Item 5")

--------
Click Here to display the illustration
--------

The code to select from this ListView isn't completely obvious either. I used the SelectedIndexChanged event of the ListView to display the value. Again, code first, then explanation.


Private Sub ListView1_SelectedIndexChanged(
    sender As Object, e As System.EventArgs
    ) Handles ListView1.SelectedIndexChanged
    Dim theItems As  _
        ListView.SelectedListViewItemCollection =
    Me.ListView1.SelectedItems
    For Each item As ListViewItem In theItems
        TextBox1.Text =
        item.SubItems(1).Text
    Next
End Sub

The most confusing thing (for me) is that the SubItems in an item are a collection that you have to iterate through whether you want to or not. In other words, we only need the value of the only SubItem in each ListViewItem. It seems like I ought to be able to simply take the one at that index position. But VB.NET crashes when you do that and I haven't been able to find a simple way around it. But an iteration that only executes once works!

--------
Click Here to display the illustration
--------

If you know of a simpler way, send me a message and let me know.

See More About
  1. About.com
  2. Computing
  3. Visual Basic
  4. Quick Tips
  5. ListBox, Dictionary, and ListView Example

©2014 About.com. All rights reserved.