Asp.net 4.5 webforms – model binding selected value for dropdownlist and listbox

With the Asp.net 4.5 release, webforms inherited several improvements from its Asp.net MVC cousin. I’ve been enjoying the new model binding support lately. Since none of the old datasource controls fully support Entity Framework’s DbContext anyway, model binding is quite handy when using code-first EF models.

For the most part, model binding is straight forward. The basic usage is covered in the tutorials on the asp.net web site, but other resources are rare and hard to find. In the case of DropDownList and similar controls, I found that model binding in webforms was not as straight-forward as I would have thought — especially when trying to set the selected value.

Before I begin, let me explain about the SelectList class.

These examples are valid no matter what data you bind to, but the ItemType that I’m showing in these examples use an implementation of the SelectList class, which I’ve borrowed from asp.net MVC. I don’t like to reference MVC assemblies in my webforms applications, so I just copy in source files to my webforms application. Using SelectList gives you a consistent and strongly typed collection, which tracks each item’s display text, value, and its selected state. SelectList acts as a sort of miniature view-model.

The code for SelectList can be found on the AspNetWebStack project page over at CodePlex. Here are the three files needed for SelectList :

How you bind your dropdownlist depends a lot on if it appears inside some other model bound control or not. To bind a dropdownlist inside of a model bound container (repeater, listview, formview, etc) looks something like this:

*.aspx.cs

<asp:DropDownList ID="MyDropDown" runat="server" 
	SelectMethod="GetMyDropDownItems"
	ItemType="MyApp.SomeNameSpace.SelectListItem" 
	DataTextField="Text" 
	DataValueField="Value"
	SelectedValue="<%# BindItem.EdCodeType %>" 
/>

*.aspx.cs

protected SelectList GetMyDropDownItems()
{
    var items = from t in someDbContext.AllThings
    select new { ID = t.ID, Name = t.Name };
    return new SelectList(items, "ID", "Name");
}

Note: SelectedValue property does NOT show up in intellisense. This appears to be a bug caused by the fact that this property was marked with the BrowsableAttribute set to false (for mysterious reasons). 

When working with a dropdownlist that is not conveniently nested within a model bound container control, binding the dropdown is still fairly simple. You have three options. You can explicitly declare a selected value, if you know what it is at design-time and it never changes. If that isn’t the case, then you can set the SelectedValue property to the results of some method call, or wire up an ondatabound event handler to set the selected item. Here are the examples:

Declarative example: Set SelectedValue to a known value (rarely helpful):

*.aspx.cs

<asp:DropDownList ID="MyDropDown" runat="server" 
	SelectMethod="GetMyDropDownItems"
	ItemType="MyApp.SomeNameSpace.SelectListItem" 
	DataTextField="Text" 
	DataValueField="Value"
	SelectedValue="1234" 
/>

Declarative example: Set SelectedValue to the result of a method call:

*.aspx

<asp:DropDownList ID="MyDropDown" runat="server" 
	SelectMethod="GetMyDropDownItems"
	ItemType="MyApp.SomeNameSpace.SelectListItem" 
	DataTextField="Text" 
	DataValueField="Value"
	SelectedValue="<%# GetSelectedItemForMyDropDown()%>"
/>

*.aspx.cs

private SelectList myDropDownItems;

protected SelectList GetMyDropDownItems()
{
	//store the selectlist in a private field for use by other events/methods later
	if(myDropDownItems == null)
	{
		var items = from t in someDbContext.AllThings
					select new { ID = t.ID, Name = t.Name };

		var selectedItems = from t in someDbContext.SelectedThings
					select new { ID = t.ID};

		myDropDownItems = new SelectList(items, "ID", "Name", selectedItems);
	}

	return myDropDownItems;
}

protected string GetSelectedItemForMyDropDown()
{
	var selected = GetMyDropDownItems().FirstOrDefault(i => i.Selected);
	return (selected != null) ? selected.Value : string.Empty;
}

Event example: Set Selected item from an event handler

*.aspx

<asp:DropDownList ID="MyDropDown" runat="server" 
	SelectMethod="GetMyDropDownItems"
	ItemType="MyApp.SomeNameSpace.SelectListItem" 
	DataTextField="Text" 
	DataValueField="Value"
	OnDataBound="MyDropDown_DataBound" 
/>

*.aspx.cs

private SelectList myDropDownItems;

protected SelectList GetMyDropDownItems()
{
	//store the selectlist in a private field for use by other events/methods later
	if(myDropDownItems == null)
	{
		var items = from t in someDbContext.AllThings
					select new { ID = t.ID, Name = t.Name };

		var selectedItems = from t in someDbContext.SelectedThings
					select new { ID = t.ID};

		myDropDownItems = new SelectList(items, "ID", "Name", selectedItems);
	}

	return myDropDownItems;
}

protected void MyDropDown_DataBound(object sender, EventArgs e)
{
	var ddl = (DropDownList)sender;
	var selectedValue = GetMyDropDownItems().FirstOrDefault(i => i.Selected);
	if(selectedValue != null)
	{
		ddl.Items.FindByValue(selectedValue.Value).Selected = true;
	}
}

With the ListBox control, and controls similar, you can employ the same techniques as long as you only allow single item selection. If you need to support multiple selection though, you can’t just set SelectedValue. Instead, you would use the DataBound event to loop each item to selecting the appropriate ones.

*.aspx

<asp:ListBox ID="MyListBox" runat="server"
	SelectionMode="Multiple"
	SelectMethod="GetMyListBoxItems"
	ItemType="Weber.Vfao.Inside.Web.SelectListItem"
	DataTextField="Text" 
	DataValueField="Value" 
	OnDataBound="MyListBox_DataBound"
/>

*.aspx.cs

private SelectList myListBoxItems;

protected SelectList GetMyListBoxItems()
{
	//store the selectlist in a private field for use by other events/methods later
	if(myListBoxItems == null)
	{
		var items = from t in someDbContext.AllThings
					select new { ID = t.ID, Name = t.Name };

		var selectedItems = from t in someDbContext.SelectedThings
					select new { ID = t.ID};

		myListBoxItems = new SelectList(items, "ID", "Name", selectedItems);
	}

	return myListBoxItems;
}

protected void MyListBox_DataBound(object sender, EventArgs e)
{
	var lb = (ListBox)sender;
	foreach (var item in GetMyListBoxItems())
	{
		if (item.Selected)
		{
			b.Items.FindByValue(item.Value).Selected = true;
		}
	}
}

3 Replies to “Asp.net 4.5 webforms – model binding selected value for dropdownlist and listbox”

Leave a Reply to 3nigma Cancel reply

Your email address will not be published. Required fields are marked *