Dynamically create textbox on button click - c#

I have created a button whereby when it is clicked, it should display 3 textboxes in a row. However, every time i click the submit button, the textbox would display 2 rows(which is 6 textboxes). And subsequently increase 2 rows at every click.
Is there anyway that it could just increase one row of textbox at every click??
Here is the code infront:
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
<asp:Panel ID="Panel1" runat="server">
</asp:Panel>
</div>
</form>
Code Behind:
protected void Page_Load(object sender, EventArgs e)
{
// Add any controls that have been previously added dynamically
for (int i = 0; i < TotalNumberAdded; i++)
{
AddControls(i + 1);
}
// Attach the event handler to the button
Button1.Click += new EventHandler(Button1_Click);
}
protected void Button1_Click(object sender, EventArgs e)
{
// Increase the number added and add the new label and textbox
TotalNumberAdded++;
AddControls(TotalNumberAdded);
}
private void AddControls(int controlNumber)
{
TextBox TxtBoxU = new TextBox();
TextBox TxtBoxE = new TextBox();
TextBox TxtBoxY = new TextBox();
Label lblU = new Label();
Label lblE = new Label();
Label lblY = new Label();
TxtBoxU.ID = "TextBoxU" + controlNumber;
TxtBoxE.ID = "TextBoxE" + controlNumber;
TxtBoxY.ID = "TextBoxY" + controlNumber;
lblU.ID = "LabelU" + controlNumber;
lblE.ID = "LabelE" + controlNumber;
lblY.ID = "LabelY" + +controlNumber;
lblU.Text = "User : ";
lblE.Text = "E-Mail : ";
lblY.Text = "Phone number : ";
//Add the labels and textboxes to the Panel.
Panel1.Controls.Add(lblU);
Panel1.Controls.Add(TxtBoxU);
Panel1.Controls.Add(TxtBoxU);
Panel1.Controls.Add(lblE);
Panel1.Controls.Add(TxtBoxE);
Panel1.Controls.Add(lblY);
Panel1.Controls.Add(TxtBoxY);
Panel1.Controls.Add(new LiteralControl("<br>"));
}
protected int TotalNumberAdded
{
get { return (int)(ViewState["TotalNumberAdded"] ?? 0); }
set { ViewState["TotalNumberAdded"] = value; }
}

Your problem is in your page load, becouse your click event declaretion is redundant, you are attaching the EventHandler when you are assinging by HTML, And If you push click the event, It is fires 2 time.
Remove
Button1.Click += new EventHandler(Button1_Click);
And you page load will looks like:
protected void Page_Load(object sender, EventArgs e)
{
// Add any controls that have been previously added dynamically
for (int i = 0; i < TotalNumberAdded; i++)
{
AddControls(i + 1);
}
}
I hope that help.
P.S: I'm sorry in my first test I did not test right.

protected void Button1_Click(object sender, EventArgs e)
{
TextBox txtobj = new TextBox();
Form.Controls.Add(txtobj);
txtobj.Text = "Dynamically Textbox";
}

Related

Button Click in a TableCell never fires and table disappears

I my ASP.NET Webforms app, I have a table in which I add all data dynamically. One row contains Buttons in each cell. I want the button to fire onclick event when the user clicks on it. But, with the below code, the event never fires and the table disappears. Here's the code :
<asp:Table ID="floorTable" runat="server" Width="100%" GridLines="Both">
</asp:Table>
In Code behind
// This method is called on a DropDownList SelectedItemChanged Event - so
// the buttons cannot be created in Page_Load or so. Have to create
// totally based on the DropDown selected item.
private void PopulateFloorRow(int floorNo, FloorPattern fp)
{
int cols = fp.UnitPattern.Count;
// HEADER ROW
TableRow thead = new TableRow();
thead.Width = Unit.Percentage(100);
thead.TableSection = TableRowSection.TableHeader;
TableCell theadCell = new TableCell();
theadCell.ColumnSpan = cols;
Label title = new Label();
title.Text = "Floor # " + floorNo;
theadCell.Controls.Add(title);
thead.Controls.Add(theadCell);
TableRow planRow = GetFloorPlan(floorNo, fp);
TableRow tr = new TableRow();
TableCell tc = null;
int tcWidPerc = (int)fp.UnitPattern.Count / 100;
foreach (UnitPattern up in fp.UnitPattern)
{
tc = new TableCell();
Button imgBtn = new Button();
// On Adding BELOW Line - ERROR - 0x800a1391 - JavaScript runtime error: 'UnitLinkClicked' is undefined
//imgBtn.Attributes.Add("onClick", "UnitLinkClicked(this)");
imgBtn.CommandArgument = up.UnitPatternId.ToString(); // I want to know which button is pressed. So, sort of Tag
imgBtn.Click += new EventHandler(UnitLinkClicked);
imgBtn.BorderWidth = Unit.Pixel(10);
imgBtn.BorderColor = Color.Transparent;
imgBtn.Width = Unit.Percentage(100);
if (up.UnitNo != null)
{
imgBtn.Text = up.UnitNo;
}
tc.Controls.Add(imgBtn);
tr.Controls.Add(tc);
}
floorTable.Rows.Add(thead);
floorTable.Rows.Add(planRow);
floorTable.Rows.Add(tr);
// Create Footer
PopulateTableFooter(cols);
}
protected void UnitLinkClicked(object sender, EventArgs e)
{
Button btn = (Button)(sender);
string upId = btn.CommandArgument;
System.Diagnostics.Debug.WriteLine("LINK Button clicked Of UP ID :" + upId);
}
EDIT : CODE OF SELECTEDiNDEXCHANGED ADDED
My DropDown_SelectedIndexChanged Code :
protected void floorDropDownList_SelectedIndexChanged(object sender, EventArgs e)
{
if (selectedProject == null)
selectedProject = _db.Projects.Find(projectsList.SelectedValue);
System.Diagnostics.Debug.WriteLine("SELCTED Project = " + selectedProject.ProjectId);
// "Select Floor" is selected, so Hide floor Table
if (floorDropDownList.SelectedValue == "-1")
{
floorTable.Visible = false;
}
else
{
int floorNo = int.Parse(floorDropDownList.SelectedValue);
if (floorNo > 0)
{
PopulateFloorRow(floorNo, (FloorPattern)selectedProject.FloorPattern.ElementAt(floorNo - 1));
}
}
}
If I had selected "3" in my drop down, the table appears as expected. I click on a button and the table disappears, but the value in the drop down in still "3" only.
EDIT PART OVER
With the above code, I when I click on a button, the UnitLinkClicked event is never fired (I had added breakpoint) and the whole table disappears.
Can you say what problem can this be ? A button by default is meant to be AutoPostBack & it doesn't have that property too. What am I missing here and how to solve this. Am stuck on this since days and trying to figure out.
Any help is highly appreciated.
Thanks
You need to set an ID for your button. Without the ID the event will not be fired.
Button imgBtn = new Button();
imgBtn.ID = "imgBtn";
Also make sure that each button you add has a unique ID. You could probably concatenate the floor no. or any other fields to arrive at a unique name.
Also, the table will disappear unless, you manage that in your Page_Load. You need to reload the table if the DropDown has a selected index.
EDIT: Code Sample
.cs code
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
PopulateFloorRow();
}
}
protected void cmb_SelectedIndexChanged(object sender, EventArgs e)
{
PopulateFloorRow();
}
private void PopulateFloorRow()
{
floorTable.Rows.Clear();
for (int i = 0; i < 2; i++)
{
TableRow tableRow = new TableRow();
tableRow.Cells.Add(new TableCell());
tableRow.Cells.Add(new TableCell());
tableRow.Cells[0].Controls.Add(new Label() { Text = cmb.SelectedItem.Text });
Button button = new Button();
button.ID = "btn" + i.ToString();
button.Text = "Click";
button.Click += button_Click;
tableRow.Cells[1].Controls.Add(button);
floorTable.Rows.Add(tableRow);
}
}
void button_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
}
.aspx code
<asp:DropDownList id="cmb" runat="server" OnSelectedIndexChanged="cmb_SelectedIndexChanged" AutoPostBack="true"><asp:ListItem>One</asp:ListItem><asp:ListItem>Two</asp:ListItem></asp:DropDownList>
<asp:Table ID="floorTable" runat="server" Width="100%" GridLines="Both">
</asp:Table>

How Do I Insert Dynamically Created Textbox Values To Database

Here is my code to create dynamical textboxes..I want to insert those values to database
I need to insert the dynamically created textbox values to database.how can i do that..i am new to asp.net
Markup:
<div>
<asp:Panel ID="Panel1" runat="server" Width="300px" />
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</div>
Code-behind:
protected void Page_load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//Remove the session when first time page loads.
Session.Remove("clicks");
}
}
protected void Button1_Click(object sender, EventArgs e)
{
int rowCount = 0;
//initialize a session.
rowCount = Convert.ToInt32(Session["clicks"]);
rowCount++;
//In each button clic save the numbers into the session.
Session["clicks"] = rowCount;
//Create the textboxes and labels each time the button is clicked.
for (int i = 0; i < rowCount; i++)
{
TextBox TxtBoxU = new TextBox();
Label lblU = new Label();
TxtBoxU.ID = "TextBoxU" + i.ToString();
lblU.ID = "LabelU" + i.ToString();
lblU.Text = "Category Name " + (i + 1).ToString() + " : ";
//Add the labels and textboxes to the Panel.
Panel1.Controls.Add(lblU);
Panel1.Controls.Add(TxtBoxU);
}
}
I think you are not able to acces the value of textbox, through this you can easily access the value.
and I hompe thant u know how to insert data into data base.
for (int i = 0; i < rowCount; i++)
{
string OptionID = "TextBoxU" + i;
TextBox tb = (TextBox)Panel1.FindControl(OptionID);
/******** USe the tb.Text value to get
the value and then store it into Database**********/
}

Textbox disappears when linkbutton is clicked

I have a problem. I'm trying to make some panels, and in these panels I would like to have some linkbuttons, when the user click a linkbutton of a panel a textbox will appear in that panel, when I click in another linkbutton the textboxes of that panel also appear without problem but when I click in the other linkbutton the texboxes created in the previous panel disappears.
Here is my code:
public partial class _Default : Page
{
Label myLabel1;
Label myLabel2;
protected void Page_Load(object sender, EventArgs e)
{
myLabel1 = new Label();
myLabel2 = new Label();
Panel1.Controls.Add(myLabel1);
Panel2.Controls.Add(myLabel2);
if (!Page.IsPostBack)
{
//Remove the session when first time page loads.
Session.Remove("clicks");
Session.Remove("clicks2");
}
}
protected void LinkButton1_Click(object sender, EventArgs e)
{
int rowCount = 0;
//initialize a session.
rowCount = Convert.ToInt32(Session["clicks"]);
rowCount++;
//In each button clic save the numbers into the session.
Session["clicks"] = rowCount;
//Create the textboxes and labels each time the button is clicked.
for (int i = 0; i < rowCount; i++)
{
TextBox TxtBoxU = new TextBox();
TxtBoxU.ID = "TextBoxU" + i.ToString();
//Add the labels and textboxes to the Panel.
Panel1.Controls.Add(TxtBoxU);
}
myLabel1.Text = rowCount + "";
}
protected void LinkButton2_Click(object sender, EventArgs e)
{
int rowCount2 = 0;
//initialize a session.
rowCount2 = Convert.ToInt32(Session["clicks2"]);
rowCount2++;
//In each button clic save the numbers into the session.
Session["clicks2"] = rowCount2;
//Create the textboxes and labels each time the button is clicked.
for (int i = 0; i < rowCount2; i++)
{
TextBox TxtBoxU = new TextBox();
TxtBoxU.ID = "TextBoxU" + i.ToString();
//Add the labels and textboxes to the Panel.
Panel2.Controls.Add(TxtBoxU);
}
myLabel2.Text = rowCount2 + "";
}
}
And here is the other part:
<form id="form1" runat="server">
<p>
Part I</p>
<asp:Panel ID="Panel1" runat="server" Height="53px">
<asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click">Add to 1</asp:LinkButton>
<br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</asp:Panel>
<asp:Panel ID="Panel2" runat="server" Height="51px">
<asp:LinkButton ID="LinkButton2" runat="server" OnClick="LinkButton2_Click">Add to 2</asp:LinkButton>
<br />
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
</asp:Panel>
</form>
Since the text boxes are dynamically created, when the page loads everything needs to be re-built, but the code you posted only re-builds the text boxes for one of the panels when the particular link button for that panel is being clicked. However, your code is just building the one panel again, because that is all that your click event handlers for the link buttons are telling it to do.
I suggest combining the logic into a single method that does the building and then each link button click event handler can update its own count and pass it to the method, like this:
private void BuildTextBoxes(int rowCount1, int rowCount2)
{
for (int i = 0; i < rowCount; i++)
{
TextBox TxtBoxU = new TextBox();
TxtBoxU.ID = "TextBoxU" + i.ToString();
//Add the labels and textboxes to the Panel.
Panel1.Controls.Add(TxtBoxU);
}
myLabel1.Text = rowCount + "";
for (int i = 0; i < rowCount2; i++)
{
TextBox TxtBoxU = new TextBox();
TxtBoxU.ID = "TextBoxU" + i.ToString();
//Add the labels and textboxes to the Panel.
Panel2.Controls.Add(TxtBoxU);
}
myLabel2.Text = rowCount2 + "";
}
Now in your link button click event handlers, you will need to update the one count, but pass both to the method, like this:
protected void LinkButton1_Click(object sender, EventArgs e)
{
int rowCount = 0;
//initialize a session.
rowCount = Convert.ToInt32(Session["clicks"]);
rowCount++;
//In each button clic save the numbers into the session.
Session["clicks"] = rowCount;
BuildTextBoxes(rowCount, Convert.ToInt32(Session["clicks2"]));
}
protected void LinkButton2_Click(object sender, EventArgs e)
{
int rowCount2 = 0;
//initialize a session.
rowCount2 = Convert.ToInt32(Session["clicks2"]);
rowCount2++;
//In each button clic save the numbers into the session.
Session["clicks2"] = rowCount2;
BuildTextBoxes(Convert.ToInt32(Session["clicks1"]), rowCount2));
}
Now, whether you click the first or second link button, all of the text boxes will be recreated; with only the particular link button incrementing the number of rows.
When there is a post-back to the server following the click on the link an entirely new HTML page is generated and returned to the client. In the click event handler in your code you are adding additional controls to the ones in your aspx markup. These are then included in the HTML returned to the client. But the server is state-less and will not remember that you added these the next time there is a request from the client. You will need to add them again every time there is a post-back.
Maybe try to move your logic to add the text boxes into a separate method and then call it with the appropriate values in your click.
Something like this:
protected void LinkButton1_Click(object sender, EventArgs e)
{
int rowCount = Convert.ToInt32(Session["clicks"]) + 1;
Session["clicks"] = rowCount;
int rowCount2 = Convert.ToInt32(Session["clicks2"]) + 1;
Session["clicks2"] = rowCount2;
AddTextBoxes(rowCount, Panel1, myLabel1);
AddTextBoxes(rowCount2, Panel2, myLabel2);
}
protected void LinkButton2_Click(object sender, EventArgs e)
{
int rowCount = Convert.ToInt32(Session["clicks"]) + 1;
Session["clicks"] = rowCount;
int rowCount2 = Convert.ToInt32(Session["clicks2"]) + 1;
Session["clicks2"] = rowCount2;
AddTextBoxes(rowCount, Panel1, myLabel1);
AddTextBoxes(rowCount2, Panel2, myLabel2);
}
protected void AddTextBoxes(int numberToAdd, Panel panel, Label label)
{
//In each button clic save the numbers into the session.
numberToAdd = rowCount;
//Create the textboxes and labels each time the button is clicked.
for (int i = 0; i < rowCount; i++)
{
TextBox TxtBoxU = new TextBox();
TxtBoxU.ID = "TextBoxU" + i.ToString();
//Add the labels and textboxes to the Panel.
panel.Controls.Add(TxtBoxU);
}
label.Text = rowCount + "";
}

Click events on Array of buttons

How can I get the name of the object last clicked on a panel? The trick is there is a big array of buttons on the panel (btn[1] ... btn [200]). How can I check if I clicked on button b[180], or b[11] or even outside the panel (no button)? Also the buttons are generated at page load via coding.
Thank you. Anna
EDIT:
Thank you! Another issue that arose (this generated a NULL object reference):
I have a method on the same level as buttonHandler(), it is named HowManyClicked() and it's called from within buttonHandler(). Inside HowManyClicked() I want to identify Button btn1 = Panel2.FindControl(x) as Button; where x is, for example, buttonArray[2,3]. But I always get NULL. Is the button array buttonArray not identifiable by name once out of the method that generated it??
public void buttonHandler(object sender, EventArgs e)
{
Button btn = sender as Button;
//string tt = btn.ToolTip.ToString();
btn.BackColor = Color.Red;
statusL.Text = HowManyClicked().ToString();
}
public int HowManyClicked()
{
int sum=0;
for (int a = 0; a < 10; a++)
for (int b = 0; b < 14; b++)
{
string x = "buttonArray[" + a + ", " + b + "]";
statusL.Text = x;
Button btn1 = Panel2.FindControl(x) as Button;
if (btn1.BackColor == Color.Red) sum += 1;
}
return sum;
}
As #AVD commented you can get the button originating the postback casting the sender object, you can also use the CommandName and CommandArgument properties from the button object (they are usually used when the button is inside a Grid, DataList etc but you can use them in this context if you need):
protected void Page_Init(object sender, EventArgs e)
{
var s = Enumerable.Range(1, 10);
foreach (var item in s)
{
var b = new Button();
b.Text = "My Button " + item.ToString();
b.CommandName = "custom command";
b.CommandArgument = item.ToString();
b.Click += new EventHandler(b_Click);
this.myPanel.Controls.Add(b);
}
}
void b_Click(object sender, EventArgs e)
{
var current = sender as Button;
this.lblMessage2.Text = "Clicked from array buttons: <br/>Command Name: " + current.CommandName + "<br/>Args: " + current.CommandArgument + "<br/>Button Unique ID: " + current.UniqueID + "<br/>Client ID: " + current.ClientID;
}
Page:
<asp:Panel runat="server" ID="myPanel">
</asp:Panel>
<asp:Label ID="lblMessage2" runat="server" />
This code generates something like:
As an additional note, Microsoft recommends to create dynamic controls in the PreInit event or in case you are using a master page, in the Init event
source
Edited
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
this.ViewState["count"] = 0;
}
}
protected void Page_Init(object sender, EventArgs e)
{
var s = Enumerable.Range(1, 10);
foreach (var item in s)
{
var b = new Button();
b.Text = "My Button " + item.ToString();
b.Click += new EventHandler(buttonHandler);
this.myPanel.Controls.Add(b);
}
}
void buttonHandler(object sender, EventArgs e)
{
// update here your control
var b = sender as Button;
b.BackColor = Color.Red;
HowManyClicked();
}
private void HowManyClicked()
{
var c = (int)this.ViewState["count"];
c++;
this.ViewState["count"] = c;
this.lblMessage2.Text = "Clicked controls: " + this.ViewState["count"].ToString();
}
This produced:
How can I get the name of the object last clicked on a panel?
The first parameter of click handler returns the reference of control/object has raised the event.
public void buttonHandler(object sender, EventArgs e)
{
Button btn=sender as Button;
....
}
I just figured out another fix by just redefining HowManyClicked() so I am adding it here below. Not sure still why the first method (the one in my question) didn't work also. Here goes:
public int HowManyClicked()
{
int sum=0;
foreach (Control cnt in this.Panel2.Controls)
if (cnt is Button)
{
Button btn = (Button)cnt;
if (btn.BackColor == Color.Red)
sum += 1;
}
return sum;
}
}
Thanks everyone!

asp.net auto generated textboxes ID on webform

I am using C# on Visual Studio. I want to generate a webform with auto numbered Textboxes depending on the input from the previous page. What is the best way to do this loop?
For example:
Input is 4
The next page should generate textboxes with ID of
"name1"
"name2"
"name3"
"name4"
Something like this :
<asp:TextBox ID="name1" runat="server"></asp:TextBox>
<asp:TextBox ID="name2" runat="server"></asp:TextBox>
<asp:TextBox ID="name3" runat="server"></asp:TextBox>
<asp:TextBox ID="name4" runat="server"></asp:TextBox>
Part 2 of my question is that if I want to call them when a Button is click, how should I use a loop the get those ID?
Use for loop and PlaceHolder control to create dynamic TextBox controls
<asp:PlaceHolder ID="phDynamicTextBox" runat="server" />
int inputFromPreviousPost = 4;
for(int i = 1; i <= inputFromPreviousPost; i++)
{
TextBox t = new TextBox();
t.ID = "name" + i.ToString();
}
//on button click retrieve controls inside placeholder control
protected void Button_Click(object sender, EventArgs e)
{
foreach(Control c in phDynamicTextBox.Controls)
{
try
{
TextBox t = (TextBox)c;
// gets textbox ID property
Response.Write(t.ID);
}
catch
{
}
}
}
You could create those controls in the Page Init event handler by say loop for the number of times the control needs to made available.
Please remember since these are dynamic controls they need to be recreated during postbacks and will not be done automatically.
Further Dynamic controls and postback
Check this code.
In first page...
protected void Button1_Click(object sender, EventArgs e)
{
Response.Redirect("Default.aspx?Name=" + TextBox1.Text);
}
In second page you can get the value from querystring and create controls dynamically
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["Name"] != null)
Response.Write(Request.QueryString["Name"]);
Int32 howmany = Int32.Parse(Request.QueryString["Name"]);
for (int i = 1; i < howmany + 1; i++)
{
TextBox tb = new TextBox();
tb.ID = "name" + i;
form1.Controls.Add(tb);
}
}
for ( int i=0; i<4; i++ )
{
TextBox t = new TextBox();
t.ID = "name" + i.ToString();
this.Controls.Add( t );
}

Categories