The server-side data binding techniques introduced inASP.NET
1.x revolutionized the way developers build pages that access data.
With the introduction of data-bound controls in ASP.NET 2.0, you now have a
whole range of features at your disposal that can be used for filtering,
sorting and paging, editing, and deleting data.
GridView
is one of the
important data-bound controls that automatically handles these operations as
long as the bound data source control supports these capabilities. In addition
to GridView s out-of-the-box features, you also have the option of extending
these built-in capabilities by intercepting the various events of the GridView
control. Specifically, by handling the data binding events, you can support
rich data-bound scenarios when the out-of-the-box capabilities fall short of
your requirements. This article takes a detailed look at the data binding
events supported by the GridView control and discusses the steps involved in
implementing these events. To this end, you ll see advanced examples on using
these events to create sophisticated ASP.NET Web applications.
The main reason for using data binding is to save you code
through a declarative approach. For example, you can use the simple data
binding features of GridView to retrieve and display data with no code at all.
Although this approach works for many simple scenarios, there are times when
you might want to extend this data binding when the simple data binding output
doesn t meet your needs. Consider the scenario wherein you want to display
embedded GridViews that display master-detail data in an ASP.NET page. To
accomplish this, you need to intercept one of the GridView data binding events
and write code to retrieve the right data to display the parent and child
GridView controls. When displaying data in the GridView, the main binding
events fire in the order shown in Figure 1. Event Name Description DataBinding Raised when the GridView control binds to a data source. RowCreated Enables you to affect the row before the GridView has
been bound to the fields. RowDataBound Enables you to affect the row after the GridView has
been bound, and evaluate the GridView that has been bound. DataBound Raised after the GridView control binds to a data source. Figure 1: When
displaying data in the GridView, the main binding events fire in this order. Note that the RowCreated and RowDataBound events fire for
each row bound to the GridView control. The rich event model allows you to
intercept the render of your view control at any point in the binding process.
For selecting objects, the RowDataBound event is useful, because you can gain
access to both the bound row and your object, which is useful for applying
formatting to your row. For adding custom content to the data rows, such as
injecting client-side script, use the RowCreated event. To demonstrate the data binding events supported by the
GridView control, consider the following scenarios wherein you expose rich data
binding capabilities: In this section, you ll see an example for creating a
parent/child report that shows all the records from the child table, organized
by parent. For the purposes of this example, consider displaying a complete
list of products organized by category in the AdventureWorks database. The
basic technique is to create a GridView for the parent table that contains an
embedded GridView for each row. These child GridView controls are inserted into
the parent GridView using a TemplateField. The only trick is that you cannot
bind the child GridView controls at the same time that you bind the parent
GridView, because the parent rows have not been created yet. Instead, you must
wait for the GridView.RowDataBound event to fire in the parent. The code
required to achieve this output is shown in Listing One. In this example, the parent GridView defines two columns,
both of which are the TemplateField type. The first column combines the category
id and category name (see Figure 2); the second contains an embedded GridView
of products, with two bound columns (see Figure 3). Figure 2: The
parent GridView defines two columns; this one combines the category id and
category name. Figure 3: The parent
GridView defines two columns; this one contains an embedded GridView of
products. Now all you need to do is create two data sources, one for
retrieving the list of categories and the other for retrieving all products in
a specified category. The first query fills the parent GridView; the second
query is called multiple times to fill the child GridView. You can bind the
first grid directly to the data source, as shown here: This part of the code is typical. The trick is to bind the
child GridView controls. If you omit this step, the child GridView controls
will not appear. To bind the child GridView controls, you must react to the
GridView.RowDataBound event, which fires every time a row is generated and
bound to the parent GridView. At this point, you can retrieve the child
GridView control from the second column and bind it to the product information
by programmatically calling the Select method of the data source. To ensure
that you show only the products in the current category, you must also retrieve
the CategoryID field for the current item and pass it as a parameter. The code
you need is shown in Figure 4; Figure 5 shows the resultant output generated. Figure 4: Retrieve
the CategoryID field for the current item and pass it as a parameter ... By default, GridView provides built-in support for single
row selection. It is also possible for you to extend the single row selection
to multiple rows using a few lines of code. However, when you select multiple
rows, it would be nice if you could change the background color of the selected
row so that you can easily identify all the selected rows. To implement this,
you need to be able to inject client-side script for each of the rows displayed
through the GridView. The right place to do this is the GridView.RowCreated
event. The complete code required to implement this solution is shown in Listing Two. The key in the code shown in Listing Two is the RowCreated
event handler, where you inject a block of code that does the job of
highlighting the rows in the GridView whenever a row is selected. To inject
this block of code, use the RegisterStartupScript method of the ClientScriptManager
object: After inserting the code, you associate that with the
JavaScript onclick event of the checkbox: If you navigate to the page in the browser, you should see
an output that is somewhat similar to the screenshot shown in Figure 6. If you select a couple of rows in the GridView, you ll see
the background color of the selected rows change to a different color, similar
to that shown in Figure 7. Although the prime purpose of a GridView is to show a set
of records, you can also add more interesting information, such as summary data,
by intercepting the RowDataBound event. The first step is to add the footer row
by setting the GridView.ShowFooter property to true. This displays a shaded
footer row (which you can customize freely), but it doesn t show any data. To
take care of that task, insert the content into the GridView.FooterRow. For example, imagine you are dealing with a list of
special offers. A simple summary row could display the summary for each type of
special offer. The first step is to decide when to calculate this information.
If you are using manual binding, you could retrieve the data object and use it
to perform your calculations before binding it to the GridView. However, if you
are using declarative binding, you need another technique. You have two basic
options you can retrieve the data from the data object during the binding
operation, or you can retrieve it from the grid itself after the grid has been
bound. The following example uses the former approach because it gives you the
freedom to use the same calculation code no matter what data source was used to
populate the control. It also gives you the ability to total only the records
that are displayed on the current page, if you have enabled paging. The
disadvantage is that your code is tightly bound to the GridView, because you
need to pull out the information you want by position, using hard-coded column
index numbers. As in the previous examples, the basic strategy is to
react to the GridView.RowDataBound event. This occurs immediately after each
row in the GridView is populated with data. At this point, you calculate the
summary by retrieving the type of discount type from the current row. Once this
total is calculated, it is inserted into the footer row. Listing
Three shows the complete code. In the RowDataBound event, you check to see if the current
row is a footer row using the DataRowControlType enumeration. Figure 8 shows
the output generated by the page. This article provides a detailed discussion of the events
supported by the GridView control. You have also been introduced to the
advanced data binding capabilities of GridView, through which you can create
sophisticated Web sites. As you can see, the data binding events are very
extensible in that they provide you with hooks into the data binding lifecycle,
making it extremely easy to build sophisticated ASP.NET applications. The code accompanying
this article is available for download. Thiru Thangarathinam
is an MVP who specializes in architecting, designing, and developing
distributed enterprise-class applications using .NET-related technologies. He
is the author of Professional ASP.NET 2.0 XML
from Wrox and has co-authored a number of books in .NET-related technologies.
He has also been a frequent contributor to leading technology-related online
publications. He can be reached at mailto:[email protected]. Introduction to Data Binding
Using Embedded GridView Controls
<%# Eval("ProductSubcategoryID") %>
<%# Eval("Name") %>
void gridCategories_RowDataBound(object sender,
GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//Retrieve the GridView control in the second column
GridView gridProducts = (GridView)e.Row.Cells[1].Controls[1];
//Set the CategoryID parameter to return the products
//for the current category
string categoryID=
gridCategories.DataKeys[e.Row.DataItemIndex].Value.ToString();
productSource.SelectParameters[0].DefaultValue = categoryID ;
gridProducts.DataSource =
productSource.Select(DataSourceSelectArguments.Empty);
gridProducts.DataBind();
}
}
Figure 5: ... to show only the
products in the current category. Injecting Client-side Script
Page.ClientScript.RegisterStartupScript(this.GetType(),
"RowCreatedScript", script, true);
chkBox.Attributes.Add("onclick", "HighlightSelected(this,'" +
Convert.ToString(e.Row.RowState) + "' );") ;
Figure 6: Injecting client-side
script through the RowCreated event handler.
Figure 7: Selected rows in the
GridView change color. Displaying Summary Row Using the GridView Control
Figure 8: Output generated by using
the DataRowControlType enumeration.Conclusion
<%@ Page Language="C#" %>
End Listing One
<%@ Page Language="C#" %>
End Listing Two
<%@ Page Language="C#" %>
End Listing Three
Extend the GridView Control
Handling Data Binding Events in GridView
0 comments
Hide comments