Tuesday, May 15, 2012

ASP.NET GridView Row Edit mode

It's great to have CRUD operations in a single place and ASP.NET GridView provides this feature in a nice way. Without much pre writing I will just start off with the topic.

I have a GridView in my page and I have named it "GridViewUsers". First I will load values to a DataSet and Bind my GridView's Data Source to that DataSet in Page Load event. Please note that in here I will be writing only the necessary codes.
using System;
using System.Web.UI.WebControls;
using System.Data;

dbConnection odbConnection = new dbConnection(); // calling my dbConnection class

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        DataSet ds = GetAllUsers();
        gridViewUsers.DataSource = ds;
        gridViewUsers.DataBind();
    }
}

private DataSet GetAllUsers()
{
    DataSet ds = new DataSet();
    try
    {
        string selectQuery = "SELECT USER_ID,FIRST_NAME,LAST_NAME,GENDER From USERS";
        ds = odbConnection.ExecuteSelectQuery(selectQuery);
    }

    catch (Exception ex)
    {
        throw ex;
    }
    return ds;
}
Now I will  modify some properties in the GridView from the aspx file.
<asp:GridView ID="GridViewUsers" runat="server"
     AutoGenerateColumns="False"
     GridLines="None"
     AllowPaging="True">
</asp:GridView>
I have put,
AutoGenerateColumns="False"
here, because I need to write column names I want to show in the GridView. If I put,
AutoGenerateColumns="True"
I don't need to write any custom code and all the columns I have selected in my query will be appeared as it is in my GridView. Ok, Now what my target is, I will have some rows in my GridView and initially it will be read only. And in each each row, there will be a single column which will be used to modify the selected row. It will have a single button in read only mode which is "Edit", And when I click on Edit, the row will change into Edit mode. The editable fields of the row will change into edit mode and the "Edit" button will disappear. Instead of  "Edit" button, three more buttons will come to the picture which will be "Update","Delete" and "Cancel".

I hope you all got the target well, let's start achieving it.

So basically we will have two modes and some custom controls. In GridView, to define custom controls with other columns we are using "TemplateField" which is like a place holder. Under "TemplateField", I will have two properties which are "ItemTemplate" and "EditItemTemplate". "ItemTemplate" property is used to control the appearance of a data item and "EditItemTemplate" property is used to control the appearance of a data item in Edit mode. So here is my complete code for the GridView.
<asp:GridView ID="gridViewUsers" runat="server"
     AutoGenerateColumns="False"
     AllowPaging="True" Height="134px" Width="536px" 
     onrowediting="gridViewUsers_RowEditing"
     onrowcancelingedit="gridViewUsers_RowCancelingEdit"
     onrowdeleting="gridViewUsers_RowDeleting"
     onrowupdating="gridViewUsers_RowUpdating">

     <Columns>
          <asp:TemplateField HeaderText="User ID">
               <ItemTemplate>
                    <asp:Label runat="server" ID="lblUserID" Text='<%# Eval("USER_ID") %>' />
               </ItemTemplate>
          </asp:TemplateField>

          <asp:TemplateField HeaderText="First Name" >
               <ItemTemplate>
                    <asp:Label ID="lblFirstName" runat="server" Text='<%# Eval("FIRST_NAME") %>' />
               </ItemTemplate>
               <EditItemTemplate>
                    <asp:TextBox ID="txtFirstName" runat="server" Text='<%# Eval("FIRST_NAME") %>' />
               </EditItemTemplate>
          </asp:TemplateField>

          <asp:TemplateField HeaderText="Last Name" >
               <ItemTemplate>
                    <asp:Label ID="lblLastName" runat="server" Text='<%# Eval("LAST_NAME") %>' />
               </ItemTemplate>
               <EditItemTemplate>
                    <asp:TextBox ID="txtLastName" runat="server" Text='<%# Eval("LAST_NAME") %>' />
               </EditItemTemplate>
          </asp:TemplateField>

          <asp:TemplateField HeaderText="Action">
               <ItemTemplate>
                    <asp:ImageButton ID="btnEdit" runat="server" Text="Edit" CommandName="Edit" ImageUrl="~/images/iconEdit.png" ToolTip="Edit" AutoPostBack="true" />
               </ItemTemplate>
               <EditItemTemplate>
                    <asp:ImageButton ID="btnUpdate" runat="server" Text="Update" CommandName="Update" ImageUrl="~/images/iconUpdate.png" ToolTip="Update" AutoPostBack="true" />
                    <asp:ImageButton ID="btnDelete" runat="server" Text="Delete" CommandName="Delete" ImageUrl="~/images/iconDelete.png" ToolTip="Delete" AutoPostBack="true" />
                    <asp:ImageButton ID="btnCancel" runat="server" Text="Cancel" CommandName="Cancel" ImageUrl="~/images/iconCancel.png" ToolTip="Cancel" AutoPostBack="true" />
               </EditItemTemplate>
          </asp:TemplateField>
     </Columns>
</asp:GridView>
So here what I have done is, UserID is the primary key. So in it there is no Edit mode. For all other columns there is a "EdiItemTemplate". And in "ItemTemplate", I have used a Label to display the value. Because it is read only. And in "EdiItemTemplate", I have used a TextBox to display value, because it should be editable. In here last "TemplateField" is the column which will contain controls for modifying the row. In "ItemTemplate", it will contain a single button which will trigger GridView EDIT command and in "EdiItemTemplate", it will contain three buttons which will trigger GridView UPDATE, DELETE and CANCEL commands. I have used image buttons here to make the UI bit nicer.

Now here is my code behind code file. First it is gridViewUsers_RowEditing event.
protected void gridViewUsers_RowEditing(object sender, GridViewEditEventArgs e)
{
    gridViewUsers.EditIndex = e.NewEditIndex;
    BindGrid();
}
In here GridViewEditEventArgs will give the row number I am editing by it's NewEditIndex property. Then I am assigning that row number to GridView's EditIndex property which will put the appropriate row into the Edit Mode. Then I am calling my custom method which I am going to write in few minutes and it will bind the GridView again.
Then it's gridViewUsers_RowUpdating event and gridViewUsers_RowDeleting event.
protected void gridViewUsers_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    Label userID = (Label)gridViewUsers.Rows[e.RowIndex].FindControl("lblUserID");
    TextBox txtFirstName = (TextBox)gridViewUsers.Rows[e.RowIndex].FindControl("txtFirstName");
    TextBox txtLastName = (TextBox)gridViewUsers.Rows[e.RowIndex].FindControl("txtLastName");
        
    string updateQuery = "update query";

    gridViewUsers.EditIndex = -1;
    BindGrid("UPDATE", updateQuery);
}
protected void gridViewUsers_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
    Label UserID = (Label)gridViewUsers.Rows[e.RowIndex].FindControl("lblUserID");
    string deleteQuery = "delete query";

    gridViewUsers.EditIndex = -1;
    BindGrid("DELETE", deleteQuery);
}
In these two events, first line is to get the primary key's value of the current row item being modified.
protected void gridViewUsers_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
    gridViewUsers.EditIndex = -1;
    BindGrid();
}
Then my BindGrid method. I have two optional parameters here which will get query type and the query. If the query type is "UPDATE" or "DELETE", it will execute the query and in the finally block it will bind the GridView.
private void BindGrid(string queryType = "default", string query = "default")
{
    DataSet ds = null;

    try
    {
        if (queryType == "UPDATE" || queryType == "DELETE")
        {
            odbConnection.ExecQuery(query);
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    {
        string selectQuery = "SELECT USER_ID,FIRST_NAME,LAST_NAME,GENDER From USERS";

        using (ds = oDBConnection.SelectQuery(selectQuery))
        {
            gridViewUsers.DataSource = ds;
            gridViewUsers.DataBind();
        }
    }
}

So that's all about ASP.NET GridView Row Edit mode. This is what you will get at the end.

gridViewUsers

gridViewUsers Edit Mode

Happy Coding.

Regards,
Jaliya

6 comments:

  1. This is great and nicely described...!
    Good work machan :-)

    - Manulak

    ReplyDelete
  2. Nicely described .. how efficient would this be as in how long would an update take and would it work with partial post backs an all .. I am gonna test this out .. its great if u could make a dll out of it u know with custom controls .. CusCntrl:EditGrid would be a marvelous thing to have in our toolkit

    ReplyDelete
  3. Great, helped a lot! Thanks Jaliya!

    ReplyDelete