Binding an ASP.Net Control to a Generic List

In this tutorial I will show you how to bind ASP.Net Control to a Generic List or array of objects and control how they dispay.

By Tim Trott | C# ASP.Net MVC | February 21, 2012
1,056 words, estimated reading time 4 minutes.

.Net makes it very easy to bind its data objects to data controls, but there are times when you may wish to bind a generic, or even custom data structure, to a data control. This tutorial will show you how to bind a generic data object and a custom class to data-bound controls so that they behave the same as the .Net native data structures.

Binding ASP.Net Control to a Generic List

In this first example, I will show you how to bind a simple List object to a drop-down box. First, we need some data, so I'm going to create a static list of colours.

C#
List<string> colours = new List<string>();
colours.Add("Black");
colours.Add("Slate Gray");
colours.Add("Midnight Blue");
colours.Add("Steel Blue");
colours.Add("Firebrick");
colours.Add("Purple");
colours.Add("Cyan");
colours.Add("Sea Green");
colours.Add("Dark Green");
colours.Add("Yellow");
colours.Add("Khaki");
colours.Add("Dark Orange");
colours.Add("Red");

Now, you may be tempted to loop through each item and add it to a list by creating a new list item:

C#
foreach (string colour in colours)
  lstColours.Items.Add(new ListItem(colour));

While this method will certainly get the job done, it is perhaps not the most efficient nor the correct way of doing things. Instead, you should bind the data to the list box, and that is done just like binding an ADO.Net DataSet.

C#
lstColours.DataSource = colours;
lstColours.DataBind();

This will produce a user-selectable list (ListBox, ComboBox, CheckListBox etc...) of colours where the key and the value are both set to the colour name. While this may be the result you need, more often than not you will need a separate value, or code, for each item which you can later use. In this instance, you will need to use a generic data type that supports a key/value pair such as a Dictionary or Hashtable.

List of colours
List of colours

Let us recreate the colours data list using a Dictionary using the HTML hex colour codes as the key.

C#
Dictionary<string, string> colours = new Dictionary<string, string>();
colours.Add("#000000", "Black");
colours.Add("#657383", "Slate Gray");
colours.Add("#151B54", "Midnight Blue");
colours.Add("#4863A0", "Steel Blue");
colours.Add("#800517", "Firebrick");
colours.Add("#8E35EF", "Purple");
colours.Add("#00FFFF", "Cyan");
colours.Add("#4E8975", "Sea Green");
colours.Add("#254117", "Dark Green");
colours.Add("#FFFF00", "Yellow");
colours.Add("#ADA96E", "Khaki");
colours.Add("#F88017", "Dark Orange");
colours.Add("#FF0000", "Red");

This time when we bind the list to a control, we get a different and unexpected, result as shown in the image to the right. This is because the standard ToString() method of the Dictionary class will return both the key and the value together - not what we were looking to get!

What we need to do is tell the list box what to use as the key and what to use as the value. This is where it gets slightly confusing as the key of the colours object will become the value of the list item, and the value of the colours object will be the list item text.

Colour list with HEX values
Colour list with HEX values
C#
lstColours.DataSource = colours;
lstColours.DataValueField = "Key";
lstColours.DataTextField = "Value";
lstColours.DataBind();

This will now result in a list that is shown like the first example, but the value of the selected item will be the hexadecimal colour code of the selected colour!

Remember: Unless you tell the list otherwise, it will use the default .ToString() method to set both the item value and item text. You must use DataValueField and DataTextField to tell it which fields to use.

Control Data Binding to a Class

This technique can also be used to bind a collection of classes to a list as well. For this, to work you need to specify the properties to be used as the key and value.

C#
/ The class we are going to use in this example
public class Customer
{
    private string _accountNumber;
    public string AccountNumber
    {
        get { return _accountNumber; }
        set { _accountNumber = value; }
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    private string _address;
    public string Address
    {
        get { return _address; }
        set { _address = value; }
    }

    public Customer(string account, string name, string address)
    {
        _accountNumber = account;
        _name = name;
        _address = address;
    }

    public override string ToString()
    {
        return string.Format("{0} ({1})", Name, AccountNumber);
    }
}

This class defines three public properties, a constructor to make adding new items easier and an override for the ToString() method. Next, we populate a list of Customer classes.

C#
List<Customer> customers = new List<Customer>();
customers.Add(new Customer("123456", "Bob Smith", "1 Some Street"));
customers.Add(new Customer("789012", "Jane Doe", "2 Example Road"));
customers.Add(new Customer("345678", "John Smith", "3 Sample Lane"));
customers.Add(new Customer("901234", "Jane Fonda", "4 Sample Avenue"));

Now we can bind this list to a list box control as we have done before.

C#
lstCustomers.DataSource = customers;
lstCustomers.DataBind();

As seen in the previous examples, this default binding will use the ToString() method of the List item object. This is shown in the image to the right which shows our overridden ToString() being used. As with the colours list, we can tell the list box which properties of the class to use for the key and the value.

Binding a class to a list
Binding a class to a list
C#
lstCustomers.DataSource = customers;
lstCustomers.DataValueField = "AccountNumber";
lstCustomers.DataTextField = "Name";
lstCustomers.DataBind();

This will now bind the class property AccountNumber to the list item value property, and the Name property of the class to the list item text.

In your C# code behind, when the form is submitted you can retrieve the account number of the selected item from the list by accessing its SelectedItem property.

When binding complex data structures to ASP.Net controls, it is often helpful to access the full record, not just the value and description. In these instances, you can use the code below to get the full list item from a list box data source.

C#
protected void ListBox_OnClick(object sender, EventArgs e)
{
  ListBox lb = sender as ListBox;

  if (lb != null)
  {
    foreach (ListItem item in lb.Items)
    {
      object o = lb.DataSource;
      List<Customer> data = o as List<Customer>;

      / Now get the customer selected
      Customer cust = data.Find(toFind => toFind.AccountNumber == item.Value);

      / ...
    }
  }
}

And that's how to bind generics to data controls!

Was this article helpful to you?
 

Related ArticlesThese articles may also be of interest to you

CommentsShare your thoughts in the comments below

If you enjoyed reading this article, or it helped you in some way, all I ask in return is you leave a comment below or share this page with your friends. Thank you.

This post has 1 comment(s). Why not join the discussion!

We respect your privacy, and will not make your email public. Learn how your comment data is processed.

  1. SB

    On Monday 10th of October 2016, Simon Brown said

    I found this as was interested in getting to the complex data associated with datasource property.
    I have a Datalist (rather than Listbox) control and bind the datasource to my own class as a list
    That all shows fine with my added checkbox to select multiple items.

    However when processing the Datalist from a submit button the datalist.datasource is set to null viewing from VS debugger.

    I would absolutely like to grab the matching entry in the datasource list for the complex class to process the request.
    Do you know why a datalist would not support this, I am using so can use templates to present multiple fields