In my aspx file I have the following code:
<asp:PlaceHolder ID="phdHolding" runat="server">
<asp:Label ID="lblWarning" runat="server" Text="" Visible="false" />
<asp:PlaceHolder ID="phdInput" runat="server" Visible="false">
<h3><asp:Label ID="lblArea" runat="server" Text="Area" /></h3>
</asp:PlaceHolder>
</asp:PlaceHolder>
In code behind (c#) I create a table which is added to phdInput. One part of that code is the creation and population of a TextBox (and Label) within a Table Cell. The TextBox is required to call a function on TextChanged.
decimal amount = Convert.ToDecimal(dc.DataScalar("SELECT Item" + rownr + " FROM Companies WHERE CompanyName='" + coy + "' AND BusinessUnit='" + bu + "'"));
TextBox tb = new TextBox(); tb.ID = "txtAmount" + rownr; tb.Width = 70; tb.Text = amount.ToString("N0");
tb.AutoPostBack = true; tb.TextChanged += new EventHandler(UpdateAmounts);
Label lbl = new Label(); lbl.Text= " " + trow["Unit"].ToString();
TableCell tdamount = new TableCell(); tdamount.Controls.Add(tb); tdamount.Controls.Add(lbl);
tr2.Cells.Add(tdamount);
This is all working fine and everything is displayed on the page. However, when the text is changed and you click outside the textbox or press'Enter' etc. the function is not being reached (have checked in VS) and phdInput becomes blank.
I have used this function, and the TextChanged method of calling it, before with no issues so why is it not working now?
I have managed to recreate one problem
phdInput becomes blank
This was suspicious, if it disappears there must be PostBack in the action. Suspicion rises especially because phdInput attribute Visible is set to false on the form.
I suppose form's initialization is happening inside the Page_Load method and one of the code behind lines is to set phdInput attribute Visible to true. However, phdInput disappears after PostBack is fired, so there's probably check
if (!IsPostBack)
Initialization is happening inside of it, which is correct, no need to initialize it every time page reloads. However
phdInput.Visible = true;
should be outside of check if (!IsPostBack) in order to phdInput be always visible.
Next, something fires the PostBack.
However, when the text is changed and you click outside the textbox or
press'Enter' etc. the function is not being reached (have checked in
VS) and phdInput becomes blank.
This sounds like TextChanged event works, it only calls some other event handler.
I hope it will help you find the solution. Here follows the code that recreates the issue phdInput becomes blank (it is poorly written).
.aspx - content of body tag
<form id="form1" runat="server">
<div>
<p>start</p>
<asp:PlaceHolder ID="phdHolding" runat="server">
<asp:Label ID="lblWarning" runat="server" Text="" Visible="false" />
<asp:PlaceHolder ID="phdInput" runat="server" Visible="false" >
<h3><asp:Label ID="lblArea" runat="server" Text="Area" /></h3>
</asp:PlaceHolder>
</asp:PlaceHolder>
<p>end</p>
</div>
</form>
code behind
using System;
using System.Web.UI.WebControls;
namespace WebApplication8
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
try
{
if (!IsPostBack)
{
// row 1
int rownr = Convert.ToInt32(1);
TableRow tr = new TableRow();
tr.VerticalAlign = VerticalAlign.Top;
TableCell tdtype = new TableCell();
tdtype.Text = "table cell 1 text";
tdtype.Width = 250;
tdtype.HorizontalAlign = HorizontalAlign.Left;
tr.Cells.Add(tdtype);
decimal amount = Convert.ToDecimal(1);
TextBox tb = new TextBox(); tb.ID = "txtAmount" + rownr; tb.Width = 70; tb.Text = amount.ToString("N0");
tb.AutoPostBack = true; tb.TextChanged += new EventHandler(UpdateAmounts);
Label lbl = new Label(); lbl.Text = " " + "1";
TableCell tdamount = new TableCell(); tdamount.Controls.Add(tb); tdamount.Controls.Add(lbl);
tr.Cells.Add(tdamount);
// row 2
int rownr2 = Convert.ToInt32(2);
TableRow tr2 = new TableRow();
tr2.VerticalAlign = VerticalAlign.Top;
TableCell tdtype2 = new TableCell();
tdtype2.Text = "table cell 2 text";
tdtype2.Width = 250;
tdtype2.HorizontalAlign = HorizontalAlign.Left;
tr2.Cells.Add(tdtype2);
decimal amount2 = Convert.ToDecimal(2);
TextBox tb2 = new TextBox(); tb2.ID = "txtAmount" + rownr2; tb2.Width = 70; tb2.Text = amount2.ToString("N0");
tb2.AutoPostBack = true; tb2.TextChanged += new EventHandler(UpdateAmounts);
Label lbl2 = new Label(); lbl2.Text = " " + "2";
TableCell tdamount2 = new TableCell(); tdamount2.Controls.Add(tb2); tdamount2.Controls.Add(lbl2);
tr2.Cells.Add(tdamount2);
// table
var table = new Table();
table.Rows.Add(tr);
table.Rows.Add(tr2);
phdInput.Controls.Add(table);
lblWarning.Text = "some warning";
lblArea.Text = "some area text";
lblWarning.Visible = true;
phdInput.Visible = true;
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
protected void UpdateAmounts(object sender, EventArgs e)
{
}
}
}
when page is opened
after textbox's text is changed - either one
Related
I'm having a problem to get controls/ controls id that I have created manually from code behind. after doing research I found if I create the table and its all component including any controls in Page_Init() method, when rendering after postback the text value of textbox control should be available to the page. i tried to locate the textbox control using FindControl() method. when debugging it only reach to the line where I tried to locate the control using FindControl() and then throw an exception "Object reference not set to an instance of an object" bellow is the Page_Init() method
protected void Page_Init(object sender, EventArgs e)
{
Table tb = new Table();
tb.ID = "Table1";
TableRow row1 = new TableRow();
TableCell cell1 = new TableCell();
TableCell cell2 = new TableCell();
TableCell cell3 = new TableCell();
TextBox txtbx = new TextBox();
Button btn = new Button();
cell1.Text = "Name: ";
txtbx.ID = "table1_text_input";
txtbx.ValidationGroup = "rosy";
cell2.Controls.Add(txtbx);
btn.Text = "Get the input";
btn.ValidationGroup = "rosy";
btn.Click += getBoxinput_Click;
cell3.Controls.Add(btn);
// adding cells to row1
row1.Cells.Add(cell1);
row1.Cells.Add(cell2);
row1.Cells.Add(cell3);
// adding row to table1
tb.Rows.Add(row1);
Panel1.Controls.Add(tb);
}
below is the button click event that supposes to display the control id and its text. I'm stuck with this for the last couple of days. any help will be appreciated.
protected void getBoxinput_Click(object sender, EventArgs e)
{
try
{
if (IsPostBack)
{
Table t = (Table)Page.FindControl("Panel1").FindControl("Table1");
TextBox tbox;
foreach (TableRow tr in t.Rows)
{
foreach (TableCell tc in tr.Cells)
{
foreach (Control cnt in tc.Controls)
{
if (cnt.GetType() == typeof(TextBox))
{
tbox = (TextBox)cnt;
display.Text += "control id: " + tbox.ID + " control input: " + tbox.Text + "<br/>";
}
}
}
}
}
}
catch (NullReferenceException ex)
{
display.Text += ex.Message;
}
}
Maybe I am missing something but why don't you just put all the controls in the global scope of the class (instead of just creating the instances inside Page_Init) so that you can access them in any part of your class. Of course I am assuming that Page_Init and getBoxinput_Click are in the same class.
EDIT:
Here is the example on how to put the variables in the global scope:
Table tb; //Declare variables outside any function.
protected void getBoxinput_Click(object sender, EventArgs e)
{
tb = new Table(); //Initialize them inside a function.
}
This way you will be able to access tb inside any function.
Your code is working perfectly. Here is what I used for the form markup:
<form id="form1" runat="server">
<asp:Panel ID="Panel1" runat="server"></asp:Panel>
<asp:Label ID="display" runat="server"></asp:Label>
</form>
I have search box that take username and search on it in the userlist
the problem is that I want from the program to search directly as he get first letter from the user
Front-End
<asp:TextBox ID="TextBox1"
class="form-control table-search-input"
ontextchanged="TextBox1_TextChanged"
AutoPostBack="True"
runat="server" >
Back-End
protected void TextBox1_TextChanged(object sender, EventArgs e )
{
int bb=TextBox1.Text.Length;
adminuserlist2 = adminuserlist2.Where(o => o.AdminUserName.Substring(0,bb) == TextBox1.Text).ToList();
if (adminuserlist2 != null)
{
Table1.Rows.Clear();
Table1.BorderWidth = 1;
Table1.BorderStyle = BorderStyle.Groove;
Table1.GridLines = GridLines.Both;
TableCell un = new TableCell();
un.Text = "UserName";
TableCell pass = new TableCell();
pass.Text = "Password";
TableCell email = new TableCell();
email.Text = "Email";
TableCell isactives = new TableCell();
isactives.Text = "IsActive";
TableCell typename = new TableCell();
typename.Text = "Type Name";
TableCell typeid = new TableCell();
typeid.Text = "Type Id";
row = new TableRow();
row.Width = new Unit("120%");
row.BackColor = System.Drawing.Color.White;
row.ControlStyle.Font.Size = 25;
row.ControlStyle.Font.Bold = true;
row.ControlStyle.ForeColor = System.Drawing.Color.Black;
row.Controls.Add(un);
row.Controls.Add(pass);
row.Controls.Add(email);
row.Controls.Add(isactives);
row.Controls.Add(typename);
row.Controls.Add(typeid);
Table1.Controls.Add(row);
row.ControlStyle.Width = 300;
row.ControlStyle.Height = 30;
Table1.Width = 500;
Table1.ControlStyle.Width = 1000;
Table1.Height = 500;
Table1.CellSpacing = 50;
Table1.CellPadding = 50;
for (int i = 0; i < adminuserlist2.Count; i++)
{
TableCell un2 = new TableCell();
un2.Text = adminuserlist2[i].AdminUserName;
TableCell pass2 = new TableCell();
pass2.Text = adminuserlist2[i].AdminUserPassword;
TableCell email2 = new TableCell();
email2.Text = adminuserlist2[i].AdminUserEmail;
TableCell isactives2 = new TableCell();
isactives2.Text = adminuserlist2[i].IsActive.ToString();
TableCell typename2 = new TableCell();
typename2.Text = adminuserlist2[i].AdminUserType;
TableCell typeid2 = new TableCell();
typeid2.Text = adminuserlist2[i].AdminUserTypeID.ToString();
row = new TableRow();
row.Controls.Add(un2);
row.Controls.Add(pass2);
row.Controls.Add(email2);
row.Controls.Add(isactives2);
row.Controls.Add(typename2);
row.Controls.Add(typeid2);
Table1.Controls.Add(row);
}
}
}
I faced a problem that I should click out of the text box to search
please any one can help
It will be better if you go for OnKeyPress Event instead of TextChanged just change the event and it will be working
Front End
<asp:TextBox ID="TextBox1"
class="form-control table-search-input"
onkeypress="__doPostBack(this.name,'OnKeyPress');"
AutoPostBack="True"
runat="server" >
BackEnd
private void TextBox1_OnKeyPress(string ctrlName, string args){
//your code goes here
}
In Asp.Net there is no real textchanged event, it will only fire if the textbox lost focus and if you have set autopostback to true.
What you can do is the Following:
Add A ScriptManager to your aspx page:
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true"/>
Add an onkeypress clientside event to your textbox:
<asp:TextBox ID="TextBox1"
class="form-control table-search-input"
ontextchanged="TextBox1_TextChanged"
AutoPostBack="True"
runat="server" onkeypress="CallMyPageMethod();" >
Call your PageMethod:
<script language="javascript" type="text/javascript">
function CallMyPageMethod() {
PageMethods.MyPageMethod();
}
Add a PageMethod to your code behind:
[System.Web.Services.WebMethod]
public static void MyPageMethod()
{
//add your textchanged event code here
}
Aspx page:
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<asp:placeholder id="container" runat="server" visible="false"></asp:placeholder>
</td>
</tr>
</table>
On Code Behind file:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
generateDynamicControls();
}
private void generateDynamicControls()
{
for (int i = 0; i < dt.Rows.Count; i++)
{
HtmlGenericControl tr = new HtmlGenericControl("tr");
HtmlGenericControl td1 = new HtmlGenericControl("td");
Label lbl = new Label();
lbl.ID = "lbl" + dt.Rows[i]["sSubjectName"].ToString();
lbl.Text = dt.Rows[i]["sSubjectName"].ToString() + " :";
lbl.Width = new Unit(170);
lbl.Style.Add("padding-left", "10px");
lbl.Style.Add("font-weight", "bold");
td1.Controls.Add(lbl);
tr.Controls.Add(td1);
HtmlGenericControl td2 = new HtmlGenericControl("td");
TextBox txtBox = new TextBox();
txtBox.ID = "txt" + dt.Rows[i]["sSubjectName"].ToString();
txtBox.CssClass = "TxtBox";
txtBox.TextMode = TextBoxMode.MultiLine;
txtBox.Width = new Unit(840);
td2.Style.Add("colspan", "3");
td2.Controls.Add(txtBox);
tr.Controls.Add(td2);
container.Controls.Add(tr);
HtmlGenericControl tr1 = new HtmlGenericControl("tr");
HtmlGenericControl td3 = new HtmlGenericControl("td");
td3.Style.Add("colspan", "4");
td3.InnerHtml = " ";
tr1.Controls.Add(td3);
container.Controls.Add(tr1);
//container.Controls.Add(new LiteralControl("<br />"));
//LiteralControl literalBreak = new LiteralControl();
//literalBreak.Text ="</br>";
}
container.Visible = true;
}
}
`dt(datatable)` is filled from other function.
this is working fine and controls are created correclty.
But I want to recreate this dynamic controls on selected change event of dropdownlist. but before recreate these controls i have to delete previously created controls.
I have tried below code in dropdownlist selected changed event to delete these controls and recreate new controls.
for (int i = 0; i < dt.Rows.Count; i++)
{
container.Controls.Remove(container.FindControl(dt.Rows[i]["nSubjectId"].ToString()));
}
generateDynamicControls();
But it's not work and give me following error. becuase of onload event is alread ycalled first and created the dyanmic controls.
Multiple controls with the same ID 'lblOrals' were found. FindControl requires that controls have unique IDs.
How can I solve this problem.
Please help me solve this problem.
Thanks in advance
Try this
Give the for loop variable (i) to your label id, like the below way
lbl.ID = "lbl" + dt.Rows[i]["sSubjectName"].ToString()
+i.ToString();//i is loop variable for coordinated with labelid.
Now if the "dt.Rows[i]["sSubjectName"]" is return "LabeleName", When the for loop will assign the values like
dt.Rows[i]["sSubjectName"].ToString() + i.ToString() , So It is return values like "LabeleName1"
Finally you got the label id's are followings name
lblLabeleName1
lblLabeleName2
lblLabeleName3
.
.
.
.etc
textbox are like
txtBox.ID = "txt" + dt.Rows[i]["sSubjectName"].ToString() + i.ToString();
Result are
txtLabeleName1
txtLabeleName2
txtLabeleName3
.
.
.
etc.
Remove fields code like
//For label
container.Controls.Remove(container.FindControl("lbl" + dt.Rows[i]["sSubjectName"].ToString() +i.ToString()));
//For TextBox
container.Controls.Remove("txt" + dt.Rows[i]["sSubjectName"].ToString()+ i.ToString() ));
And Should call the generateDynamicControls(); method inside of !ISPostBack() event in page load event
Like
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if(!IsPostBack)
{
generateDynamicControls();
}
}
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'm building a in codebehind. The table is a listing of a database records (one record per row) and I neeed to add a delete button for each row. To do that, I of course need to build a button with a unique ID for that. To do that, I came up with the following ... which doesn't work. Any tips on how to get this working?
Button deleteButton = new Button();
deleteButton.ID = "deleteStudentWithID" + singleStudent.ID.ToString();
deleteButton.Text = "X";
string row = "<tr>";
row += "<td class=\"style5\">"+deleteButton.ClientID +"</td>";
row += "</tr>";
Your problem is that you're adding only the ClientID of your control to the html and not adding the control to the page itself.
Controls.Add(new LiteralControl("<table>"));
foreach(var singleStudent in students)
{
Controls.Add(new LiteralControl("<tr>"));
//Code to add other columns
Button deleteButton = new Button();
deleteButton.ID = "deleteStudentWithID" + singleStudent.ID.ToString();
deleteButton.Text = "X";
Controls.Add(new LiteralControl("<td class=\"style5\">"));
Controls.Add(deleteButton);
Controls.Add(new LiteralControl("</td></tr>");
}
Controls.Add(new LiteralControl("</table>"));
Instead of creating the entire table markup in your code behind, use the controls made available by ASP.NET.
For an example, place this in your .aspx:
<table>
<asp:Repeater runat="server" ID="MyRepeater1">
<ItemTemplate>
<tr>
<td><%# Eval("StudentName")%></td>
<td>... other student object bindings ...</td>
<td>
<asp:Button runat="server" ID="MyDeleteButton"
CommandArgument='<%# Eval("ID")%>'
CommandName="Delete"
OnCommand="MyDeleteButton_Command"
Text="X" />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
And include this in your code-behind:
protected void Page_Load(object sender, EventArgs e)
{
MyRepeater1.DataSource = new MyStudent[]
{
new MyStudent()
{
ID = 1,
StudentName = "Student 1"
},
new MyStudent()
{
ID = 2,
StudentName = "Student 2"
}
};
MyRepeater1.DataBind();
}
protected void MyDeleteButton_Command(object sender, CommandEventArgs e)
{
switch (e.CommandName)
{
case "Delete":
// stuff for deleting by e.CommandArgument
break;
}
}
The best Solution to Your problem i can think of is
Button deleteButton = new Button();
deleteButton.ID = "deleteStudentWithID" + singleStudent.ID.ToString();
deleteButton.Text = "X";
StringBuilder sb = new StringBuilder();
StringWriter writer = new StringWriter(sb);
HtmlTextWriter htmlWriter = new HtmlTextWriter(writer);
deletedButton.RenderControl(htmlWriter);
string row = "<tr>";
row += "<td class=\"style5\">"+sb.toString(); +"</td>";
row += "</tr>";
This way you can get any control's HTML. :) If you are building dynamically HTML from code behind then try not to use string rather StringBuilder. strings are immutable and has performance penalty.