Introduction
The ASP.NET DataGrid control is very powerful and versatile. A dataset can be bound and displayed with almost no effort and extending the control to fit the needs of a project is very easy as we will see in this tutorial.
AutoGenerateColumns
The simplist way to use a DataGrid
is to allow the .NET library to do the work. This is easily accomplished by setting the AutoGenerateColumns
property to true and binding it to a datasource.
DataGrid1.DataSource = sqlCmd.ExecuteReader();
DataGrid1.DataBind();
The above code will assign the SqlDataReader
returned from the SqlCommand.ExecuteReader
method to the DataGrid1.DataSource
. The call to DataGrid1.DataBind()
will cause the control to iterate through the DataReader
and create the columns and populate the rows appropriately for the contents.
Bound Columns
One drawback with the AutoGenerateColumns
method is that all columns in the dataset will be displayed. If you want more control you need to use bound columns. To access the DataGrid
properties dialog, either right click on the DataGrid
on your form and choose Property Builder, or click on the ellipse button next to the columns collection in the property browser.
To add a bound column, select it the Available columns listbox then click the arrow button. Select the column in the Selected columns listbox, First Name in this case. When a new column is added it will be displayed as Bound Column in the listbox. Now you can set the propeties necessary to display the column in you DataGrid. If you want to display a name in the header for this column enter it in the Header text textbox. This will also change the name in the Selected columns listbox. Enter the field name from the dataset you wish to bind to this column in the Data Field textbox.
The Data formatting expression textbox is used to apply any formatting to the displayed data. For instance if the field is numeric and you want it displayed as a currency you would enter {0:c}
in this field. The Visible checkbox can be used to hide columns you want populated but not visible. The ordering of the columns can be changed by moving them up or down in the Selected columns listbox.
Hyperlink Columns
Hypertext Columns are used to obviously display a hypertext link in the data column. The text of the link can be configured in the Text textbox and the URL in the URL text box. As with bound columns the Text field textbox is used to set the dataset field to bind this column to. This will only set the text of the hyperlink not the URL. The URL field is used to bind the link to a dataset field. The URL format string is used to format the hyperlink if necessary.
Template Columns
To get more creative with how the DataGrid is rendered we need to use Template Columns. Any column can be changed into a Template Column by clicking the link on the DataGrid properties page. As can be seen in this code snippet the default template uses a label control for normal display and a textbox control while in edit mode.
<asp:TemplateColumn HeaderText="First Name">
<ItemTemplate>
<asp:Label runat="server"
Text='<%# DataBinder.Eval(Container, "DataItem.au_fname") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox runat="server"
Text='<%# DataBinder.Eval(Container, "DataItem.au_fname") %>' />
</EditItemTemplate>
</asp:TemplateColumn>
The Text property of these controls are set by using the DataBinder.Eval
method. This static method uses reflection to evaluate the first parameter at runtime. In this case, Container is a DataRow
from the DataReader
that is bound to the DataGrid
. The second parameter, DataItem.au_fname
, represents the column in the DataRow
. The parameters can also be written as Container.DataItem
and "au_fname
", which makes it slightly more clear.
Edit Mode
To place the DataGrid
in edit mode you need to set the EditItemIndex
property to a valid row index and rebind the DataGrid
. The DataGrid
will be rendered again but this time the EditTemplate
will be used for the indicated row.
DataGrid1.EditItemIndex = 1;
BindData();
Although the DataGrid.EditItemIndex
can be set at anytime the most user friendly way is to create a Button Column. Expanding the Button Column item in the Available columns listbox will show three predefined button columns. For our purposes add the Edit, Update, Cancel Button Column. We will leave the default values for the properties but you can change the text displayed for each by editing the appropriate textbox. The Button type combobox is used to select how the button will be displayed, either as a hyperlink or normal button.
As can be seen here the EditCommandColumn
will be added to the DataGrid
. During normal rendering the column will contain an Edit linkbutton, when in edit mode the column will contain both an update and cancel linkbutton.
<asp:EditCommandColumn ButtonType="LinkButton" UpdateText="Update"
CancelText="Cancel" EditText="Edit"></asp:EditCommandColumn>
Because these are CommandButtons
you must handle the events generated and provide any necessary processing. Events can be added from the Events view of the property browser for the DataGrid
.
In the Edit event handler the Item.DataSetIndex
can be used to set the DataGrid.EditItemIndex
. This property contains the index within the DataGrid
of the row the event was generated from.
private void OnEdit(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
DataGrid1.EditItemIndex = e.Item.DataSetIndex; BindData();
}
To cancel the edit simply set the DataGrid.EditItemIndex
to -1 and rebind the DataGrid
. In the Update event handler you can take whatever action is necessary to update your datasource.
More Creative Editing
The above method works fine if you want to use TextBoxes for the editing but what if you want the user to be able to enter values from a selected range. In this case a bit more creativity is needed. In the EditItemTemplate
, the Textbox control can be replaced with a Dropdownlist control.
<asp:dropdownlist DataSource='<%# LoadNames() %>'
DataTextField="au_fname" runat="server"></asp:dropdownlist>
As can be seen here the DataSource
property is set at runtime by a call to the LoadNames
function.
public ICollection LoadNames()
{
SqlConnection sqlNewConnection = new SqlConnection();
sqlNewConnection.ConnectionString = sqlConnection1.ConnectionString;
SqlDataAdapter da = new SqlDataAdapter("SELECT au_fname FROM authors",
sqlNewConnection);
DataSet ds = new DataSet();
da.Fill(ds);
return ds.Tables[0].DefaultView;
}
Note that a new SqlConnection
must be created to obtain the DataSet
for the DropDownList
. This is because databinding is still occurring on the DatGrid
and the SqlConnection
object is still in use at this point. The DropDownList
control is bound to an ICollection
derived object, in this case it is the DefaultView
from the first DataSet
table.
After the user has made changes and clicked the Update link, the OnUpdate
method will be called. This is where it can be determined which item was selected in the dropdownlist
. As can be seen in this code using the FindControl
method of the DataGridCommandEventArgs.Item
property will return the DropDownList
. You can then obtain the SelectedItem
text or value depending on needs.
private void OnUpdate(object source,
System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
DropDownList DropList = (DropDownList)e.Item.FindControl("dlNames");
string strTest = DropList.SelectedItem.Text;
DataGrid1.EditItemIndex = -1;
BindData();
}
Checkboxes and TextBoxes
In the case of a shopping cart type application where the user would enter a quantity or select a checkbox you need to process the DataGrid
a little differently. In this example only the ItemTemplate
will be used. Here a TextBox
has been added for the user to enter a quantity. The OnTextChanged
event must either be entered by hand, or you can create the TextBox
control outside the DataGrid
then copy it.
<asp:TemplateColumn HeaderText="Qty">
<ItemTemplate>
<asp:TextBox id="TextBox1" runat="server"
Columns="3" MaxLength="3" OnTextChanged="OnQtyChanged">
</asp:TextBox>
</ItemTemplate>
</asp:TemplateColumn>
The OnTextChange
handler is necessary because of the order events are processed when the form is submitted. When the submit button is clicked the form is posted to the server and the DataGrid
is rebound which replaces any values that had been entered into the TextBoxes
. By using the OnTextChanged
event you have the chance to catch the value entered and store it for later use. As can be seen here the DataGridItem
is obtained from the sender parameter. The TextBox
control is the second control in the first cell, the first control in the cell is a Literal Control so we skip it. In this example the Text property is converted to an int and placed in the HashTable
.
Checkboxes or other controls can be used in a similar manner.
protected void OnQtyChanged( object sender, System.EventArgs e)
{
DataGridItem Item = (DataGridItem)
(((System.Web.UI.Control)sender).NamingContainer);
TextBox txtQty = (TextBox)Item.Cells[0].Controls[1];
int nID = Item.ItemIndex;
hashQty.Add(nID, int.Parse(txtQty.Text));
}
Conclusion
It would take a complete book to cover all the features of the DataGrid
effectively but hopefully this will give you the basics necessary to begin using it in your projects. Other areas of interest are the Template styles which can give your DataGrid a distinctive look.