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());
}
Related
i have a gridview in a asp.net webform and i add it a check box column like this (the dataTable first column(0) is empty in sql data source and i add check boxes on the column cells):
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (rowNum != 0)//except first row
{
CheckBox cb = new CheckBox();
cb.Enabled = true;
e.Row.Cells[0].Controls.Add(cb);//row[0]=first clmn-and this event happend for all rows
}
rowNum++;
}
now i have a dynamic check box column! and user should check some of them and click the submit then i need the row number of the checked check boxes.
how can i do this?
i tried this before:
DataTable editTable = new DataTable();
editTable.Rows.Add(GridView1.Rows[0]);
var x = editTable.Rows[0][0];
but the x cannot get the check box true or false! it seems that getting me the original field under the check box content.
regards.
Instead of creating the controls dynamically which in most cases results in a lot of trouble, you could add the CheckBoxes in one or more template columns. The following sample shows how to add a checkbox in a template column and how to retrieve the value afterwards:
<asp:GridView ID="gridView" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="chb" runat="server" />
<asp:HiddenField ID="hiddenId" runat="server"
Value='<%# DataBinder.Eval(Container.DataItem, "Id") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Text" />
</Columns>
</asp:GridView>
In my sample, I've bound some data to the GridView:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
var dt = GetData();
gridView.DataSource = dt;
gridView.DataBind();
}
}
private DataTable GetData()
{
var dt = new DataTable();
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Text", typeof(string));
for (int i = 0; i < 10; i++)
dt.Rows.Add(new object[] { i, "Test text " + i.ToString() });
return dt;
}
If you need to set the value, you can do so in the RowDatabound event. The following code shows how to retrieve the value of the Checkbox controls:
protected void btn_Click(object sender, EventArgs e)
{
List<int> checkedIds = new List<int>();
foreach(GridViewRow row in gridView.Rows.OfType<GridViewRow>()
.Where(x => x.RowType == DataControlRowType.DataRow))
{
var hiddenId = (HiddenField)row.Cells[0].FindControl("hiddenId");
var checkBox = (CheckBox) row.Cells[0].FindControl("chb");
if (checkBox.Checked)
checkedIds.Add(int.Parse(hiddenId.Value));
}
}
I got an error of
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: System.ArgumentOutOfRangeException: Specified
argument was out of the range of valid values. Parameter name: index
Source Error:
if (e.Row.RowType == DataControlRowType.DataRow)
{
LinkButton _singleClickButton = (LinkButton)e.Row.Cells[0].Controls[2];
string _jsSingle = ClientScript.GetPostBackClientHyperlink(_singleClickButton, "Select$" + e.Row.RowIndex);
e.Row.Style["cursor"] = "hand";
my code
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[3] { new DataColumn("itemid", typeof(string)),
new DataColumn("itemdesc", typeof(string)),
new DataColumn("itemtype",typeof(string)) });
dt.Rows.Add("FG001", "Red Velvet Cake (8'' round)","Dry Goods");
dt.Rows.Add("FG002", "Voilet Velvet Cake (8'' round)", "Dry Goods");
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
protected void OnDataBound(object sender, EventArgs e)
{
GridViewRow row = new GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal);
for (int i = 0; i < GridView1.Columns.Count; i++)
{
TableHeaderCell cell = new TableHeaderCell();
TextBox txtSearch = new TextBox();
txtSearch.Attributes["placeholder"] = GridView1.Columns[i].HeaderText;
txtSearch.CssClass = "search_textbox";
cell.Controls.Add(txtSearch);
row.Controls.Add(cell);
}
GridView1.HeaderRow.Parent.Controls.AddAt(1, row);
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (!IsPostBack)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
LinkButton _singleClickButton = (LinkButton)e.Row.Cells[0].Controls[0];
string _jsSingle = ClientScript.GetPostBackClientHyperlink(_singleClickButton, "Select$" + e.Row.RowIndex);
e.Row.Style["cursor"] = "hand";
e.Row.Attributes["onclick"] = _jsSingle;
}
}
}
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewRow selectedRow = GridView1.SelectedRow;
hiddenitemid.Value = selectedRow.Cells[0].Text;
}
the error pointing
LinkButton _singleClickButton = (LinkButton)e.Row.Cells[0].Controls[0];
Either you have rows without any cells, or you have a cell with less than three controls.
To prevent the code from crashing, just check if you have enough items:
if (e.Row.Cells.Count > 0)
{
TableCell cell = e.Row.Cells[0];
if (cell.Controls.Count > 2)
{
LinkButton _singleClickButton = (LinkButton)cell.Controls[2];
string _jsSingle = ClientScript.GetPostBackClientHyperlink(_singleClickButton, "Select$" + e.Row.RowIndex);
e.Row.Style["cursor"] = "hand";
}
}
The reason behind this error is there are no cells available in your gridview when your code is executing.
You are adding columns to the gridview and binding it to datatable in page_load that too in "if(!this.IsPostBack)" block. So columns will be added to the gridview only when the page loads first time. And when gridview event is fired and page is posted back the page_load is executed again but no columns added and no databinding done to the gridview.
After that gridview's event handler gets executed and it does not find any cells in the row (coz there are no columns in the grid) so it does not go inside "if (e.Row.Cells.Count > 0)" block. And if you try to access cells using Cells[0] it throws Exception.
The solution to this problem is to define column structure of grid view in the HTML and bind gridview to data source in the code behind.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="itemdesc" HeaderText="Item Description" ReadOnly="True" />
<asp:BoundField DataField="itemtype" HeaderText="Item Type" ReadOnly="True" />
</Columns>
</asp:GridView>
Or you write code of adding columns to gridview in the InitialzeComponents() method which is executed every time page loads.
I have a GridView on my asp.net webform with all the columns and rows created in C# code from behind. Except the first column, every cell in each column is a DropDownList with a DataSource.
Here is my GridView:
<asp:GridView ID="gv_Rota" runat="server" AutoGenerateColumns="false" OnRowDataBound="gv_Rota_RowDataBound">
<HeaderStyle BackColor="#6a3d98" ForeColor="White" Height="20" />
<RowStyle HorizontalAlign="Center" Height="20px" Width="100px" />
<AlternatingRowStyle Height="20px" />
</asp:GridView>
And the c# creation of the columns and cells:
private void BindGrid(int Amount)
{
gv_Rota.DataSource = null;
gv_Rota.Columns.Clear();
BoundField bfield = new BoundField();
bfield.HeaderText = "Days";
bfield.DataField = "Days";
gv_Rota.Columns.Add(bfield);
for (int i = 0; i < Amount; i++)
{
int week = i + 1;
string sWeek = "Week " + week.ToString();
TemplateField tfield = new TemplateField();
tfield.HeaderText = sWeek;
gv_Rota.Columns.Add(tfield);
}
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("Days", typeof(string)));
dt.Rows.Add("M");
dt.Rows.Add("T");
dt.Rows.Add("W");
dt.Rows.Add("T");
dt.Rows.Add("F");
dt.Rows.Add("S");
dt.Rows.Add("S");
gv_Rota.DataSource = dt;
gv_Rota.DataBind();
}
And then on the RowDataBound trigger of my GridView, I add the DropDownList control to every cell:
protected void gv_Rota_RowDataBound(object sender, GridViewRowEventArgs e)
{
for (int i = 1; i <= ColumnCount; i++)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
ddlShift = new DropDownList();
ddlShift.ID = "ddlShift";
ddlShift.DataSource = DCListOfShifts;
ddlShift.DataValueField = "SHIFT_ID";
ddlShift.DataTextField = "SHIFT_NAME";
ddlShift.DataBind();
ddlShift.Items.Insert(0, new ListItem("Shift..."));
ddlShift.CssClass = "ddl_rotamanager";
e.Row.Cells[i].Controls.Add(ddlShift);
}
}
}
What is displayed for example on my page:
So my question and problem is that I now want to save each column (except the first) to a database, as a "scheduled week", and have no idea how to get the values of selected items in all or any of the DropDownLists to then pass that back to the database. Baring in mind, this is NOT done on selectedindexchanged. I will select items from all the DropDownLists and then press a button to submit the values. Please could someone give me some highlight on how this could be done? Thanks.
EDIT 1: Response explains how I could get every value of a DropDownList in a row or by individual cell. However, now I need to know more specifically how I can get values of specific cells in the columns rather than the rows. Is it possible to get further highlight on this?
Use Gridview.Rows property
protected void MyButton_Click(object sender, EventArgs e)
{
foreach(GridViewRow row in gv_Rota.Rows)
{
//find this control in this row
DropDownList dd = row.FindControl("MyDropdown") as DropDownList;
//OR
//find this control in a specific cell
DropDownList day = row.Cells[0].FindControl("MyDropdown") as DropDownList;
DropDownList Week1 = row.Cells[1].FindControl("ddShift") as DropDownList;
//this is just a pseudo-code to determine which dropdown was selected per row.
//You can improve on this
if(dd1.SelectedValue != string.Empty)
thisDay.SelectedWeek = dd1.SelectedValue;
else if(dd2.SelectedValue != string.Empty)
thisDay.SelectedWeek = dd2.SelectedValue;
....
}
}
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.