The Windows Forms ListBox -- VS.NET 2005
by Peter A. Bromberg, Ph.D.

Peter Bromberg

Recently we've had several posts relating to general difficulty "grokking" the Windows Forms ListBox and related controls. This can be especially frustrating for ASP.NET developers since they are used to having a DataTextField and DataValueField and don't understand why the Windows Forms ListBox doesn't offer the same conveniences - at least in terms of storing simple name - value pairs. In addition, the Items Collection editor in the Property Sheet is a simple String Collection editor, which can make the uninitiated even more confused.

Windows Forms ListBox has an Items property that is comprised of a ListBox.ObjectCollection. That is a collection of objects, and what that means is that you can store whatever you want as a ListBox Item. When you bind a Collection to a ListBox (which is how one would normally populate one), it's default behavior is to display the ToString() of whatever object you've stored in it. So, for example, if you set a DataTable to be the DataSource of a ListBox, you will get to see a nice list of System.Data.DataRowView's, since that's what the individual row item in a DataTable translates to. However, if you set the DisplayMember to a column name, then the ListBox will dutifully display the contents of that column for each row in your DataTable. Much better!



Because of the power of the "Mother Function", class Object, you can also store custom items in a ListBox, and one easy way to ask it to display what you want is, as mentioned above, to have your custom item return that as its overridden ToString method.

So what I present here is a very simple Visual Studio 2005 WinForms app that has a ListBox, a Label, and two buttons. The first button populates a DataSet from our main RSS feed here on Eggheadcafe.com (I'm lazy). And the other button gets the same DataSet, but iterates over the rows to create an ArrayList of a small CustomItem class, to illustrate other alternatives.

So here is what the UI of the sample app looks like. We've clicked on the Use Custom Class button, and selected an item from the list. The label at the botton shows that the listBox1.Text property and the CustomItem "value" property result, which is represented with  ((CustomItem)((ListBox)sender).SelectedItem).Value , can be easily obtained and displayed:

Example Listbox

And following is the complete contents of the Form1 partial class, which contains all the populating and data manipulation code:

using System.Collections;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

 

namespace ListboxSample2005

{

    public partial class Form1 : Form

                   {

 

                       private bool IsDataSet = false;

                       public Form1()

                       {

                           InitializeComponent();

                       }

 

                       private void button1_Click(object sender, EventArgs e)

                       {

                           IsDataSet = true;

                           DataSet ds = new DataSet();

                           ds.ReadXml("http://www.nullskull.com/rss.xml");

                           listBox1.DataSource = ds.Tables[2];

                           listBox1.DisplayMember = "title";

 

 

                       }

 

                       private void listBox1_SelectedIndexChanged(object sender, EventArgs e)

                       {

                           if (IsDataSet)

                           {

                               label1.Text = "";

                               label1.Text = "Text Property: " + listBox1.Text + "\n";

                               label1.Text += "DataRowView \"title\" column: "
                                  + ((DataRowView)((ListBox)sender).SelectedItem).Row["title"];

                              

                           }

                           else

                           {

                               label1.Text = "";

                               label1.Text = "Text Property: " + listBox1.Text + "\n";

                              label1.Text += "Class Property \"value\" : " +

                                          ((CustomItem)((ListBox)sender).SelectedItem).Value;

                           

                           }

                       }

 

                       private void button2_Click(object sender, EventArgs e)

                       {

                           IsDataSet = false;

                           DataSet ds = new DataSet();

                           ds.ReadXml("http://www.nullskull.com/rss.xml");

                           DataTable dt = ds.Tables[2];

                           ArrayList al = new ArrayList();

                           string thename;

                           string thevalue;

                           foreach (DataRow row in dt.Rows)

                           {

                               thename = (string)row["title"];

                               thevalue = (string)row["link"];

                               al.Add (new CustomItem(thename,thevalue)); 

                           }

                           listBox1.DataSource =al;

                       }

                   }

}

Now here is the CustomItem sample class we use to populate the ListBox from the second button. You can see this is ultra-simple, and provides an overriden ToString method that returns the Name field:

using System;

using System.Collections.Generic;

using System.Text;

 

namespace ListboxSample2005

{

    class CustomItem

    {

        public string Name;

        public string Value;

 

        public CustomItem(string name, string value)

        {

            this.Name = name;

            this.Value = value;

        }

 

        public override string ToString()

        {

            return Name;

        }

 

    }

}

It's easy to see that we can tame the Windows Forms ListBox and make it behave nicely! There's much more to this class, but this should be enough to get anyone to first base.

Download the Visual Studio.NET 2005 solution accompanying this article

 


Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform.
Article Discussion: