Repeated Value Binding to ASP.NET List Controls
by Pete Ehli
ASP.NET provides a powerful and rich set of server side controls, but
after you write your server tag, <asp:dropdownlist
id="MyDropDownList" runat ="server"> for instance, how do you
bind your control to your intended data source, and what method do you
use to perform your data binding? Well if you have ever done any Visual
Basic or Access development, then you probably have some experience using
data binding to bind controls to a data collection like a recordset for
example. The binding in ASP.NET is similar, but in ASP.NET using server
side Web Controls, all the data binding takes place on the server and
the result is HTTP sent to the client or browser in HTML 3.5, unless otherwise
specified. This means we can target a wide range of browsers running on
a wide range of platforms using some pretty cool ASP.NET controls.
In this article we will look at data binding using four types of list
controls: a DropDownList, a RadioButtonList, a DataList,
and a DataGrid. To bind any of the list controls you would use
a collection such as an ArrayList, HashTable, DataReader,
and DataSet. We have left out binding using a DataView,
but you can easily change the 'DataSet Binding Example' shown here to
use the DataView class, which is defined in the System.Data namespace.
We will show the DataSet binding example last, so let's hold off on any
explanation until we get there.
Basically there are two types of binding, "single value binding" and
"repeated value binding". Single value binding refers to just that, binding
a single value to a control such as an ASP:TextBox, ASP:HyperLink, ASP:Image,
ASP:LinkButton and so on. This article is only concerned with repeated
value binding using list controls that use one of the aforementioned collections
as the data source. List controls can bind only to collections that support
the IEnumerable, ICollection, or IListSource interface,
so all list controls basic behavior is predefined for you with these interfaces.
When you bind a control you can individually bind single controls or
all the controls on the page. DataBind() is a method of the Page class
and also all server controls. Calling Page.DataBind() or DataBind() will
call all of the data binding expressions on the page to be executed. Typically
you would perform all your data binding in the Page_Load method, as we
do in our examples included here.
Quick Note: I am
a big advocate of using the code behind file to implement the design
strategy of loose coupling, strong cohesion, and information hiding,
not to mention avoiding rats nest or spaghetti code which results
in the use of inline code. Imagine having a web form with 20 or
more controls with at least 10 or more requiring some complicated
script logic. If you write server tags, HTML, and script logic all
within the .aspx page, what you have is a huge mess! The examples
here are simple, and use inline code for explanation and space purposes.
You can easily take the script out of the page and place it in the
code-behind Page_Load method where it belongs. I suggest that if
you are new to using these controls and binding them, that you first
get the examples to run as is, and then implement the code-behind
page. |
There are eight ASP.NET controls designed for repeated value server side
binding. They are the HTML select, ListBox, DropDownList,
CheckBoxList, RadioButtonList, Repeater, DataList,
and DataGrid. All of these controls have Properties, Methods and
Events that allow us to manage the binding process. Their Properties
are: DataTextField, DataValueField, DataTextFormatString,
and DataMember. The Methods are: DataBind, and FindControl.
The Events are: DataBinding, and SelectedIndexChanged.
In the examples provided you will see the use of all of the properties
and methods except the FindControl method. Events are a different
story and we are mainly concerned with how to bind our controls to data
sources, so we will leave Events for you to investigate on your own after
you see how to perform some simple binding through the provided examples.
Let's look at the first example using an ArrayList which is a
class of the System.Collections namespace. In the Page_Load method
we first declare our ArrayList and load the ArrayList with string objects
of fictitious programming books. The databind process in this example
is straightforward and pretty simple. There are two ways to map data to
our controls. One is to use the control's properties depending on what
control we are using to bind our data to, or we can use templates if the
control supports them. Let's look at our example DataList control that
supports templates. The DataList control uses a template referenced by
the tag <itemtemplate>, that is the DataList control below uses
a template defined within the control, which tells the control how to
bind our data. Binding using templates takes place using the syntax <%#
TheNameOfTheDataSource %>. Using this syntax you can bind to data sources,
properties of your page, properties of another control, collections, expressions,
and also results returned from called methods. The only three ASP.NET
list controls that support templates are the, Repeater, DataList,
and DataGrid. What is going on in our DataList control is that
the row or list item is mapped to our data using a DataItem object
within the controls Container to designate which field or column
we want to display. Since we only have one column to display, which is
our fictions books, that is what we get. In the next example using the
HashTable, we will define two columns or fields to be displayed.
ArrayList Binding Example
<!doctype html public "-//w3c//dtd html 4.0 transitional//en"
>
<html>
<head>
<title>ArrayList Binding</title>
</head>
<body>
<form runat="server">
<p align=center><b><font size="5"> ArrayList
Binding</font></b></p>
<p align=left>
<table height=603 cellspacing=1 cellpadding=0 width=605 border=0>
<tr>
<td>
<p align=center><b>DropDownList Control:
MyDropDownList</b></p>
</td>
</tr>
<tr>
<td>
<p align=center><asp:dropdownlist id="MyDropDownList" runat="server">
</asp:dropdownlist></p>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td>
<p align=center><b>RadioButtonList
Control: MyRadioButtonList</b></p>
</td>
</tr>
<tr>
<td>
<p align=center>
<asp:RadioButtonList id="MyRadioButtonList" runat="server">
</asp:RadioButtonList></p>
</td>
</tr>
<tr>
<td>
<font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td>
<font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td>
<p align=center><b>DataGrid Control:
MyDataGrid</b></p>
</td>
</tr>
<tr>
<td>
<p align=center>
<asp:datagrid id="MyDataGrid" runat="server"></asp:datagrid>
</p>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td>
<p align=center><b>DataList Control:
MyDataList</b></p>
</td>
</tr>
<tr>
<td>
<p align=center>
<asp:datalist id="MyDataList" runat="server">
<itemtemplate>
<%# Container.DataItem %>
</itemtemplate>
</asp:datalist></p>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td>
<p align=left><font face="Tahoma" size="2">Author: Pete
Ehli</font></p>
</td>
</tr>
</table>
</p>
</form>
<script language="C#" runat="server">
private void Page_Load(object sender, System.EventArgs e)
{
//Create an ArrayList of values to bind to
ArrayList MyArrayList = new ArrayList();
MyArrayList.Add("Turbo C#");
MyArrayList.Add("C# Programming 101");
MyArrayList.Add("DOS Basic Training");
MyArrayList.Add("C# Patterns with ASP.NET");
MyArrayList.Add("ADO.NET in Action");
MyArrayList.Add("Intermediate ASP.NET");
//Bind the controls to the data source MyArrayList
MyDropDownList.DataSource = MyArrayList;
MyRadioButtonList.DataSource = MyArrayList;
MyDataGrid.DataSource = MyArrayList;
MyDataList.DataSource = MyArrayList;
//Bind all controls on the page
Page.DataBind();
}
</script>
</body>
</html>
In the 'HashTable Binding Example' below we have added prices for our
books. Using a HashTable provides a simple solution to displaying two
values to be displayed by our controls instead of one. Each of the HashTable
references has a Key and a Value. The key is the name of
our fictitious books and the value is the book prices. If you are familiar
with HashTables you know that they are a Dictionary of sorts. If you compare
a real life dictionary to a HashTable, the Key is the word in the dictionary
and the definition is the value. Using a HashTable we locate our data
using the Key, we do this by the statement MyDropDownList1.DataValueField
="Key"; We then tell the control what data to display MyDropDownList1.DataTextField
= "Key"; and then format the data if we wish MyDropDownList2.DataTextFormatString
= "{0:E}"; which in the case of our second DropDownList control is scientific
notation. If we look at our DataList control you will see that we are
using the DataBinder.Eval method of the DataBinder class
for displaying our data. We use the Eval method of the DataBinder
class in our example because it is capable of displaying two values. The
DataBinder.Eval method takes three arguments used for locating,
displaying, and formatting our data, with the third argument being optional.
One important point here is that DataBinder.Eval is a static method
that uses late-bound reflection to bind data. It therefore incures a "performance
hit", but in my opinion this hit is negligible when taken into account
its functionality and ease by which it makes binding possible. Let's now
consider binding the DataGrid control using a HashTable. The DataGrid
control using an ArrayList, DataReader, DataView, and DataSet as its data
source is smart enough to figure out what columns or fields to display,
but not using the HashTable. As you see we need to use the <asp:boundcolumn>
tag within the control definition to specify to the DataGrid what columns
or fields, and what header information to display. Also, we format the
second column as currency values.
HashTable Binding Example
<!doctype html public "-//w3c//dtd html 4.0 transitional//en"
>
<html>
<head>
<title>HashTable Binding</title>
</head>
<body>
<form runat="server">
<p align=center><b><font size="5"> HashTable
Binding</font></b></p>
<p align=left>
<table height=603 cellspacing=1 cellpadding=0 width=605 border=0>
<tr>
<td>
<p align=center><b>DropDownList Control:
MyDropDownList1</b></p>
</td>
</tr>
<tr>
<td>
<p align=center><asp:dropdownlist
id="MyDropDownList1"
runat="server">
</asp:dropdownlist></p>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>xx</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td>
<p align=center><b>DropDownList Control:
MyDropDownList2</b></p>
</td>
</tr>
<tr>
<td>
<p align=center><asp:dropdownlist
id="MyDropDownList2"
runat="server">
</asp:dropdownlist></p>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td>
<p align=center><b>RadioButtonList Control:
MyRadioButtonList</b></p>
</td>
</tr>
<tr>
<td>
<p align=center>
<asp:RadioButtonList id="MyRadioButtonList"
runat="server">
</asp:RadioButtonList>
</p>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td>
<font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td>
<p align=center><b>DataGrid Control:
MyDataGrid</b></p>
</td>
</tr>
<tr>
<td>
<p align=center>
<asp:datagrid id="MyDataGrid"
autogeneratecolumns="False"
runat="server">
<columns>
<asp:boundcolumn headertext="Key"
datafield="Key">
</asp:boundcolumn>
<asp:boundcolumn headertext="Value"
datafield="Value" dataformatstring="{0:C}">
</asp:boundcolumn>
</columns>
</asp:datagrid></p>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td>
<p align=center><b>DataList Control:
MyDataList</b></p>
</td>
</tr>
<tr>
<td>
<p align=center>
<asp:datalist id="MyDataList" runat="server">
<itemtemplate>
<%# DataBinder.Eval(Container.DataItem, "Key") %>
<%# DataBinder.Eval(Container.DataItem, "Value", "{0:C}") %>
</itemtemplate>
</asp:datalist></p>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td><font color=#ffffff>x</font>
</td>
</tr>
<tr>
<td>
<p align=left><font face="Tahoma" size="2">Author: Pete
Ehli</font></p>
</td>
</tr>
</table>
</p>
<script language="C#" runat="server">
private void Page_Load()
{
//Create a HashTable
Hashtable MyHashTable = new Hashtable(5);
//Populate MyHashTable with key and value data
MyHashTable.Add("Turbo C#", 39.99);
MyHashTable.Add("C# Programming 101", 29.49);
MyHashTable.Add("DOS Basics Training", 30.00);
MyHashTable.Add("C# Patterns with ASP.NET", 49.49);
MyHashTable.Add("ADO.NET in Action", 35.99);
MyHashTable.Add("Intermediate ASP.NET", 69.99);
//Define the DataSource for the control
MyDropDownList1.DataSource = MyHashTable;
//Tell the control where to find our data
MyDropDownList1.DataValueField ="Key";
//Tell the control what data to display
MyDropDownList1.DataTextField = "Key";
//Define the DataSource for the control
MyDropDownList2.DataSource = MyHashTable;
//Tell the control where to find our data
MyDropDownList2.DataValueField = "Key";
//Tell the control what data to display
MyDropDownList2.DataTextField = "Value";
//Format the displayed data
MyDropDownList2.DataTextFormatString = "{0:E}";
//Define the DataSource for the control
MyRadioButtonList.DataSource = MyHashTable;
//Tell the control where to find our data
MyRadioButtonList.DataValueField = "Key";
//Tell the control what data to display
MyRadioButtonList.DataTextField = "Value";
//Format the displayed data
MyRadioButtonList.DataTextFormatString = "Current Book Price {0:C}";
//Define the DataSource for the control
MyDataGrid.DataSource = MyHashTable;
//Define the DataSource for the control
MyDataList.DataSource = MyHashTable;
//Bind all controls on the page
Page.DataBind();
}
</script>
</form>
</body>
</html>
In the 'DataReader Binding Example' below, we use only a DataGrid control
to show data binding to a DataReader. Using a DataReader is the
preferred choice for data binding using a collection, but this of course
depends on what you are tring to accomplish with your list controls. Using
a DataReader is a Forward only, Read only means by which to access our
data, so we can use it only once to literally suck our data out of our
database, and then populate our DataGrid control. A DataReader is a very
efficient means by which to access our data so we have very little overhead
using one unlike a DataSet. For this and the DataSet example we are uing
the Northwind SQL Server database which resides in the MSDE
(Microsoft SQL Server Desktop Engine) included in the .Net Framework
SDK samples. We also have included a "striped out" Web.config file which
you should place in the same directory with this example in your IIS web
server. The Web.config file included here is pretty bare, and is used
only for example purposes, but will function fine as is to run our example.
If you look at the Web.config file, you will notice the name of
the MSDE instance is 'NetSDK' - to access the database, use the server
name: (local)\NetSDK. If your machine's name is MyMachine then
your MSDE sever name is MyMachine\NetSDK, but using this name will not
work to connect to the MSDE server. You must use (local)\NetSDK
to be able to connect to your MSDE server and access the included Northwind
database. In this example we are binding to just the control itself. Since
this is an article about data binding, not data access, we will not go
into great detail about how data access is done here. The script in the
examples is well commented so that should give you a good idea about what
is going on as far as performing our data access to bind to our DataGrid
control.
DataReader Binding Example
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<%@ Import Namespace="System.Configuration" %>
<!doctype html public "-//w3c//dtd html 4.0 transitional//en" >
<html>
<head>
<title>DataReader Binding</title>
</head>
<body >
<form runat="server">
<p align=center><b><font size="5">DataReader Binding</font></b></p>
<p align=center> </p>
<p align=center><b>DataGrid Control: MyDataGrid</b></p>
<p align=center><asp:datagrid id="MyDataGrid" runat="server">
</asp:datagrid><br></p>
</form>
<script language="C#" runat="server">
private void Page_Load(object sender, System.EventArgs e)
{
//Create a variable to hold the connection object
SqlConnection MySqlConn = null;
try
{
//Assign a connection string from the Web.config file
string MySqlConnString = (string)
ConfigurationSettings.AppSettings["SqlConnString"];
//Create a connection object
MySqlConn = new SqlConnection(MySqlConnString);
//Open the connection
MySqlConn.Open();
//Build the string Select statement
string Select = "SELECT * FROM Orders, Customers " +
"WHERE Orders.CustomerID = Customers.CustomerID and ShipVia = 1";
//Create a command object
SqlCommand SqlCmd = new SqlCommand(Select, MySqlConn);
//Define a DataReader object using our
//command object's ExecuteReader method
SqlDataReader MyDataReader = SqlCmd.ExecuteReader();
//Tell our DataGrid what it's data source is
MyDataGrid.DataSource = MyDataReader;
//Bind our DataGrid to the specified data source
MyDataGrid.DataBind();
}
catch(Exception ex)
{
throw ex;
}
finally
{
if(MySqlConn.State == ConnectionState.Open)
{
MySqlConn.Close();
}
}
}
</script>
<p align=left><font face="Tahoma" size="2">Author: Pete
Ehli</font>
</body>
</html>
Web.config File for the "DataReader Binding Example"
<configuration>
<appSettings>
<add key="SqlConnString" value="server=(local)\NetSDK;
uid=QSUser;pwd=QSPassword;database=Northwind"
/>
</appSettings>
<system.web>
</system.web>
</configuration>
In the 'DataSet Binding Example' below, data binding is shown binding
two DataGrids to one DataSet. We are using the System.Data.OleDb
namespace as our means of data access to the same database, Northwind
(see the above DataReader example). By using the System.Data.OleDb
namespace we can access different databases such as Microsoft Access,
Oracle and so on, but you would just need to change the connection string
in the Web.config file included below this example. Again since
this is an article about data binding, not data access, we will not go
into great detail about how data access is done here. The script in the
examples is well commented so that should give you a good idea about what
is going on as far performing our data access to bind to our controls.
Again, you need to place the Web.cofig file included below in the same
directory you place the example in your IIS web server. What needs to
be noted here is we are creating a DataSet that contains two tables that
have a defined one-to-many relationship within the DataSet, that is one
Order to many Order Details. This is what is referred as a Master Detail.
MyDataGrid1 is the Master and MyDataGrid2 is the Detail. The tables that
reside in our DataSet are significantly smaller due to the data we pull
out of the Northwind database, using our SQL Select statements with the
SQL comparison key word 'LIKE'. At the end of the script block we bind
one DataGrid to one table in our DataSet. DataSets are disconnected objects
where we can define simple to complex DataTable relationships, where we
could add, change, or delete data contained in our DataSet, and then reflect
these changes in our database.
DataSet Binding Example
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDb" %>
<%@ Import Namespace="System.Configuration" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<html>
<head>
<TITLE>DataSet Binding</TITLE>
</head>
<body>
<form runat="server">
<p align=center><b><font size=5>DataSet Binding</font></b></p>
<p align=center><b><font size=5></font></b> </p>
<p align=center>DataGrid Control: MyDataGrid<b><font
size=5></font></b></p>
<p align=center><asp:datagrid id=MyDataGrid1 runat="server"></asp:datagrid><br></p>
<p align=center><asp:datagrid id=MyDataGrid2 runat="server"></asp:datagrid><br></p>
</form>
<script language="C#" runat="server">
private void Page_Load(object sender, System.EventArgs e)
{
//Create a string for comparison reasons
string TheOrderID = "1025%";
 //Build the string select statements
string Orders = "SELECT * FROM Orders WHERE " +
OrderID LIKE'" + TheOrderID + "'";
string OrderDetails = "SELECT * FROM [Order Details] WHERE " + "OrderID LIKE'" + TheOrderID + "'";
//Create a new DataSet object
DataSet MyDataSet = new DataSet();
//Assign a connection string from the Web.config file
string MyOleConnString = (string)
ConfigurationSettings.AppSettings["OleConnString"];
//Create our connection object
OleDbConnection MyOleDbConn = new OleDbConnection(MyOleConnString);
//Create our command object
OleDbCommand MyOleDbCmd = new OleDbCommand();
//Set the command object properties
MyOleDbCmd.Connection = MyOleDbConn;
MyOleDbCmd.CommandType = CommandType.Text;
MyOleDbCmd.CommandText = Orders;
//Create our adapter oject
OleDbDataAdapter MyOleDataAdapter = new OleDbDataAdapter();
//Set the SelectCommand property using or command object
MyOleDataAdapter.SelectCommand = MyOleDbCmd;
//Get the data from the "Orders" table in the database and
//put it into a table named "MyOrders" into the MyDataSet object
MyOleDataAdapter.Fill(MyDataSet, "MyOrders");
//Reassign the command oject CommandText property
MyOleDbCmd.CommandText = OrderDetails;
//Get the data from the "Order Details" table in the database and
//put it into a table named "MyOrderDetails"
//into the MyDataSet object
MyOleDataAdapter.Fill(MyDataSet, "MyOrderDetails");
//Create a relation in the DataSet object named MyDataSetRelation
DataRelation MyRelation = new DataRelation("MyDataSetRelation",
MyDataSet.Tables["MyOrders"].Columns["OrderID"],
MyDataSet.Tables["MyOrderDetails"].Columns["OrderID"]);
//Add the relation to the MyDataSet object
MyDataSet.Relations.Add(MyRelation);
//Specify to the DataGrids what their data source is
MyDataGrid1.DataSource = MyDataSet;
MyDataGrid2.DataSource = MyDataSet;
//Tell the DataGrids to set their DataMember
//propety to the the table named in the DataSet object
MyDataGrid1.DataMember = "MyOrders";
MyDataGrid2.DataMember = "MyOrderDetails";
//Bind our DataGrids to their specified data source
MyDataGrid1.DataBind();
MyDataGrid2.DataBind();
}
</script>
<p align=left><font face="Tahoma" size="2">Author: Pete
Ehli</font>
</body>
</html>
Web.config for the "DataSet Binding Example"
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!--modify connection string for your server -->
<add key="OleConnString" value="provider=SQLOLEDB.1;
data source=(local)\NetSDK;initial catalog=Northwind;
uid=QSUser;pwd=QSPassword" />
</appSettings>
<system.web>
</system.web>
</configuration>
In conclusion, repeated data binding in ASP.NET using list controls can
be much more complicated and robust than what has been shown here. However,
you should now have a good understanding and firm grounding on how repeated
binding takes place, and what methods and data sources are available for
you to implement repeated binding in your ASP.NET list controls.
Pete Ehli holds an Associate of Applied Science degree in Computer
Information Systems. Having a firm foundation in Java, he has decided
to transfer his skills to C#, and has been working with Visual Studio.NET
since late Beta 1. He is Vice President of the Portland Area .NET User
Group (PADNUG) http://www.3leaf.com/padnug/.
Besides having a passion for the C# language, Pete is an avid weightlifter,
bodybuilder, and health nut. He can be reached at csharpexpert@hotmail.com. |