I have to bind a label and a drop down in a gridview,the DDL contains rundates that is datetime format i have to show all the different dates in the DDL associated with the name.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataTable dt = new DataTable();
dt = Common.rundate();
DropDownList ddl = e.Row.FindControl("DropDownList1") as DropDownList;
ddl.DataTextField = "RunDate";
ddl.DataValueField = "TempID";
ddl.DataSource = dt;
ddl.DataBind();
}
}
Store Proc::
alter PROC display_rundates
#rundate datetime,#tempid int
AS
SELECT RunDate,TempID
FROM History_Table
ORDER BY Rundate DESC
GO
But i have to show the specific rundates associated with each Name.Any help can be appreciated.
Name rundate
Test datetime(DDL)
Test1 datetime
Try this
ddl.SelectedValue = ((System.Data.DataRowView)(e.Row.DataItem)).Row["TempId"].ToString();
Basically just get "TempId" from the data item during GridView1_RowDataBound and assign that "TempId" to drop down's Selected value.
Something like this
void bindGrid()
{
grid.DataSource = getRunDates();
grid.DataBind();
}
DataTable getRunDates()
{
DataTable dt = new DataTable();
dt.Columns.Add("TempID");
dt.Columns.Add("RunDate");
dt.Rows.Add(new object[] { 1, "20-May-2012" });
dt.Rows.Add(new object[] { 2, "21-May-2012" });
dt.Rows.Add(new object[] { 3, "10-May-2012" });
dt.Rows.Add(new object[] { 4, "20-May-2012" });
return dt;
}
protected void grid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataTable dt = new DataTable();
dt = getRunDates();
DropDownList ddl = e.Row.FindControl("DropDownList1") as DropDownList;
ddl.DataTextField = "RunDate";
ddl.DataValueField = "TempID";
ddl.DataSource = dt;
ddl.DataBind();
ddl.SelectedValue = ((System.Data.DataRowView)(e.Row.DataItem)).Row["TempId"].ToString();
}
}
Design
<asp:GridView runat="server" ID="grid" OnRowDataBound="grid_RowDataBound" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField HeaderText="RunDate">
<ItemTemplate>
<asp:DropDownList runat="server" ID="DropDownList1" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="TempID" DataField="TempID" />
</Columns>
</asp:GridView>
When you bind the gridview you must also bind the primary key to some template field control,if you have not written it then add hidden field and bind to it as follow
<ItemTemplate>
<asp:HiddenField runat="server" ID="hiddenfield1" Value='<%# Eval("TempID") %>' />
<asp:DropDownList runat="server" ID="ddl" />
</ItemTemplate>
In RowDataBound Event you can findout the PrimaryKey and then use it to set the Dropdown Selected Value as follow...
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataTable dt = new DataTable();
dt = Common.rundate();
DropDownList ddl = e.Row.FindControl("DropDownList1") as DropDownList;
ddl.DataTextField = "RunDate";
ddl.DataValueField = "TempID";
ddl.DataSource = dt;
ddl.DataBind();
HiddenField hdn=(HiddenField)row.Cells[cellindex].FindControl("hiddenField1");
ddl.SelectedValue=hdn.Value;
}
}
I am still not convinced by my solution, but I think this is the way I would go about it...
When loading the data in the first time I would fill a dictionary with the run dates for each name:
private Dictionary<string, List<DateTime>> runDates = new Dictionary<string, List<DateTime>>();
private void LoadData()
{
DataTable table = new DataTable();
table.Columns.Add("TempName", typeof(string));
using (var connection = new SqlConnection("YourConnectionString"))
using (var command = new SqlCommand("SELECT DISTINCT TempName, RunDate FROM History_Table;", connection))
{
connection.Open();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
string tempName = reader.GetString(0);
if (!runDates.ContainsKey(tempName))
{
DataRow row = table.NewRow();
row[0] = tempName;
table.Rows.Add(row);
runDates.Add(tempName, new List<DateTime>());
}
runDates[tempName].Add(reader.GetDateTime(1));
}
}
GridView1.DataSource = table;
GridView1.DataBind();
}
}
When reading each row it checks if the name already exists, if it does not then it adds it to the table that will be used to bind the GridView and to the dictionary. Then in the binding event use the name label to find the list of dates from the dictionary:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//Find the label with the temp name and assign it
string tempName = (e.Row.FindControl("Label1") as Label).Value;
DropDownList ddl = e.Row.FindControl("DropDownList1") as DropDownList;
ddl.DataTextField = "RunDate";
ddl.DataValueField = "TempID";
ddl.DataSource = runDates[tempName];
ddl.DataBind();
}
}
I toyed with various other ideas, one was returning the date list as an xml field with a unique list of names (much like in your previous question), storing this in a hidden field and deserialising on the row databound event, another solution was to generate 2 tables in the data set and define relationships, but this is very similar in principle to the method I have proposed, and I think I prefer this one...
Related
I've dynamically created a dropdownlist within C# (No code in asp):
DropDownList myDDL = new DropDownList();
This can't be called from pageLoad() as it's not loaded everytime the page refreshes. However it's loaded everytime OnPostback(OnSelectedIndexChanged()) of another dll so I cant do !IsPostBack.
This dll is created when:
A value of another dropdownlist populates a GridView using OnSelectedIndexChanged()
<asp:DropDownList id ="select1" name="assignGetForm" runat="server" class="selectClass" AutoPostBack="True" OnSelectedIndexChanged="populateGridView">
On the GridView a function is run OnRowDatabound()(when the above OnIndexChanged() populates it) to populate myDDL inside the GridView
<asp:GridView id="GridView1" name="GridView1" onrowdatabound="populateCellsDDL" runat="server"></asp:GridView>
I'm now trying to access the values in myDDL using a button onclick() event - however this always does postback and refreshes the page so myDDL dissapears and when I print the value to console it just gives my first value select activity and not the one i've actually selected.
How would I get these values when they are changed as this dll is not populated on pageLoad().
I've tried looking at AJAX however i'm unsure how to look at the c# value through this. I tried aswell viewstates but i dont have luck as again it doesnt populate on pageLoad().
I think, you need to rebind the grid in each postback, if you want to access values of dynamically created controls.
I tried to simulate the situation with below sample code and I was able to access the value successfully.
ASPX code
<asp:DropDownList ID="select1" name="assignGetForm" runat="server" class="selectClass" AutoPostBack="True" />
<asp:GridView ID="GridView1" name="GridView1" OnRowDataBound="GridView1_DataBound" runat="server" />
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
C# code behind
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
FillMainDll();
if (!IsPostBack || GridView1.Rows.Count > 0)
BindGrid();
}
private void FillMainDll()
{
select1.DataSource = new int[] { 1, 2, 3 };
select1.DataBind();
}
private void BindGrid()
{
var dt = new DataTable();
dt.Columns.Add(new DataColumn("ID", typeof(Int32)));
dt.Columns.Add(new DataColumn("Name", typeof(string)));
for (int i = 1; i < 5; i++)
{
DataRow dr = dt.NewRow();
dr[0] = i;
dr[1] = "Name - " + i.ToString();
dt.Rows.Add(dr);
}
GridView1.DataSource = dt;
GridView1.DataBind();
}
protected void GridView1_DataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var myDDL = new DropDownList();
myDDL.ID = "myDDL";
myDDL.DataSource = GetGridRowDdlData();
myDDL.DataBind();
e.Row.Cells[1].Controls.Add(myDDL);
}
}
private IEnumerable<string> GetGridRowDdlData()
{
var data = new List<string>();
for (int i = 1; i < 4; i++)
{
data.Add("Name - " + i * int.Parse(select1.SelectedValue));
}
return data;
}
protected void Button1_Click(object sender, EventArgs e)
{
var sb = new System.Text.StringBuilder();
foreach (GridViewRow row in GridView1.Rows)
{
var myDDL = row.FindControl("myDDL") as DropDownList;
if (myDDL != null)
{
sb.AppendFormat("{0}<br/>", myDDL.SelectedValue);
}
}
Response.Write(sb.ToString());
}
I have an editable GridView, which has a AddRow button, on click of which an empty row consisting of text boxes is added.
Whenever I insert values inside these textboxes, and click AddRow or Delete button, the text boxes loose their values.
I am sure, this doesn't happen due to postback, because there's a Save button too, on the click of which the values are normally preserved.
Below is the markup:
<asp:GridView ID="GridView1" runat="server" ShowFooter="true" AutoGenerateColumns="false"
OnRowDeleting="GridView1_RowDeleting">
<Columns>
<asp:TemplateField HeaderText="Col1">
<ItemTemplate>
<asp:TextBox runat="server" ID="txt1"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Col2">
<ItemTemplate>
<asp:TextBox ID="txt2" runat="server"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Col3">
<ItemTemplate>
<asp:TextBox ID="txt3" runat="server"></asp:TextBox>
</ItemTemplate>
<FooterStyle HorizontalAlign="Right" />
<FooterTemplate>
<asp:Button ID="btnAddNewRow" runat="server" Text="AddRow" OnClick="Add" />
</FooterTemplate>
</asp:TemplateField>
<asp:CommandField ButtonType="Button" ShowDeleteButton="true" />
</Columns>
</asp:GridView>
<asp:Button ID="btnSavetoDB" runat="server" Text="save" OnClick="btnSavetoDB_Click" />
Code Behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
SetInitialRow();
}
}
//Sets the first empty row to the grid view
private void SetInitialRow()
{
DataTable dt = new DataTable();
DataRow dr = null;
dt.Columns.Add(new DataColumn("Column1", typeof(string)));
dt.Columns.Add(new DataColumn("Column2", typeof(string)));
dt.Columns.Add(new DataColumn("Column3", typeof(string)));
dr = dt.NewRow();
dr["Column1"] = string.Empty;
dr["Column2"] = string.Empty;
dr["Column3"] = string.Empty;
dt.Rows.Add(dr);
//Store the DataTable in ViewState
ViewState["CurrentTable"] = dt;
GridView1.DataSource = dt;
GridView1.DataBind();
}
//Adds a new empty row to the grid view
protected void Add(object sender, EventArgs e)
{
int rowIndex = 0;
if (ViewState["CurrentTable"] != null)
{
DataTable dtCurrentTable = (DataTable)ViewState["CurrentTable"];
DataRow drCurrentRow = null;
if (dtCurrentTable.Rows.Count > 0)
{
for (int i = 0; i < dtCurrentTable.Rows.Count; i++)
{
//extract the TextBox values
TextBox box1 = (TextBox)GridView1.Rows[rowIndex].Cells[0].FindControl("txt1");
TextBox box2 = (TextBox)GridView1.Rows[rowIndex].Cells[1].FindControl("txt2");
TextBox box3 = (TextBox)GridView1.Rows[rowIndex].Cells[2].FindControl("txt3");
drCurrentRow = dtCurrentTable.NewRow();
//drCurrentRow["RowNumber"] = i + 1;
drCurrentRow["Column1"] = box1.Text;
drCurrentRow["Column2"] = box2.Text;
drCurrentRow["Column3"] = box3.Text;
rowIndex++;
}
//add new row to DataTable
dtCurrentTable.Rows.Add(drCurrentRow);
//Store the current data to ViewState
ViewState["CurrentTable"] = dtCurrentTable;
//Rebind the Grid with the current data
GridView1.DataSource = dtCurrentTable;
GridView1.DataBind();
}
}
else
{
Response.Write("ViewState is null");
}
}
//Called on Delete Button click, which is inside a CommanField
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
int num = GridView1.Rows.Count;
int index = Convert.ToInt32(e.RowIndex);
if (num > 1)
{
DataTable dt = ViewState["CurrentTable"] as DataTable;
dt.Rows[index].Delete();
ViewState["CurrentTable"] = dt;
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
Initial snapshot:
After AddRow button click:
Where am I going wrong?
Experts please help.
Regards
The problem is that you haven't used Eval in your markup
<asp:TextBox runat="server" ID="txt1" Text='<%# Eval("Column1") %>'></asp:TextBox>
Optimized code-behind. No need of ViewState
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
var table = CreateDataTable();
table.Rows.Add("", "", "");
BindGridView(table);
}
}
//Sets the first empty row to the grid view
private DataTable CreateDataTable()
{
var dt = new DataTable
{
Columns = { "Column1", "Column2", "Column3" }
};
return dt;
}
private void BindGridView(DataTable table)
{
GridView1.DataSource = table;
GridView1.DataBind();
}
private DataTable PopulateTableFromGridView()
{
var table = CreateDataTable();
for (int i = 0; i < GridView1.Rows.Count; i++)
{
//extract the TextBox values
TextBox box1 = (TextBox)GridView1.Rows[i].FindControl("txt1");
TextBox box2 = (TextBox)GridView1.Rows[i].FindControl("txt2");
TextBox box3 = (TextBox)GridView1.Rows[i].FindControl("txt3");
table.Rows.Add(box1.Text, box2.Text, box3.Text);
}
return table;
}
//Adds a new empty row to the grid view
protected void Add(object sender, EventArgs e)
{
var newTable = PopulateTableFromGridView();
newTable.Rows.Add("", "", "");
BindGridView(newTable);
}
//Called on Delete Button click, which is inside a CommanField
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
var dt = PopulateTableFromGridView();
dt.Rows[e.RowIndex].Delete();
if (dt.Rows.Count == 0)
{
dt.Rows.Add("", "", "");
}
BindGridView(dt);
}
Links on inline expressions
http://support.microsoft.com/kb/976112
http://weblogs.asp.net/ahmedmoosa/embedded-code-and-inline-server-tags
The ff are codes in my .cs file
private void BindGridview(int rowcount)
{
DataTable dt = new DataTable();
DataRow dr;
dt.Columns.Add(new System.Data.DataColumn("Code", typeof(String)));
dt.Columns.Add(new System.Data.DataColumn("Course", typeof(String)));
dt.Columns.Add(new System.Data.DataColumn("Credit", typeof(String)));
if (ViewState["CurrentData"] != null)
{
for (int i = 0; i < rowcount + 1; i++)
{
dt = (DataTable)ViewState["CurrentData"];
if (dt.Rows.Count > 0)
{
dr = dt.NewRow();
dr[0] = dt.Rows[0][0].ToString();
}
}
dr = dt.NewRow();
dr[0] = this.cboCourseCode.Text;
dr[1] = this.txtCourseName.Text;
dr[2] = this.txtCredit.Text;
dt.Rows.Add(dr);
}
else
{
dr = dt.NewRow();
dr[0] = this.cboCourseCode.Text;
dr[1] = this.txtCourseName.Text;
dr[2] = this.txtCredit.Text;
dt.Rows.Add(dr);
}
// If ViewState has a data then use the value as the DataSource
if (ViewState["CurrentData"] != null)
{
GridView1.DataSource = (DataTable)ViewState["CurrentData"];
GridView1.DataBind();
}
else
{
// Bind GridView with the initial data assocaited in the DataTable
GridView1.DataSource = dt;
GridView1.DataBind();
}
// Store the DataTable in ViewState to retain the values
ViewState["CurrentData"] = dt;
}
protected void BindGrid()
{
GridView1.DataSource = ViewState["dt"] as DataTable;
GridView1.DataBind();
}
protected void OnRowDeleting(object sender, GridViewDeleteEventArgs e)
{
int index = Convert.ToInt32(e.RowIndex);
DataTable dt = ViewState["dt"] as DataTable;
dt.Rows[e.RowIndex].Delete();
ViewState["dt"] = dt;
BindGrid();
}
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string Code = e.Row.Cells[0].Text;
foreach (Button button in e.Row.Cells[3].Controls.OfType<Button>())
{
if (button.CommandName == "Delete")
{
button.Attributes["onclick"] = "if(!confirm('Do you want to delete " + Code + "?')){ return false; };";
}
}
}
}
protected void cboCourseCode_SelectedIndexChanged(object sender, EventArgs e)
{
this.Populate_Course_Details();
}
protected void BtnAdd_Click(object sender, EventArgs e)
{
/* DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[3] { new DataColumn("Code"), new DataColumn("Course"), new DataColumn("Credit") });
dt.Rows.Add(this.cboCourseCode.Text, this.txtCourseName.Text, this.txtCredit.Text);
ViewState["dt"] = dt;
BindGrid();*/
if (ViewState["CurrentData"] != null)
{
DataTable dt = (DataTable)ViewState["CurrentData"];
int count = dt.Rows.Count;
BindGridview(count);
}
else
{
BindGridview(1);
}
}
My aspx file also has this gridview
<asp:GridView ID="GridView1" CssClass = "Grid" runat="server" OnRowDeleting="OnRowDeleting" AutoGenerateColumns = "false" OnRowDataBound = "OnRowDataBound">
<Columns>
<asp:BoundField DataField="Code" HeaderText="Code" />
<asp:BoundField DataField="Course" HeaderText="Course" />
<asp:BoundField DataField="Credit" HeaderText="Credit" />
<asp:CommandField ShowDeleteButton="True" ButtonType="Button" />
</Columns>
</asp:GridView>
When I start to delete, I get this error:
check to determine if the object is null before calling the method
Error Reason
in OnRowDeleting function you are creating datatable and assigning viewstate["dt"],which doesn't have current data. that's why it shows Object is Null
Solution
Try This
First make one of the column as data key.consider i want to make "Code" column as datakey.
datakey will help to find specific row to delete
<asp:GridView ID="GridView1" CssClass = "Grid" runat="server" OnRowDeleting="OnRowDeleting" AutoGenerateColumns = "false" OnRowDataBound = "OnRowDataBound" DataKeyNames="Code">
After That in .cs code
create a datatable with currentdata
make "Code" column as primary key
find particular code(which you want to delete)using find()
then delete that row using delete() function
Reflect the deletion in viewsate["currentdata"]
then bind to gridview
protected void OnRowDeleting(object sender, GridViewDeleteEventArgs e)
{
string code = GridView1.DataKeys[e.RowIndex].Value.ToString();
if (ViewState["CurrentData"] != null)
{
DataTable dt = (DataTable)ViewState["CurrentData"];
dt.PrimaryKey = new DataColumn[] { dt.Columns["Code"] };
dt.Rows.Find(code).Delete();
ViewState["CurrentData"] = dt;
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
Good day!
I need to dynamycally upload files and display information in gridview.
After file upload, i need to select file type in dropdown.
But after postback i can't access Gridview1 rows, and get selected file types. After postback Gridview1.Rows.Count = 0.
Is it possible to get selected values from DropDownLists?
<asp:GridView ID="GridView1" runat="server" ShowHeader="False" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="FileName" />
<asp:TemplateField HeaderText="FileType">
<ItemTemplate>
<asp:DropDownList runat="server">
<asp:ListItem Value="Val1">Val1</asp:ListItem>
<asp:ListItem Value="Val2">Val2</asp:ListItem>
<asp:ListItem Value="Val3">Val3</asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField DeleteText="Remove" ShowDeleteButton="true" />
</Columns>
</asp:GridView>
<asp:FileUpload ID="FileUpload" runat="server" onchange="this.form.submit()" />
Thanks
In Page_Load, during PostBack, GridView rows is empty.
protected void Page_Load(object sender, EventArgs e)
{
RestoreForm();
if (IsPostBack && FileUpload.HasFile)
{
AddRow(FileUpload.PostedFile.FileName);
}
FilesGridView.RowDeleting += new GridViewDeleteEventHandler(RemoveFileFromTable);
}
private void AddRow(string file)
{
DataTable dt = (DataTable)Page.Session["Files"];
if (dt == null)
{
AddDataTableToSession();
dt = (DataTable)Page.Session["Files"];
}
DataRow dr = dt.NewRow();
dr["FileName"] = file;
dr["FileType"] = 0;
dt.Rows.Add(dr);
Page.Session["Files"] = dt;
FilesGridView.DataSource = dt;
FilesGridView.DataBind();
}
private void AddDataTableToSession()
{
DataTable dt = new DataTable("Files");
DataColumn dc = new DataColumn("FileName", Type.GetType("System.String"));
dt.Columns.Add(dc);
dc = new DataColumn("FileType", Type.GetType("System.String"));
dt.Columns.Add(dc);
Page.Session["Files"] = dt;
}
private void RemoveFileFromTable(object sender, GridViewDeleteEventArgs e)
{
int recordToDelete = e.RowIndex;
DataTable dt = (DataTable)Page.Session["Files"];
int cn = dt.Rows.Count;
dt.Rows.RemoveAt(recordToDelete);
dt.AcceptChanges();
Page.Session["Files"] = dt;
FilesGridView.DataSource = dt;
FilesGridView.DataBind();
}
Try by changing Ispostback like this.
if (!IsPostBack && FileUpload.HasFile)
{
AddRow(FileUpload.PostedFile.FileName);
}
(or)
if (IsPostBack == false && FileUpload.HasFile)
{
AddRow(FileUpload.PostedFile.FileName);
}
So that, if page load occurs, Your if condition will get true.
You can find the drop down list and update it with the value in the RowDataBOund event of gridview as follows
protected void Page_Load(object sender, EventArgs e)
{
//RestoreForm();
if (IsPostBack && FileUpload.HasFile)
{
AddRow(FileUpload.PostedFile.FileName);
}
else
{
AddDataTableToSession();
}
FilesGridView.RowDeleting += new GridViewDeleteEventHandler(RemoveFileFromTable);
FilesGridView.RowDataBound += KBFilesGridView_RowDataBound;
}
and row databound will be as follows
void KBFilesGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
DropDownList ddl = e.Row.FindControl("DropDownList1") as DropDownList;
if (ddl != null)
{
DataRow dr= ((DataRowView)e.Row.DataItem).Row;
ddl.SelectedValue = dr["FileType"].ToString();
}
}
Similary you can get the value of dropdown for remove method as well as follows
private void RemoveFileFromTable(object sender, GridViewDeleteEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddl = e.Row.FindControl("DropDownList1") as DropDownList;
if (ddl != null)
{
if(ddl.SelectedValue == "someValue") doSomeThing();
}
}
}
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, "");
}
}
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"]);
}
}
}
RowDataBound gets fired every time (irrespective of whether the page is PostBack page or NOT).
You need to add that if(!IsPostBack) condition around the code where you are performing the databinding for the dropdowns in your RowDataBound event.