C# – Postback resets the selectedValue of DropdownList inside GridView

asp.netcgridview

My gridview has 2 columns – DropDownList & TextBox. The DDL is databound by a datatable. The SelectedIndex Change of DDL will populate its Textbox and also add a new row. All of this works fine, but the selected values of DDLs of previous rows, reset to 0 index, when a new row is added.The textbox values remain intact though. How can I retain the DDL selected values when adding new rows.

For eg. if I select 'abc' from dropdown of row 1, it populates its text field and also adds a new row. But with the postback happening, abc does not remain selected in row 1 ddl:

  LOGIN PHONE

1       123456789

2

ASPX:

<asp:GridView ID="gvCommissions" runat="server"
 OnRowDataBound="gvCommissions_RowDataBound">
 <Columns>
  <asp:TemplateField HeaderText="LOGIN" ItemStyle-Width="29%">
   <ItemTemplate>
    <asp:DropDownList ID="ddlLogin" runat="server" Width="98%" 
     DataTextField="login" DataValueField="id"
     OnSelectedIndexChanged="ddlLogin_SelectedIndexChanged" AutoPostBack="true" >
     </asp:DropDownList>
   </ItemTemplate>
  </asp:TemplateField>
  <asp:TemplateField HeaderText="PHONE" ItemStyle-Width="12%">
   <ItemTemplate>
    <asp:TextBox ID="txtPhone" runat="server" Width="98%" 
    Text='<%# Eval("phone")%>' Enabled="false"></asp:TextBox>
   </ItemTemplate>
  </asp:TemplateField>
 </Columns>
</asp:GridView>

CODE BEHIND:

protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
         //Get values from DB, store to a datatable and then to a viewstate               
            GetAgentDetails();
         //Adds an empty row to grid                
            SetInitialRow(); 
        }            
    }

private void AddNewRow()
    {
      //Create a datatable 
      dtCurrentData = new DataTable();
      dtCurrentData.Columns.Add("phone");

//Store values of each row to a new datarow. Add all rows to datatable
      foreach (GridViewRow gvRow in gvCommissions.Rows)
        {
          DataRow drcurrentrow = dtCurrentData.NewRow();                      
          drcurrentrow["phone"] = ((TextBox)gvRow.FindControl("txtphone")).Text;
          dtCurrentData.Rows.Add(drcurrentrow);
        }

      //create an empty datarow and also add it to the new datatable.
        DataRow dr = dtCurrentData.NewRow();
        dr["phone"] = "";
        dtCurrentData.Rows.Add(dr);

     //Bind the new datatable to the grid
       gvCommissions.DataSource = dtCurrentData;
       gvCommissions.DataBind();
   }

protected void gvCommissions_RowDataBound(object sender, GridViewRowEventArgs e)
    {
     if (e.Row.RowType == DataControlRowType.DataRow)
      {
        DropDownList ddl = (DropDownList)e.Row.FindControl("ddlLogin");
        dtAgents = (DataTable)ViewState["AgentsTable"];
        ddl.DataSource = dtAgents;
        ddl.DataBind();
        ddl.Items.Insert(0, "");
      }            
    }

Best Answer

When you databind in AddNewRow, the original rows are lost. You must store the dropdown selected index, together with your textbox phone value in dtCurrentData. You can then set the index of the dropdowns in your RowDataBound event, using the values your saved in dtCurrentData.

private void AddNewRow()
{
  //Create a datatable 
  dtCurrentData = new DataTable();
  dtCurrentData.Columns.Add("phone");
  //new column for dropdown index
  dtCurrentData.Columns.Add("ddlIndex");

//Store values of each row to a new datarow. Add all rows to datatable
  foreach (GridViewRow gvRow in gvCommissions.Rows)
    {
      DataRow drcurrentrow = dtCurrentData.NewRow();                      
      drcurrentrow["phone"] = ((TextBox)gvRow.FindControl("txtphone")).Text;
      //get dropdown index
      drcurrentrow["ddlIndex"] = ((DropDownList)gvRow.FindControl("ddlLogin")).SelectedIndex;
      dtCurrentData.Rows.Add(drcurrentrow);
    }

  //create an empty datarow and also add it to the new datatable.
    DataRow dr = dtCurrentData.NewRow();
    dr["phone"] = "";
    //initial drop down index
    dr["ddlIndex"] = 0;
    dtCurrentData.Rows.Add(dr);

    //save to the viewstate like your AgentsTable
    ViewState["CurrentData"] = dtCurrentData;

 //Bind the new datatable to the grid
   gvCommissions.DataSource = dtCurrentData;
   gvCommissions.DataBind();
}

protected void gvCommissions_RowDataBound(object sender, GridViewRowEventArgs e)
{
 if (e.Row.RowType == DataControlRowType.DataRow)
  {
    DropDownList ddl = (DropDownList)e.Row.FindControl("ddlLogin");
    dtAgents = (DataTable)ViewState["AgentsTable"];
    ddl.DataSource = dtAgents;
    ddl.DataBind();
    ddl.Items.Insert(0, "");

    //get the dropdown index from CurrentData
    //use the current gridview's row index, since it matches the datatable
    if (ViewState["CurrentData"] != null)
    {
     DataTable dtCurrentData = (DataTable)ViewState["CurrentData"];
     ddl.SelectedIndex = Convert.ToInt32(dtCurrentData.Rows[e.Row.RowIndex]["ddlIndex"]);
    }

  }            
}