We have a table on aspx page as -
<asp:Table ID="tblContainer" runat="server" Visible="false">
<asp:TableHeaderRow>
<asp:TableCell> Alplabates </asp:TableCell>
</asp:TableHeaderRow>
</asp:Table>
and we are adding control in this table as -
protected void Page_Load(object sender, EventArgs e)
{
int rowcount = tblContainer.Rows.Count;
// rowcount is one always
GenerateDynamicControls();
}
private void GenerateDynamicControls()
{
int rowcount = tblContainer.Rows.Count;
tblContainer.Visible = true;
for (int i = 0; i < 2; i++)
{
TableRow tr = new TableRow();
TableCell td = new TableCell();
TextBox textBox = new TextBox();
textBox.ID = i + "abc";
td.Controls.Add(textBox);
tr.Cells.Add(td);
tblContainer.Rows.Add(tr);
}
}
Table row count appears as one always. We tried by setting EnableViewState=true but no luck.
Can you please guide how can we get its value?
Thank you!
Related
Below is how my GridView code , since the datatable is a pivoted value so the number of columns cannot be predicted. So I am adding textbox dynamically through code.
<asp:GridView ID="gvData"
EmptyDataText="There are no data records to display."
runat="server" AutoGenerateColumns="false"
HeaderStyle-BackColor="#3AC0F2"
HeaderStyle-ForeColor="White" OnRowDataBound="gvData_RowDataBound" >
<RowStyle BorderColor="LightBlue" />
</asp:GridView>
protected void Page_Load(object sender, EventArgs e)
{
foreach (var item in columnNames)
{
TemplateField tfield = new TemplateField();
tfield.HeaderText = item;
gvData.Columns.Add(tfield);
}
gvData.DataSource = ds.Tables[0];
gvData.DataBind();}
protected void gvData_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
for (int i = 3; i < columnNames.Length; i++)
{
TextboxCount++;
TextBox txtName = new TextBox();
txtName.ID = "txt" + Convert.ToString(TextboxCount);
txtName.BorderStyle = BorderStyle.None;
txtName.Text = (e.Row.DataItem as DataRowView).Row[columnNames[i]].ToString();
e.Row.Cells[i].Controls.Add(txtName); }}}
Now when user try to change value in the textbox I have to validate that they only enter integer value.
Here I am not sure what has to be done.
You can use int.TyrParse method
Example
int number;
string s = "AA";
bool IsInteger = int.TryParse(s, out number);
You could use javascript function and that to textbox from code behind like:
// Add this gvData_RowDataBound , allownumbers is a javascript function
txtName.Attributes.Add("onkeypress", "javascript:return allownumbers(event);");
Or else if you are using .NET 4.5 version then try out this:
txtName.Attributes["type"] = "number";
Problem and Description:
I have a GridView with programmatically added DropDownLists on RowDataBound to every cell.
The DropDownLists all have Data Sources.
When I press a 'Save' button, it is meant to read all the selecteditems in the DropDownLists and save them to a database.
However, when I click on the button, it causes postback and deletes all of the controls in the GridView and therefore, none of them can be found in my button_click event.
After asking questions before and trying different techniques to try store the dropdownlists in Cache/Session state etc, I simply can't seem to be able to keep the dropdownlists or the data when I click the button.
Therefore, I am now trying to add an UpdatePanel and use AJAX to try stop the refresh of the GridView.
My attempt was as such:
<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>
</div>
<asp:Label ID="lbl_NameOfRota" runat="server" Text="New rota name:"></asp:Label>
<input runat="server" id="txt_RotaName" />
<asp:UpdatePanel runat="server" ID="RotaUpdatePanel">
<ContentTemplate>
<asp:Button ID="btn_AddRota" runat="server" Text="Add" OnClick="btn_AddRota_Click" CssClass="ButtonAdminPage" />
</ContentTemplate>
</asp:UpdatePanel>
As you can see, I placed the UpdatePanel around my button only, however, it still seemed to refresh the GridView and delete all the controls.
Questions:
Firstly, why did my attempt not work?
Secondly, how can I get around this problem using AJAX and Update Panels, or is there another method to get me what I need? (Baring in mind, if something else is suggested, I've probably already tried it).
EDIT 2:
Supplied Code:
This is when I bind the DropDownLists:
protected void gv_Rota_RowDataBound(object sender, GridViewRowEventArgs e)
{
for (int i = 1; i <= ColumnCount; i++)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
int day = e.Row.RowIndex;
day += 1;
ddlShift = new DropDownList();
ddlShift.ID = "ddlShift" + "WK" + i.ToString() + "DAY" + day.ToString();
ddlShift.DataSource = DCListOfShifts;
ddlShift.DataValueField = "SHIFT_ID";
ddlShift.DataTextField = "SHIFT_NAME";
ddlShift.Attributes.Add("Place", i.ToString());
ddlShift.DataBind();
ddlShift.Items.Insert(0, new ListItem("Shift..."));
ddlShift.CssClass = "ddl_rotamanager";
e.Row.Cells[i].Controls.Add(ddlShift);
}
}
}
This is when I create the GridView dependant on the amount of columns passed:
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();
}
This is where I get the selected amount of columns and call the method to create the GridView, I also store the amount in Cache:
protected void ddl_RotaAmountOfWeeks_SelectedIndexChanged(object sender, EventArgs e)
{
if (IsPostBack)
{
int Amount;
int.TryParse(ddl_RotaAmountOfWeeks.SelectedItem.ToString(), out Amount);
ColumnCount = Amount;
Cache.Add("columnCount", ColumnCount, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 60, 0), CacheItemPriority.Default, null);
BindGrid(Amount);
}
}
Button code:
protected void btn_AddRota_Click(object sender, EventArgs e)
{
//My first attempt at trying to save the GridView, realising I Cache'd the GridView before selecting items.
//gv_Rota = (GridView)Cache["cacheGridView"];
//Set of the size of the array to the amount of rows * colums
//this will be the maximum amount of events added
int arraysize = gv_Rota.Rows.Count * (int)Cache["columnCount"];
//the current array item being added
int arrayitem = 0;
//Finally an array of ROTA_EVENTS to pass to WCF
wsPersonnel.DC_WFM_ROTA_EVENTS[] arrayofRotaEvents = new wsPersonnel.DC_WFM_ROTA_EVENTS[arraysize];
foreach (GridViewRow row in gv_Rota.Rows)
{
for (int i = 1; i <= (int)Cache["columnCount"]; i++)
{
int day = row.RowIndex;
day += 1;
DropDownList DDL1 = (DropDownList)gv_Rota.Rows[row.RowIndex].Cells[i].FindControl("ddlShiftWK" + i.ToString() + "DAY" + day.ToString());
wsPersonnel.DC_WFM_ROTA_EVENTS dcEvent = new wsPersonnel.DC_WFM_ROTA_EVENTS
{
SHIFT_ID = DDL1.SelectedItem.Value,
WEEK = i,
WEEKSpecified = true,
DAY = day,
DAYSpecified = true,
};
arrayofRotaEvents[arrayitem++] = dcEvent;
}
}
wsP.AddRota(new wsPersonnel.DC_WFM_ROTA
{
ROTA_NAME = txt_RotaName.Value,
PERIOD_TYPE = 1,
PERIOD_TYPESpecified = true,
PERIOD_AMOUNT = ColumnCount,
PERIOD_AMOUNTSpecified = true,
ROTA_EVENTS = arrayofRotaEvents
});
}
Example of what the GridView looks like:
If you want to stop postback on button click inside the update panel then you can try this
<asp:UpdatePanel runat="server" ID="RotaUpdatePanel" UpdateMode="Conditional">
<ContentTemplate>
<asp:Button ID="btn_AddRota" runat="server" Text="Add" OnClick="btn_AddRota_Click" CssClass="ButtonAdminPage" ClientIDMode="AutoID"/>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btn_AddRota" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
I'm working on an asp project. I have a situation where I need to search files and display in gridview. The gridview have three drop down list, my problem now is how can I show the default value of my dropdown based on the result set returned when I click the search button, since I already set the default value of the drop down ("Please Select") on data row bound. Because at first load my drop down should show "please select" value. Thanks a lot for the help. below is my code.
protected void btnSearch_Click(object sender, EventArgs e)
{
int uFlag = 0;
string uploadFlag = this.ddlUploadDate.SelectedValue;
string fileName = this.txtSearchText.Text;
string uploadDt = this.txtDate.Text;
string status = this.ddlStatus.SelectedValue.ToString();
List<EventFile> fileSearch = new List<EventFile>();
fileSearch = CoMailAssociationDAL.SearchFile(uFlag, fileName, uploadDt, status);
gvwAssociation.DataSource = fileSearch;
gvwAssociation.DataBind();
}
protected void gvwAssociation_RowDataBound(object sender, GridViewRowEventArgs e)
{
ListItem Item = new ListItem();
Item.Text = "Please Select";
Item.Value = "0";
Item.Selected = true;
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddlpool = (DropDownList)e.Row.FindControl("ddlpool");
DropDownList ddlyear = (DropDownList)e.Row.FindControl("ddlyear");
DropDownList ddlevent = (DropDownList)e.Row.FindControl("ddlevent");
ddlpool.DataSource = CoMailAssociationDAL.GetCoBindEvents();
ddlpool.DataBind();
ddlpool.Items.Insert(0, Item);
ddlevent.DataSource = CoMailAssociationDAL.GetCoBindEvents();
ddlevent.DataBind();
ddlevent.Items.Insert(0, Item);
for (int intCount = 2013; intCount <= 2020; intCount++)
{
ddlyear.Items.Add(intCount.ToString());
ddlyear.SelectedIndex = 1;
}
}
}
You can do it by creating a condition in your grid RowDataBound event by taking one hiddenfield in itemtemplate for value from database and find that as
for (int intCount = 2013; intCount <= 2020; intCount++)
{
ddlyear.Items.Add(intCount.ToString());
HiddenField result= GridView1.Rows[e.RowIndex].FindControl("hdnpool") as HiddenField;
if(result!=null)
ddlyear.SelectedIndex =result.value;
else
ddlyear.SelectedIndex = 1;
}
In grid please use below for each dropdown:
<asp:TemplateField>
<ItemTemplate>
<asp:DropDownList ID="ddpool" runat="server"></asp:DropDownList>
<asp:HiddenField ID="hdnpool" Value="<%# Eval("PoolColumninDB") %>" runat="server"></asp:HiddenField>
</ItemTemplate>
</asp:TemplateField>
Have you try this
for (int intCount = 2013; intCount <= 2020; intCount++)
{
ddlyear.Items.Add(intCount.ToString());
ddlyear.SelectedValue= 1;
}
Hi I am really stuck up in one of my development tasks since couple of days and I am unable to find out the exactly whats going on. Please help.
I am trying to add rows dynamically to the webpage as follows.
I want to use server control. But I am unable to add more than one row.
No luck even though I used session variable. Kindly help please :)
-----------------aspx file---------------
<div>
<asp:Table ID="tbl" runat="server">
<asp:TableRow ID="rw0">
<asp:TableCell ID="c01" Width="100px">
<asp:CheckBox runat="server" ID="chk0" />
</asp:TableCell>
<asp:TableCell ID="c02" Width="100px">
<asp:TextBox runat="server" ID="txt0" />
</asp:TableCell></asp:TableRow>
<asp:TableRow ID="rw1">
<asp:TableCell ID="c11" Width="100px">
<asp:CheckBox ID="chk1" runat="server" />
</asp:TableCell><asp:TableCell ID="c12" Width="100px">
<asp:TextBox runat="server" ID="txt1" />
</asp:TableCell></asp:TableRow>
</asp:Table>
<asp:Button ID="btn1" runat="server" Text="Add Row" OnClick="addRow" />
</div>
---------------------C# code behind------------------------------
protected void addRow(object sender, EventArgs e)
{
int num_row = new int(); //checkpoint
num_row = (tbl.Rows).Count;
if (Session["tables"] != null)
{
tbl = (Table)Session["tables"];
}
TableRow row = new TableRow();
TableCell cell1 = new TableCell();
TableCell cell2 = new TableCell();
TextBox tb = new TextBox();
CheckBox cb = new CheckBox();
row.ID = "rw" + num_row;
cell1.ID = "c" + num_row + "1";
cell2.ID = "c" + num_row + "2";
tb.ID = "txt" + num_row;
tb.EnableViewState = true;
cb.ID = "chk" + num_row;
cell1.Controls.Add(tb);
cell2.Controls.Add(cb);
row.Cells.Add(cell1);
row.Cells.Add(cell2);
tbl.Rows.Add(row);
Session["tables"] = tbl;
}
You are able to see only one row added everytime because, dynamically created controls will not be available across postbacks.
When you click on add row first time, a post back happens, a third row is added. when you click in add row second time, the already added row would not be available and a new row gets added again. Finally you will be able to see only one row everytime.
Bottom line is you have to recreate the dynamically added controls everytime on postback in the page_load event, the reason being dynamically added server sontrols donot persist across postbacks
refer Why dynamically created user controls disappear when controls are not doing full postbacks? also
To maintain the viewstate of dynamically added controls you have to generate ids for the controls. When you recreate the controls during postback, recreate them with the same ids so that view state is maintained.
Use some standard logic to generate the ids for the controls. hope this helps.
Update:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
int num_row = (int)Session["No_of_Rows"];
for (int i = 2; i < num_row; i++)
{
TableRow row = new TableRow();
TableCell cell1 = new TableCell();
TableCell cell2 = new TableCell();
TextBox tb = new TextBox();
CheckBox cb = new CheckBox();
row.ID = "rw" + i;
cell1.ID = "c" + i + "1";
cell2.ID = "c" + i + "2";
tb.ID = "txt" + i;
tb.EnableViewState = true;
cb.ID = "chk" + i;
cell1.Controls.Add(cb);
cell2.Controls.Add(tb);
row.Cells.Add(cell1);
row.Cells.Add(cell2);
tbl.Rows.Add(row);
}
}
else
{
Session["No_of_Rows"] = 2;
}
}
protected void addRow(object sender, EventArgs e)
{
int num_row = (int)Session["No_of_Rows"]+1;
TableRow row = new TableRow();
TableCell cell1 = new TableCell();
TableCell cell2 = new TableCell();
TextBox tb = new TextBox();
CheckBox cb = new CheckBox();
row.ID = "rw" + num_row;
cell1.ID = "c" + num_row + "1";
cell2.ID = "c" + num_row + "2";
tb.ID = "txt" + num_row;
tb.EnableViewState = true;
cb.ID = "chk" + num_row;
cell1.Controls.Add(cb);
cell2.Controls.Add(tb);
row.Cells.Add(cell1);
row.Cells.Add(cell2);
tbl.Rows.Add(row);
Session["No_of_Rows"] = tbl.Rows.Count;
}
After entering the value in the tale column how to save all the values in the database table?
I found the tutorial to create a dynamic table and add rows:
http://geekswithblogs.net/dotNETvinz/archive/2009/06/29/faq-dynamically-adding-rows-in-asp-table-on-button-click.aspx
How can I read all rows in the table, and then the values of the textbox in the cells? The values are entered in a table in a database (SQL Server).
Can I continue to use C# and asp.net or do I have to use Javascript?
I hope someone will give me help.
This is the code:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Dynamic Adding of Rows in ASP Table Demo</title>
</head>
<body>
<form id="form1" runat="server">
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Add New Row" />
</form>
</body>
</html>
CODE BEHIND:
public partial class _Default1 : System.Web.UI.Page
{
//A global variable that will hold the current number of Rows
//We set the values to 1 so that it will generate a default Row when the page loads
private int numOfRows = 1;
protected void Page_Load(object sender, EventArgs e)
{
//Generate the Rows on Initial Load
if (!Page.IsPostBack)
{
GenerateTable(numOfRows);
}
}
protected void Button1_Click(object sender, EventArgs e)
{
if (ViewState["RowsCount"] != null)
{
numOfRows = Convert.ToInt32(ViewState["RowsCount"].ToString());
GenerateTable(numOfRows);
}
}
private void SetPreviousData(int rowsCount, int colsCount)
{
Table table = (Table)Page.FindControl("Table1");
if (table != null)
{
for (int i = 0; i < rowsCount; i++)
{
for (int j = 0; j < colsCount; j++)
{
//Extracting the Dynamic Controls from the Table
TextBox tb = (TextBox)table.Rows[i].Cells[j].FindControl("TextBoxRow_" + i + "Col_" + j);
//Use Request objects for getting the previous data of the dynamic textbox
tb.Text = Request.Form["TextBoxRow_" + i + "Col_" + j];
}
}
}
}
private void GenerateTable(int rowsCount)
{
//Creat the Table and Add it to the Page
Table table = new Table();
table.ID = "Table1";
Page.Form.Controls.Add(table);
//The number of Columns to be generated
const int colsCount = 3;//You can changed the value of 3 based on you requirements
// Now iterate through the table and add your controls
for (int i = 0; i < rowsCount; i++)
{
TableRow row = new TableRow();
for (int j = 0; j < colsCount; j++)
{
TableCell cell = new TableCell();
TextBox tb = new TextBox();
// Set a unique ID for each TextBox added
tb.ID = "TextBoxRow_" + i + "Col_" + j;
// Add the control to the TableCell
cell.Controls.Add(tb);
// Add the TableCell to the TableRow
row.Cells.Add(cell);
}
// And finally, add the TableRow to the Table
table.Rows.Add(row);
}
//Set Previous Data on PostBacks
SetPreviousData(rowsCount, colsCount);
//Sore the current Rows Count in ViewState
rowsCount++;
ViewState["RowsCount"] = rowsCount;
}
}
Since you're creating the table dynamically, you can't reference it like controls that are statically embedded on the page. To get a reference to the Table object you'll need to find it in the Page's ControlCollection and cast it out, just like in the example:
Table table = (Table)Page.FindControl("Table1");
The Table class contains a table row collection which you will then need to loop over. Each row in the row collection has a collection of cells, each of which will contain child controls (see: Controls property) which will be your textboxes.
Hi if you take look at SetPreviousData this function is trying to read previous textbox value but there is some thing wrong with it i have done following changes and it works fine
first of all the following code in SetPreviousData
Table table = (Table)Page.FindControl("Table1");
is always returning NULL because this function is not a recursive function and your table may be inside a container in your page so add following function to your code
private Control FindControlRecursive(Control root, string id)
{
if (root.ID == id)
{
return root;
}
foreach (Control c in root.Controls)
{
Control t = FindControlRecursive(c, id);
if (t != null)
{
return t;
}
}
return null;
}
and change the code
Table table = (Table)Page.FindControl("Table1");
to
Table table = FindControlRecursive(Page , "Table1") as Table;
in next step change the following code in SetPreviousData
tb.Text = Request.Form["TextBoxRow_" + i + "Col_" + j];
to
tb.Text = Request.Form[tb.UniqueID];
set break points and see the results if it's tough to you let me know to provide you a function which returns table data in a datatable
I think you must bind your table again at the Page_load event.For example if you are binding the table at View_Click button event,you have to call this method in Page_load event as View_Click(null,null).
<script type="text/javascript">
var StringToSend='';
function fncTextChanged(newvalueadded) {
if (StringToSend != '')
StringToSend = StringToSend + ';' + newvalueadded;
else
StringToSend = newvalueadded;
//alert(StringToSend); -- For Testing all values
// now store the value of StringToSend into hidden field ---- HFTEXTVALUES to access it from server side.
}
</script>
<asp:Button ID="Save" runat="server" onclick="SaveTextBoxValues_Click" Text="save" />
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Add New Row" />
<asp:HiddenField ID="hfTextValues" runat="server" Visible="false" Value="" />
Server Side :
protected void Page_Load(object sender, EventArgs e)
{
//Generate the Rows on Initial Load
if (!Page.IsPostBack)
{
GenerateTable(numOfRows);
}
}
protected void Button1_Click(object sender, EventArgs e)
{
if (ViewState["RowsCount"] != null)
{
numOfRows = Convert.ToInt32(ViewState["RowsCount"].ToString());
GenerateTable(numOfRows);
}
}
protected void SaveTextBoxValues_Click(object sender, EventArgs e)
{
string AllTextBoxValues = hfTextValues.Value;
string[] EachTextBoxValue = AllTextBoxValues.Split('~');
//here you would get all values, EachTextBoxValue[0] gives value of first textbox and so on.
}
private void GenerateTable(int rowsCount)
{
//Creat the Table and Add it to the Page
Table table = new Table();
table.ID = "Table1";
Page.Form.Controls.Add(table);
//The number of Columns to be generated
const int colsCount = 3;//You can changed the value of 3 based on you requirements
// Now iterate through the table and add your controls
for (int i = 0; i < rowsCount; i++)
{
TableRow row = new TableRow();
for (int j = 0; j < colsCount; j++)
{
TableCell cell = new TableCell();
TextBox tb = new TextBox();
HiddenField hf = new HiddenField();
// Set a unique ID for each TextBox added
tb.ID = "tb" + i + j;
hf.ID = "hf" + i + j;
tb.Attributes.Add("onblur", "fncTextChanged(this.value);");
// Add the control to the TableCell
cell.Controls.Add(tb);
// Add the TableCell to the TableRow
row.Cells.Add(cell);
}
// And finally, add the TableRow to the Table
table.Rows.Add(row);
}
}
Let me know if you have any questions.
One more thing, if you wish to store the values and retrieve them later, the code would be modified accordingly.
reference for a dynamic table doesn't work well , blame microsoft ,
I use this :
Save inside a session List[YourObjectData] and every time you get into Page_Load , fill it the table
here is solution for number 2 :
somewhere inside Default.aspx
<div class="specialTable">
<asp:Table ID="Table1" runat="server" />
</div>
Code behind:
protected void Page_Load(object sender, EventArgs e)
{
FillDynamicTable();
if (!IsPostBack)
{
}
}
private void FillDynamicTable()
{
Table1.Rows.Clear(); // Count=0 but anyways
if (Session["Table1"] == null) return;
foreach (var data in Session["Table1"] as List<MyObject>)
{
AddRow(data);
}
}
private void AddRow(MyObject data)
{
var row = new TableRow { Height = 50 };
var cell = new TableCell();
var label = new Label { Text = data.something, Width = 150 };
cell.Controls.Add(label);
row.Cells.Add(cell);
Table1.Rows.Add(row);
}