GridView DataBinding Events

Share on Twitter

This is a well commented example for a GridView with implementation of RowDataBound and DataBound events. I also demonstrate in it some of the important properties of GridView, like the slight diffrences when dealing with Grid Paging, Rows, Cells, and Columns. I prefered to heavily comment the code than to write separate paragraphs describing it as I do believe that the code is what gets the idea in a direct way.

The example is a simple page that uses SqlDataSource to connect to a SQL Server 2005 Express database and show the results on a GridView with paging capapility. Many parts of the code don’t show the best practices for their situation and those are only included for demonstration purpose as they are not the main focus of the example.

I’ll start with the code behind of the page as it’s the most important part:


/******************************************************************
 * The sample is provided AS IS without any warranty
 * All rights reserved (C) 2005, Mohamed Meligy
 * http://weblogs.asp.net/meligy
 * All rights reserved (C) 2010, Mohamed Meligy
 * http://gurustop.net
 * Distribution of this code without this note is prohibited.
 ******************************************************************/
//Default "using" set of a new System.Web.UI.Page Visual Studio 2005 template:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
/// <summary>
/// To test the GridView behavior in action,
/// you need to have SQL Server Express installed (comes by default with VS2005),
/// and Northwind database attached to it
/// (attaches by default when you select "Quickstart Tutorials"
/// from the .NET Framework 2.0 SDK Programs menu, and choose to install them).
/// Alternatively, change the ConnectionString property of the SqlDataSource
/// to point to another installed instance
/// of SqlServer 2000 or SqlServer 2005 that has Northwind database attached.
/// </summary>
public partial class GridViewSampler1 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //Limiting redundancy of useless execution.
        //You do no need to check IsCallback if you
        // don't have controls with Callback Enabled.
        if (!IsPostBack & !IsCallback)
        {
            //This makes performing paging and sorting uses AJAX.
            GridView1.EnableSortingAndPagingCallbacks = true;
            //Small number so that I can see many oages out of
            // 9 rows only (Yhe total Rows Count of Northwind's Employees DataTable).
            //Also selected it in a way that last Page Rows Count will be
            // different than other pages.
            GridView1.PageSize = 2;
            if (!IsPostBack)   //Just to prove the AJAX thing.
            {
                PostBackStatus.Text = "Not PostBack";
            }
            else   //Never happens, as I don't require a PostBack.
            {
                PostBackStatus.Text = "Page Is PostBack";
            }
        }
    }
    /// <summary>
    /// Executes when the databinding is complete
    /// </summary>
    protected void GridView1_DataBound(object sender, EventArgs e)
    {
        //I'll use it to show which set of Rows I'm showing in the page.
        GridView1.ShowFooter = true;
        //Similar to: GridView1.FooterRow.Visible = true
        //Stretching the first cell to fill the whole FooterRow:
        //Removing all non needed cells,
        // from the end to start
        // (so that the Cells collection is not recreated with every Removal).
        for (int cellNum = GridView1.Columns.Count - 1; cellNum > 0; cellNum--)
        {
            GridView1.FooterRow.Cells.RemoveAt(cellNum);
        }
        GridView1.FooterRow.Cells[0].ColumnSpan = GridView1.Columns.Count;
        GridView1.FooterRow.Cells[0].HorizontalAlign = HorizontalAlign.Center;
        int startIndex = GridView1.PageIndex != GridView1.PageCount - 1 ?
        //Not in last page.
        GridView1.PageSize * GridView1.PageIndex
        //GridView1 Rows Count is Count of the Rows of the current page, so,
            // unless Paging is Disabled, this is not total Rows Count.
            //gridViewTotalCount is declared and assigned just after this method.
        : gridViewTotalCount - GridView1.PageSize + GridView1.Rows.Count;
        GridView1.FooterRow.Cells[0].Text =
            string.Format
                ("Showing Employees {0} to {1} of {2}",
                startIndex + 1,
                startIndex + GridView1.Rows.Count, gridViewTotalCount);
    }
    TableCell myCell = null;
    protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        //I'll add that to every Row bound in the GridView.
        myCell = new TableCell();
        //Note that for the header, footer, and separator rows, DataItemIndex is -1
        myCell.Text = e.Row.DataItemIndex.ToString();
        //Note that when you add the cell,
        // this does NOT increase the GridView Columns Count.
        e.Row.Cells.Add(myCell);
        //The past lines will affect also HeaderRow, FooterRow, and even Pager,
        // you'll see when you run that this is not a desired behavior.
        //You can limit your code on condition. This is the recommended way.
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            //Do your UI logic now for data binding,
            // much similar to DataGrid ItemDataBound.
            //Example: changing color of text
            // for normal and alternative rows ONLY by code.
            if (e.Row.RowIndex % 2 == 0)
            {
                e.Row.Style["color"] = "#0000ff";
            }
            else
            {
                e.Row.Style["color"] = "#00bb00";
            }
            //This is the EmployeeID Cell
            e.Row.Cells[0].Text =
                "I'm alternative employee with code: " + e.Row.Cells[0].Text;
            //Another sample change making use of the DataItem:
            // This is specific to our case where the GridView is bound to
            // first DataTable in the DataSet returnd by the EmployeesSqlSource.
            // This is when SqlDataSource DataSourceMode = DataSet (Default)
            DataRowView rowView = (DataRowView)e.Row.DataItem;
            e.Row.Cells[GridView1.Columns.Count - 1].Text =
                int.Parse(rowView["Extension"] as string).ToString("###-##");
        }
    }
    int gridViewTotalCount;
    protected void EmployeesSqlSource_Selected
        (object sender, SqlDataSourceStatusEventArgs e)
    {
        //GridView has no way of telling total Rows Count when paging is enabled.
        gridViewTotalCount = e.AffectedRows;
    }
}

Now to the page XHTML source:


<%@ Page Language="C#" AutoEventWireup="true" 
    CodeBehind="GridViewSampler1.aspx.cs"
 Inherits="GridViewSampler1"
    %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="PageHeader" runat="server">
    <title>GridView Sample</title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
        Postback Status:
            <asp:Label ID="PostBackStatus" runat="server"></asp:Label>
            <asp:GridView ID="GridView1" runat="server"
                AutoGenerateColumns="False" AllowPaging="True"
                DataSourceID="EmployeesSqlSource" DataKeyNames="EmployeeID"
                OnDataBound="GridView1_DataBound"
                OnRowDataBound="GridView1_RowDataBound">
                <Columns>
                    <asp:BoundField DataField="EmployeeID"
                        HeaderText="EmployeeID" InsertVisible="False"
                        ReadOnly="True" SortExpression="EmployeeID" />
                    <asp:BoundField DataField="LastName"
                        HeaderText="LastName" SortExpression="LastName" />
                    <asp:BoundField DataField="FirstName"
                        HeaderText="FirstName" SortExpression="FirstName" />
                    <asp:BoundField DataField="Title"
                        HeaderText="Title" SortExpression="Title" />
                    <asp:BoundField DataField="BirthDate"
                        HeaderText="BirthDate" SortExpression="BirthDate" />
                    <asp:BoundField DataField="PostalCode"
                        HeaderText="PostalCode" SortExpression="PostalCode" />
                    <asp:BoundField DataField="Extension"
                        HeaderText="Extension" SortExpression="Extension" />
                </Columns>
                <EmptyDataTemplate>
                    <div style="text-align: center">
                        No Data Available.
                    </div>
                </EmptyDataTemplate>
            </asp:GridView>
            <asp:SqlDataSource ID="EmployeesSqlSource" runat="server"
                ConnectionString=
"Data Source=MELIGYSQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True"
                ProviderName="System.Data.SqlClient"
                SelectCommand=
"SELECT [EmployeeID], [LastName], [FirstName], [Title], [BirthDate], [PostalCode], [Extension] FROM [Employees]"
                OnSelected="EmployeesSqlSource_Selected"></asp:SqlDataSource>
        </div>
    </form>
</body>
</html>

 

Samples of the output of the code:

Hope that you like it.

Share on Twitter

Related posts:

  1. Unit Test Friendly File Upload Handling in N-Tier Applications
    The Problem In an N-tier application, you keep your logic...
  2. ASP.NET 2.0 Themes: Learn how to use them today!
    Note: This is ported from my old weblog. Originally published...
  3. Prevent ASP.NET Validators from Massively Increasing Page Size
    This is problematic with ASP.NET AJAX. The main Script Components...
, , , ,
  • http://www.amrelsehemy.net Amr Elsehemy

    Congrats on the new blog, so are you giving up the geeks with blogs one?

  • http://GeeksWithBlogs.NET/Mohamed Mohamed Ahmed Meligy

    I’m using cross posting right now until I settle on something! I’m worried that this blog might be more restricted in topics than GWB. I talked to the owners of both, and still not having a final decision yet!!

  • http://www.amrelsehemy.net Amr Elsehemy

    Wishing you the best,
    I subscribed for both now so keep the good posts coming.

  • http://weblogs.asp.net/meligy Mohamed Ahmed Meligy

    It’s easy, Amr :). Thanks to feedburner!

    You can subscribe to http://feeds.feedburner.com/GuruStop
    This feed now points to my old blog, but, everything I’ll post here is automatically cross posted there. Eventually, I’ll make it loaded from this new blog. I’ll do after I reach twenty-something posts, God Willing.
    So, just subscribe to that, and you’ll not even realize the change when it takes place – I hope.

    thank you for caring anyway.

  • http://

    It’t cool, but what if I use database paging and the ObjectDatasource. When I test this situation, the result is that the e.AffectedRows equal -1 in the ObjectDataSource’s OnSelected event handle.
    the Selecting method is List GetMessages(),and the SQL for selecting is:
    SELECT * FROM (SELECT MessageID,[From],Subject,CreatedDate,IsRead,IsReply,ReturnReceipt,FolderID,ROW_NUMBER() OVER ( ORDER BY CreatedDate DESC) AS RowNum FROM Mail_MailMessages WHERE FolderID=@FolderID )Messages
    WHERE Messages.RowNum BETWEEN (@PageIndex*@PageSize+1) AND ((@PageIndex+1)*@PageSize) ORDER BY CreatedDate

  • http://

    how would you place two table data in one gridview
    sharmab07@gmail.com

  • http://

    really its good ………………………………..

  • http://

    Hi! It was really awesome as I’m a beginner to .Net but I could easily understand the GridView DataBinding. Thanks once again Mohammed…

  • http://

    The article is good.

  • http://

    pls write ur code in VB.Net also.So that the readers will have both knowledge as well as persons who dnt any one can get knowledge abt the code which they require.

  • http://permoon_h2000@yahoo.com mahtab

    hello.

    thank you for this article.I dont know in vs2008 instead of ItemDataBound Ican use which one of Event??you know in visual studio 2008 we dont have ItemDataBound.

    I ask you Please help me.

  • http://

    yutr

  • Foo

    You forgot to actually include an example of the actual DataBinding event. Article should have been titled what to do after the data is bound.