Click here to Skip to main content
15,884,298 members
Articles / Web Development / ASP.NET
Article

GridView Event Handling

Rate me:
Please Sign up or sign in to vote.
4.77/5 (19 votes)
5 Jan 2010CPOL7 min read 144K   44   11
Article describes the handling of the common GridView events

Introduction

  • This is comprehensive article on the GridView events.
  • Operations/Events covered are: Update, delete, Insert, Paging, Sorting, RowDataBound.
  • It includes the working code and explanations.
  • This does not use the codeless method of the SqlDataSource.
  • Uses the DataSet model.
  • After any update/delete/insert the rows shall remain sorted in the selected order.
  • The result of the Update/ Delete / Insert is displayed.
  • Initially the rows shall be sorted in the default order.
  • Paging is done through normal default way, it can be made efficient by caching the dataset and using it, not going to database on each paging operation, may be in the next article I will put it in. Otherwise this will become bit complex. 
  • Code in the article uses the oops approach and the relevant part of the code can be moved to the business layer and the data layer appropriately to ease the maintenance, enhance the extensibility and scalability.  

BackGround

There are many articles on the GridView and it’s working, however they have been on the particular functionality in focus. In this article I have tried to put together most of the operations on the Grid View those are needed on regular basis. 

Using the Code

  • Components:
    • Database: It uses two tables: Product and category.
    • Product is referencing the category table.
    • The Grid – the aspx file.
    • The code behind
    • Class file.

Steps

  • Set/select the database.
  • Write the database operation methods in the class file. We call these methods from the code behind.
  • There are various events fired from the GridView we capture them in the Code Behind and use the methods defined in class file accordingly.

Note

  • ProductId is not displayed to the user, however we are using it to capture Insert/ Update and Delete internally. As it is a key we may not like to get it touched by the user.
  • While adding the records product ID is automatically generated. There may be various methods to generate it. I have used one of the simplest ways to produce it for demonstration.

Code

The ASPX:  main constituents of the ASPX code.

ASP.NET
<asp:GridView ID="grid1" runat="server" AutoGenerateColumns="false"
                    DataKeyNames="ProductId,Category"
                    OnRowDataBound="grid1_OnRowDataBound"  
                    OnRowEditing="grid1_OnRowEditing" 
                    OnRowUpdating="grid1_OnRowUpdating"  
                    OnRowDeleting="grid1_OnRowDeleting" 
                    OnRowCommand="grid1_OnRowCommand" 
                    ShowFooter="true"                                      
                    OnRowCancelingEdit="grid1_OnRowCancelingEdit" 
                    AllowSorting="true"
                    OnSorting ="grid1_OnSorting"
                    AllowPaging="true"
                    PageSize="2"
                    OnPageIndexChanging="grid1_OnPageIndexChanging"    
                    EmptyDataText="No records Selected."                   
                    > 
                  <Columns>
<asp:TemplateField HeaderText="Product Name" SortExpression="name">                       
      <ItemTemplate>
                    <asp:Label ID="label1"  runat="server" Text='<%#Bind("name") %>'>
                    </asp:Label>
                    </ItemTemplate>                   
                    <EditItemTemplate>
                        <asp:TextBox ID="txtName" runat="server" Text='<%#Eval("name") %>'>
                        </asp:TextBox>
                    </EditItemTemplate>                 
                    <FooterTemplate>
                        <asp:TextBox  ID="txtNameInput"  runat="server"></asp:TextBox>
                    </FooterTemplate>
                  </asp:TemplateField>
                  
                  <asp:TemplateField HeaderText="Product No">                    
                    <ItemTemplate>
                        <asp:Label ID="label2"   runat="server" 
                            Text='<%#Bind("ProductNumber") %>'></asp:Label>
                    </ItemTemplate>
                    <EditItemTemplate >
                        <asp:TextBox ID="txtProductNo" runat="server"
                            text='<%# Bind("ProductNumber") %>' ></asp:TextBox>             
                    </EditItemTemplate>
                    <FooterTemplate>
                        <asp:TextBox  ID="txtProductNumberInput"  runat="server">
                        </asp:TextBox>
                    </FooterTemplate>                  
                  </asp:TemplateField>
                  
                  <asp:TemplateField HeaderText="Color" SortExpression="Color">
                    <ItemTemplate>
                        <asp:Label ID="label3" runat="server" Text='<%#Eval("Color") %>'>
                        </asp:Label>
                    </ItemTemplate>
                    <EditItemTemplate>
                        <asp:TextBox ID="txtColor"  runat="server"
                            Text='<%#Bind("Color") %>'>'</asp:TextBox>
                    </EditItemTemplate>                  
                  <FooterTemplate>
                        <asp:TextBox ID="txtColorInput" runat="server"></asp:TextBox>
                    </FooterTemplate>
                  </asp:TemplateField>
                  
                  <asp:TemplateField HeaderText="Category"  SortExpression="Category">
                    <ItemTemplate>
                        <asp:Label ID="label4"  runat="server"
                            Text='<%#Eval("Category") %>'></asp:Label> 
                    </ItemTemplate>                  
                    <EditItemTemplate>
                        <asp:DropDownList ID ="ddlCategory"  runat="server"
                            DataTextField="cat_id" DataValueField="cat_id">
                        </asp:DropDownList>
                    </EditItemTemplate>
                    <FooterTemplate >
                        <asp:DropDownList ID ="ddlCategoryInput"  runat="server"
                            DataTextField="cat_id" DataValueField="cat_id">
                        </asp:DropDownList>
                        
                    </FooterTemplate>
                  </asp:TemplateField>
                  
                  <asp:TemplateField HeaderText="Cost" SortExpression="Cost">
                    <ItemTemplate>
                        <asp:Label ID="label7" runat="server" Text='<%#Eval("Cost") %>'>
                        </asp:Label>
                    </ItemTemplate>
                    <EditItemTemplate>
                        <asp:TextBox ID="txtCost"  runat="server"
                            Text='<%#Bind("Cost") %>'>'</asp:TextBox>
                    </EditItemTemplate>                  
                  <FooterTemplate>
                        <asp:TextBox ID="txtCostInput" runat="server"></asp:TextBox>
                    </FooterTemplate>
                  </asp:TemplateField>
                  
                           
                 <asp:TemplateField HeaderText="Edit" ShowHeader="false">
                    <EditItemTemplate>
                        <asp:LinkButton ID="linkButton1" runat="server"
                            CausesValidation="true" 
                            Text="Update" CommandName="update"></asp:LinkButton>
                        <asp:LinkButton ID="linkButton2" runat="server"
                            CausesValidation="false" 
                            Text="Cancel" CommandName="Cancel"></asp:LinkButton>
                    </EditItemTemplate>
                    <FooterTemplate>
                       <asp:LinkButton ID="linkButton2"  runat="server"
                            CausesValidation="false"  
                            Text="Add Record" CommandName="Add_Rec"></asp:LinkButton>      
                    </FooterTemplate>
                    <ItemTemplate>
                        <asp:LinkButton ID="linkButton1" runat="server"
                            CausesValidation="false" 
                            Text="Edit" CommandName="Edit"></asp:LinkButton>           
                    </ItemTemplate>                    
                 
                 </asp:TemplateField>                  
                 
                 <asp:CommandField HeaderText="Delete"  ShowDeleteButton="true"
                     ShowHeader="true" />
                  </Columns>
                </asp:GridView>
                <br />
                <br />
                <asp:Label ID="result" runat="server" ForeColor="Blue"></asp:Label>

The Class File

Don’t forget to add: using System.Data.SqlClient

C#
public class Product
{ 
	public Product()
	{
		//
		// TODO: Add constructor logic here
		//
	}

    public static DataTable  FetchProducts()
    {
        string StrCon = ConfigurationManager.ConnectionStrings["cs"].ConnectionString;
        SqlConnection Conn = new SqlConnection(StrCon);
        string SqlSelect = 
           "select ProductId ,Name ,ProductNumber ,Color ,Category , Cost   from products  ";
        SqlCommand cmd = new SqlCommand(SqlSelect,Conn); 
        SqlDataAdapter da = new SqlDataAdapter(cmd);
        DataSet ds = new DataSet();
        da.Fill(ds,"table1");
        return ds.Tables[0];       
    }
    

    public static DataTable FetchCategory()
    {
        string StrCon = ConfigurationManager.ConnectionStrings["cs"].ConnectionString;
        SqlConnection Conn = new SqlConnection(StrCon);
        string SqlSelect = "select Cat_Id, Cat_Desc  from Category ";
        SqlCommand Cmd = new SqlCommand(SqlSelect, Conn);
        SqlDataAdapter da = new SqlDataAdapter(Cmd);
        DataSet ds = new DataSet();
        da.Fill(ds, "table1");
        return ds.Tables[0];
    }

    public static int update(string ProductId_p,  string Name_p, string ProductNumber_p, 
        string Color_p, string Category_p, string Cost_p )
    {
        string StrCon = ConfigurationManager.ConnectionStrings["cs"].ConnectionString;
        SqlConnection Con = new SqlConnection(StrCon);
        string SqlUpd =
            "update products set Name=@Name, ProductNumber=@ProductNumber ," +
            "Color=@Color ,Category=@Category, Cost=@Cost  where ProductId=@ProductId";
        SqlCommand cmd = new SqlCommand(SqlUpd, Con);
        cmd.Parameters.Add(new SqlParameter("@Name", Name_p));
        cmd.Parameters.Add(new SqlParameter("@ProductNumber", ProductNumber_p));
        cmd.Parameters.Add(new SqlParameter("@Color", Color_p));
        cmd.Parameters.Add(new SqlParameter("@Category", Category_p));
        cmd.Parameters.Add(new SqlParameter("@Cost", Cost_p));
        cmd.Parameters.Add(new SqlParameter("@ProductId", ProductId_p));
        Con.Open();
        int upd = cmd.ExecuteNonQuery();
        Con.Close();
        return upd;       
    }

    public static int insertRow(string Name_p, string ProductNumber_p, string Color_p,
        string Category_p, string Cost_p)
    {
        string strcon = ConfigurationManager.ConnectionStrings["cs"].ConnectionString;
        SqlConnection con = new SqlConnection(strcon);
        string sqlselect = "select max(ProductId) from products";
        SqlCommand cmd = new SqlCommand(sqlselect, con);
        con.Open();
        int maxID = (int)cmd.ExecuteScalar();
        maxID++;
        string sqlInsert = "insert into products values (@ProductId,  @Name,
            @ProductNumber, @Color, @Category, @Cost )";
            cmd.CommandText = sqlInsert; 
            cmd.Connection=  con;
            cmd.Parameters.Add(new SqlParameter("@ProductId", maxID));
            cmd.Parameters.Add(new SqlParameter("@Name", Name_p));
            cmd.Parameters.Add(new SqlParameter("@ProductNumber", ProductNumber_p));
            cmd.Parameters.Add(new SqlParameter("@Color", Color_p));
            cmd.Parameters.Add(new SqlParameter("@Category", Category_p));
            cmd.Parameters.Add(new SqlParameter("@Cost", Cost_p));
        int rowInsert = cmd.ExecuteNonQuery(); 
        con.Close();
        return rowInsert;       
    }

    public static int RowDelete(string ProductId_p)
    {
        string StrCon = ConfigurationManager.ConnectionStrings["cs"].ConnectionString;
        SqlConnection Conn = new SqlConnection(StrCon);
        string sqlDelete = "delete from products where ProductId = @ProductId";
        SqlCommand cmd = new SqlCommand(sqlDelete, Conn);
        cmd.Parameters.Add(new SqlParameter("@ProductId", ProductId_p));
        Conn.Open();
        int rowdel = cmd.ExecuteNonQuery();
        Conn.Close();
        return rowdel;
    }
}

The Code Behind

C#
public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {            
            fill_grid();
        }         
    }

    public void grid1_OnRowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            DropDownList ddlCategory = (DropDownList)e.Row.FindControl("ddlCategory");
            if (ddlCategory != null)
                {
                    ddlCategory.DataSource = Product.FetchCategory();
                    ddlCategory.DataBind();
                    ddlCategory.SelectedValue =
                        grid1.DataKeys[e.Row.RowIndex].Values[1].ToString(); 
                }            
        }

        if (e.Row.RowType == DataControlRowType.Footer)
        {
            DropDownList ddlCategoryInput = (DropDownList)e.Row.FindControl(
                "ddlCategoryInput");
            ddlCategoryInput.DataSource = Product.FetchCategory();
            ddlCategoryInput.DataBind();
        }         
    }

    public void grid1_OnRowUpdating(object sender, GridViewUpdateEventArgs  e)
    {       
        TextBox txtName = (TextBox)grid1.Rows[e.RowIndex].FindControl("txtName");
        TextBox txtProductNo = (TextBox)grid1.Rows[e.RowIndex].FindControl("txtProductNo");
        TextBox txtColor = (TextBox)grid1.Rows[e.RowIndex].FindControl("txtColor");
        DropDownList ddlCategory = (DropDownList)grid1.Rows[e.RowIndex].FindControl(
            "ddlCategory");
        TextBox txtCost = (TextBox)grid1.Rows[e.RowIndex].FindControl("txtCost");
        int upd=  Product.update(grid1.DataKeys[e.RowIndex].Values[0].ToString(),
                    txtName.Text ,
                    txtProductNo.Text, 
                    txtColor.Text, 
                    ddlCategory.SelectedValue.ToString(),
                    txtCost.Text 
                    );
        grid1.EditIndex = -1;  
        fill_grid();
        result.Text = upd.ToString() + " : Row updated"; 
    }

    protected void fill_grid()
    {
        DataTable dt = Product.FetchProducts();
        if (dt.Rows.Count > 0)
        {
          DataView dv = new DataView(dt);
            if (Session["sortexp"] != null)
            {
                string srtexpr = Session["sortexp"].ToString();
                switch (srtexpr)
                {
                    case "name":
                        dv.Sort = "name";
                        break;
                    case "color":
                        dv.Sort = "color";
                        break;
                    case "Category":
                        dv.Sort = "Category";
                        break;
                    case "Cost":
                        dv.Sort = "Cost";
                        break;
                    default:
                        grid1.DataSource = dv;
                        break;
                }
            }
            grid1.DataSource = dv;
            grid1.DataBind();
        }
        else
        {         
            result.Text = " No rows Selected.";  
        }
    }

    public void grid1_OnRowEditing(object sender, GridViewEditEventArgs e)
    {
        grid1.EditIndex = e.NewEditIndex;
        fill_grid();
    }

    public void grid1_OnRowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
    {
        grid1.EditIndex= -1;
        result.Text = " "; 
        fill_grid();
    }

    public void grid1_OnRowCommand(object sender, GridViewCommandEventArgs e)
    {
        if (e.CommandName == "Add_Rec")
        {
            TextBox txtNameInput = (TextBox)grid1.FooterRow.FindControl("txtNameInput");
            TextBox txtProductNumberInput = (TextBox)grid1.FooterRow.FindControl(
                "txtProductNumberInput");
            TextBox txtColorInput = (TextBox)grid1.FooterRow.FindControl("txtColorInput");
            DropDownList ddlCategoryInput = (DropDownList)grid1.FooterRow.FindControl(
                "ddlCategoryInput");
            TextBox txtCostInput = (TextBox)grid1.FooterRow.FindControl("txtCostInput");
            int rowInsert
                = Product.insertRow( 
                                     txtNameInput.Text,
                                     txtProductNumberInput.Text,
                                     txtColorInput.Text,
                                     ddlCategoryInput.SelectedValue.ToString(),
                                     txtCostInput.Text 
                );
            fill_grid();
            result.Text = rowInsert.ToString() + " :Row was Inserted Successfully"; 
        }
    }

    public void grid1_OnRowDeleting(object sender, GridViewDeleteEventArgs e)
    {
        string product_Id = grid1.DataKeys[e.RowIndex].Values[0].ToString();
        int rowdel = Product.RowDelete(product_Id);
        result.Text = rowdel.ToString() + " : Row was Deleted.";
        fill_grid();
    }

    public void grid1_OnSorting(object sender, GridViewSortEventArgs e)
    {
        string sortexp = e.SortExpression;
        Session["sortexp"] = sortexp;
        fill_grid();
    }

    public void grid1_OnPageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        grid1.PageIndex = e.NewPageIndex;
        fill_grid();
    }
}

Event Description

  1. OnRowDataBound event function grid1_OnRowDataBound() is called:

    This event is called when the data is bound to the row. Dropdown lists are attached to the data row. If it’s the data control row then the selected option is set equal to the value in the database.  

    Here the value for the DataKeyNameCollection is used. The second value, the one we set on the DataKeyNames property of the  Gridview.

    For footer row the dropdown list attached.

  2. OnRowUpdating event function grid1_OnRowUpdating() is called:

    This event allows the capture of the update event and data update. Here the row index of the updating row is captured. Then the controls in that row and the values in them is retrieved and pass to update method in the class file.

    Note: The Key value for the database is extracted from the DataKeysCollection.

  3. OnRowEditing event function grid1_OnRowEditing() is called:

    This event is fired as soon as user clicked the edit button, then the edit index for that row is set that is equal to the row index of the updating row. This value is returned by the event arguments.

  4. OnRowCancelingEdit event function grid1_OnRowCancelingEdit() is called:

    This event is fired when the user cancels the row update. Here the selection of the row for editing is removed.

  5. OnRowCommand event function grid1_OnRowCommand() is called:

    This event is fired when the user clicks the ‘Add Record’ button, the command fired is ‘Add_Rec’ as it is defiend in Grid, see the  footer row. The name is captured from the event arguments. Ihe control in the footer row are located and their valus is extracted and sent for insert function.

  6. OnRowDeleting event function grid1_OnRowDeleting() is called:

    This function is called when the record is deleted, the key for the record is fetched from the datakey collection and passed to the delete function.

  7. OnSorting event function grid1_OnSorting() is called:

    This event is fired when the sort button is clicked by the user. The sort expression is retrieved from the event arguments and put in the session so that they are retrieved in the fill_grid() method and used for sorting.

  8. OnPageIndexChanging event function grid1_OnPageIndexChanging() is called:

    This function is called when user clicks different page number than current page number. The grid’s page index is set to this new page number. While loading grid automatically displayes the requested page.

    Whenever user clicks the different page number the whole set of data is retrieved from the database and loaded into the grid. Suppose the complete requested data is 1000 records and the grid page size is 10 records, then only 10 records will be displayed to the user while rest of the records are of no use as because if user clicks the different page number again, whole 1000 records shall be fetched again. This process is not very efficient. However, it is the default working of the paging operation. There are many ways to improve this process which may require another big article which will overshadow the purpose of this article so simple default operation is used here.

  9. Page_Load() this is the first significant event for the user after which he is able to see the page ready for his action. Here we are calling the fill_grid() method.

Fill_Grid(): A small trick is implemented in this function, common operation of getting the DataTable from the database is implemented. Besides that we are checking the sort order of the grid if it is present in the Session directory. If it is not then no sorting order is used, however if the sort order is present then it is used. If new sorting order is selected then that is saved in the session, (check the grid1_OnSorting() function) and is retrieved and used while filling the grid every time. This way the sort order is preserved for the session, and will be the selected sort order even after insert/update/delete operations.

Also in case there is no data returned then grid will not be displayed in this scenario we can use the lable to tell the user about it. However, it is the easiest way out but some logic can be added to allow user to enter data if appropriate, there are many ways to do it those may be business need dpendent and specific to each requirements and are not covered in this article.  

Methods used in the class file:

I am using the functions to be static so that the instantiation of the class is not required, we can call the function by the the class_name.function_name() convention.

  1. FetchProducts(): It simply retrives the data from the dabase into the datatable and retunrs this datatable to caller. 
  2. FetchCategory(): It simply returns the whole category file data into the datatable and returns this datatable to the caller.
  3. Update(): It updates the record, it gets all the field values from the calling function as parameters. These values are inserted  into the command with the help of SqlParameters. ExecuteNonQuery() is used and the number of affacted rows are returned to the calling function. 
  4. InsertRow(): It adds a new record in database. It gets all the field values from the calling function as parameters.These values are inserted  into the command with the help of SqlParameters. ExecuteNonQuery() is used and the number of affacted rows are returned to the calling function.
  5. RowDelete(): It deletes the desired row from the database. The key value is received through the parameters. With the help of SqlParameters and the ExecuteNonQuery() the record is deleted and affacted rows are returned to the calling function.

Interest

  1. Sorting order is maintained while doing operations – add/ update/ delete.
  2. The paging in the GridView is interesting to work upon to increase the process efficiency.

History

No updates so far

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionWhich event triggered when Items in combo is selected? Pin
sunpop29-Nov-13 2:11
sunpop29-Nov-13 2:11 
GeneralMy vote of 5 Pin
Shivarajbk22-Jul-13 19:16
Shivarajbk22-Jul-13 19:16 
QuestionOnRowDataBound Pin
Vistriv58-Dec-11 16:47
Vistriv58-Dec-11 16:47 
GeneralMy vote of 5 Pin
mandar130521-Jul-11 23:49
mandar130521-Jul-11 23:49 
GeneralMy vote of 5 Pin
jacky4lad30-Mar-11 23:18
jacky4lad30-Mar-11 23:18 
QuestionIs it Working in different Tabs? Pin
Member 375346310-Feb-11 17:30
Member 375346310-Feb-11 17:30 
GeneralWhy don't you use default gridview behaviour Pin
Irwan Hassan18-Jan-10 15:11
Irwan Hassan18-Jan-10 15:11 
Hi, I just want to know why don't you use the automated default behaviour of the gridview for the all the method you mentioned above. I have just started to explore the ASP.NET with it's features. So from what I know that the GridView (in .NET 2.0 and above) comes with automated function that will automatically handles all the methods (Deleting, Sorting and others) as long as you have entered the GridView.DataKeys properly. It is also easy to maintain so we don't have to write extra codes.

Thanks.
GeneralRe: Why don't you use default gridview behaviour Pin
Vikas Singhal 200922-Jan-10 6:45
Vikas Singhal 200922-Jan-10 6:45 
GeneralNice, 5 from me Pin
thatraja13-Jan-10 23:25
professionalthatraja13-Jan-10 23:25 
GeneralNice Article Pin
João Rollo de Sá12-Jan-10 6:09
João Rollo de Sá12-Jan-10 6:09 
GeneralGood article Pin
rctaubert12-Jan-10 3:13
rctaubert12-Jan-10 3:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.