I've got a question regarding textboxes in C#. I've made a button that will create textboxes when clicked:
private void helloButton_Click(object sender, EventArgs e)
{
TextBox txtRun = new TextBox();
TextBox txtRun2 = new TextBox();
txtRun2.Name = "txtDynamic2" + c++;
txtRun.Name = "txtDynamic" + c++;
txtRun.Location = new System.Drawing.Point(40, 50 + (20 * c));
txtRun2.Location = new System.Drawing.Point(250, 50 + (20 * c));
txtRun2.ReadOnly = true;
txtRun.Size = new System.Drawing.Size(200, 25);
txtRun2.Size = new System.Drawing.Size(200, 25);
this.Controls.Add(txtRun);
this.Controls.Add(txtRun2);
}
How can I pull the text which the user types into these newly generated textboxes to use it as arguments for a different function (which will be called by a different button)? I'm quite new at this and could use the help.
Thanks in advance.
var matches = this.Controls.Find("txtDynamic2", true);
TextBox tx2 = matches[0] as TextBox;
string yourtext = tx2.Text;
This will return an array of controls by the name txtDynamic2, in your case the first one would be the control you are looking for unless you create more controls having the same name.
This will allow you to fully access the textbox if you found it.
var text = (TextBox)this.Controls.Find("txtDynamic2", true)[0];
If you'd like to use the instantiated textboxes in other methods then you can achieve that by either passing them to the method, or storing them as members of your class.
Example of storing them in your class below.
public class YourForm
{
private TextBox txtRun;
private TextBox txtRun2;
private void helloButton_Click(object sender, EventArgs e)
{
txtRun = new TextBox();
txtRun2 = new TextBox();
// removed less interesting initialization for readability
this.Controls.Add(txtRun);
this.Controls.Add(txtRun2);
}
public void DoStuffWithTextBoxes()
{
if (txtRun != null && txtRun2 != null)
{
// Retrieve text value and pass the values to another method
SomeOtherMagicMethod(txtRun.Text, txtRun2.Text);
}
}
private void SomeOtherMagicMethod(string txtRunText, string txtRun2Text)
{
// Do more magic
}
}
You can do it very easily:
//get the text from a control named "txtDynamic"
string text = this.Controls["txtDynamic"].Text;
Just remember to make sure that your controls have unique Name property, otherwise You'll get the text from the first control that's found with the specified name.
Related
I'm trying to change the text of a TextBox when I click a Button: both Controls are dynamically created as run-time.
The Buttons and the TextBoxes are created every time I click on another Button.
The Name Property for each control is specified by the User, using a TextBox.
For example, the user inputs "Test1", then the Button is named btn_Test1, and the TextBox is named txt_Test1.
The Button should open a FolderBrowserDialog and after a selection has been made, the TextBox shows the path selected.
I'm using the following code:
protected void button_Click(object sender, EventArgs e)
{
Button button = sender as Button;
folderBrowserDialog.ShowDialog();
string TextName = button.Name.Replace("btn_", "txt_");
TextBox selectText = new TextBox();
selectText = this.Controls[TextName] as TextBox;
selectText.Text = folderBrowserDialog.SelectedPath;
}
however this part gives me null:
selectText = this.Controls[TextName] as TextBox;
I did check with the debugger when I create the controls, so TextName is setting the correct Name.
The Buttons and TextBoxes are inserted in a TabControls, the Tab Name is set to the value the user inputs, so the main TabControl gets 2 controls.
I'm using a hidden TabControl named "TabFolders" that will be the main reference for creating tab clones
I'm using this code:
private void CreateDynamicPathButtons(string TabName)
{
TabPage MyNewTab = new TabPage(TabName);
TabPage TabCopy1;
tabControlEmpresas.TabPages.Add(MyNewTab);
TabControl tc = new TabControl();
tc.Location = new System.Drawing.Point(6, 6);
tc.Size = TabFolders.Size;
for (int i = 0; i < TabFolders.TabCount; i++) {
TabFolders.SelectTab(i);
TabCopy1 = new TabPage(TabFolders.SelectedTab.Text);
foreach (Control c in TabFolders.SelectedTab.Controls) {
Control cNew = (Control)Activator.CreateInstance(c.GetType());
cNew.Text = c.Text;
cNew.Size = c.Size;
cNew.Location = new System.Drawing.Point(c.Location.X, c.Location.Y);
cNew.Visible = true;
if (cNew is TextBox) {
cNew.Name = "txt_" + MyNewTab.Text + "_" + TabFolders.SelectedTab.Text;
}
if (cNew is Button) {
cNew.Name = "btn_" + MyNewTab.Text + "_" + TabFolders.SelectedTab.Text;
cNew.Click += new EventHandler(button_Click);
}
TabCopy1.Controls.Add(cNew);
}
tc.TabPages.Add(TabCopy1);
}
MyNewTab.Controls.Add(tc);
}
After many attempts I did find a very simple solution.
TextBox selectText = new TextBox();
selectText = button.Parent.Controls[TextName] as TextBox;
The button parent hast all the controls.
Assuming that button is the Button control you're creating at run-time you mentioned, you're creating a TextBox control but you're not adding it to the Form.Controls collection (this.Controls.Add([Control])).
Also, you should assign a Location, using a logic that fits your current Layout, to position the newly created Controls. Otherwise, all new controls will be positioned one on top of the other. In the example, the new Control position is determined using a field (int ControlsAdded) that keeps track of the number of Controls created at run-time and add some basic layout logic.
But, if you want to keep a reference of these new Controls, you should add them to a List<Control> or some other collection that allows to select them if/when required.
int ControlsAdded = 0;
protected void button_Click(object sender, EventArgs e)
{
TextBox selectedText = new TextBox();
selectedText.Size = new Size(300, this.Font.Height);
selectedText.Location = new Point(100, ControlsAdded * selectedText.Height + 30);
ControlsAdded += 1;
this.Controls.Add(selectedText);
selectedText.BringToFront();
using (var fBD = new FolderBrowserDialog()) {
if (fBD.ShowDialog() == DialogResult.OK)
selectedText.Text = fBD.SelectedPath;
}
}
with selectText = this.Controls[TextName] as TextBox;, you are trying to find button with replaced name which is not available in this case, and hence it returns null. This is logical mistake.
also string TextName = button.Name.Replace("btn_", "txt_"); does not replace button name, it just assigns replaced string to TextName.
The proper implementation would be
protected void button_Click(object sender, EventArgs e)
{
Button button = sender as Button;
folderBrowserDialog.ShowDialog();
button.Name = button.Name.Replace("btn_", "txt_");
TextBox selectText = new TextBox();
selectText = this.Controls[button.Name] as TextBox;
selectText.Text = folderBrowserDialog.SelectedPath;
}
I have a page where n number of text boxes are created according the value n from a drop down list. My question is about accessing the values from the textboxes into string variables so that I can store them in database.
Following is the code for creating textboxes
protected void ddlNumOfVolunteers_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
// Get the number of labels to create.
int numlabels = System.Convert.ToInt32(ddlNumOfVolunteers.SelectedItem.Text);
for (int i = 1; i <= numlabels; i++)
{
Label myLabel = new Label();
TextBox txtbox = new TextBox();
// Set the label's Text and ID properties.
myLabel.ID = "LabelVol" + i.ToString();
myLabel.Text = "Volunteer " + i.ToString();
txtbox.ID = "TxtBoxVol" + i.ToString();
PlaceHolder1.Controls.Add(myLabel);
PlaceHolder2.Controls.Add(txtbox);
// Add a spacer in the form of an HTML <br /> element.
PlaceHolder2.Controls.Add(new LiteralControl("<br />"));
PlaceHolder1.Controls.Add(new LiteralControl("<br />"));
}
}
catch(Exception ex)
{
Response.Write(ex.Message);
}
}
Then when I click on the save button beneath, I want to access all the values in the dynamically created textboxes and store into a datastructure such as array.
I used the following code and I know it won't work as TxtBoxVol1 won't be available in this block. so how can I store the values in an array when in ddlNumOfVolunteers_SelectedIndexChanged function itself.
protected void btnStart_Click(object sender, EventArgs e)
{
TextBox tb = (TextBox)this.FindControl("PlaceHolder2").FindControl("TxtBoxVol1");
string vol1name = tb.Text;
}
Thanks in advance
There are oodles of ways to do this.
However, you could just store them in an array of List<T> or even a Dictionary
Dictionary<string,Textbox> myControls = new Dictionary<string,Textbox>();
...
TextBox txtbox = new TextBox();
txtbox.Id = "TxtBoxVol" + i.ToString();
myControls.Add(txtbox.Id,txtbox)
...
var myValue = myControls["TxtBoxVol1"].Text
// when you are finished
myControls.Clear();
I have a dynamically created Label, RichTextBox via a button that is constructed via array.
Label dateLabel = new Label();
dateLabel.Text = dateArray[i];
dateLabel.Name = "date" + i;
dateLabel.Location = new Point(154, 5 + (50 * i));
dateLabel.Tag = dateLabel;
dateLabel.Size = new System.Drawing.Size(91, 20);
panel1.Controls.Add(dateLabel);
RichTextBox placeTravelLabel = new RichTextBox();
placeTravelLabel.Text = placeTravelArray[i];
placeTravelLabel.Name = "placeTravel" + i;
placeTravelLabel.Location = new Point(272, 5 + (50 * i));
placeTravelLabel.Tag = placeTravelLabel;
placeTravelLabel.Size = new System.Drawing.Size(148, 45);
placeTravelLabel.ReadOnly = true;
panel1.Controls.Add(placeTravelLabel);
Button clearButton = new Button();
clearButton.Name = "clearButton" + i;
clearButton.Text = "Remove";
clearButton.Location = new Point(1200, 5 + (30 * i));
clearButton.Click += new EventHandler(this.clearButton_Click);
panel1.Controls.Add(clearButton);
Now I want them to be remove something like this.
public void clearButton_Click(object sender, EventArgs e)
{
dateLabel.Remove();
placeTravelLabel.Remove();
}
Is this possible?
Yes, it is. Try
panel1.Controls.Remove(dateLabel);
panel1.Controls.Remove(placeTravelLabel);
You obviously need to hold the references to them when you create them (i.e. declare them as fields in your class) or mark them somehow (e.g. in Tag property) and enumerate panel1.Controls to find them later.
I think it should also be possible to use closure on local instances by defining button's click event as lambda to avoid declaring those controls as fields. I do not recommend this, as typical flow is more readable and straightforward. Having said that:
Label dateLabel = new Label();
//...
panel1.Controls.Add(dateLabel);
RichTextBox placeTravelLabel = new RichTextBox();
//...
panel1.Controls.Add(placeTravelLabel);
Button clearButton = new Button();
//...
clearButton.Click += new EventHandler((s, e) =>
{
panel1.Controls.Remove(dateLabel);
panel1.Controls.Remove(placeTravelLabel);
});
panel1.Controls.Add(clearButton);
This is pseudo code built up with LinqPad but should give you enough to work with.
I assume that you are working WinForms as there is no tag to say if it is Winforms of WPF, but this is the code that you need that would remove the label for you.
var frm = new Form();
var lbl = new Label();
lbl.Name = "myLable"
frm.Controls.Add(lbl)
frm.Controls.Remove(lbl)
if you ignore the first two lines of the declarations, you simply need `FormName.Controls.Remove(LabelName)
I have the following situation:
I have 2 drop down lists (DDL) with auto-postback enabled.
When the user selects something from first DDL, he can choose stuff from 2nd DDL.
When the user selects something from 2nd DDL, I open database (WHERE clause of SQL query is filled with values from DDLs), and dynamically create several text boxes, labels and buttons which I place inside a placeholder.
The problem is: when I click on some of the dynamically created buttons, nothing happens, and I can't retrieve data from dynamically created boxes. Also, placeholder content is lost (all controls).
So my question is: how do I retain data from dynamically created controls on postback?
I have listed a lot of similar articles on this site, and none solves my problem. Another thing is - I can't use view state nor session.
Code is:
public Button btn1 = new Button();
public TextBox txtBoxC1 = new TextBox();
public TextBox txtBoxC2 = new TextBox();
public TextBox txtBoxC3 = new TextBox();
...
...
...
protected void ddl2_SelectedIndexChanged(object sender, EventArgs e)
{
...
...
if some conditions are met:
...
...
String CS4 = ConfigurationManager.ConnectionStrings["connStringName"].ConnectionString;
using (SqlConnection conn4 = new SqlConnection(CS4))
{
SqlCommand cmd4 = new SqlCommand("Select * from table where column1=" +
Convert.ToInt32(ddl2.SelectedValue)+" order by column1", conn4);
conn4.Open();
SqlDataReader rdr = cmd4.ExecuteReader();
while (rdr.Read())
{
txtBoxC1.Text = rdr["column1"].ToString(); txtBoxC1.MaxLength = 3; txtBoxC1.Columns = 3; txtBoxC1.ID = ddl2.SelectedValue + "1";
txtBoxC2.Text = rdr["column2"].ToString(); txtBoxC2.MaxLength = 3; txtBoxC2.Columns = 3; txtBoxC2.ID = ddl2.SelectedValue + "2";
txtBoxC3.Text = rdr["column3"].ToString(); txtBoxC3.MaxLength = 3; txtBoxC3.Columns = 3; txtBoxC3.ID = ddl2.SelectedValue + "3";
btn1.Text = "click me"; btn1.ID = ddl1.SelectedValue; btn1.Click += btn1_Click;
phDynamic.Controls.Add(btn1);
phDynamic.Controls.Add(txtBoxC1);
phDynamic.Controls.Add(txtBoxC2);
phDynamic.Controls.Add(txtBoxC3);
}
}
}
...
...
...
private void btn1_Click(object sender, EventArgs e)
{
Response.Write(txtBoxC1.Text+txtBoxC2.Text+txtBoxC3.Text);
}
So instead of getting back values from my 3 textboxes, I don't get back anything, and I also lose placeholder controls.
So I am trying to make a dynamic form builder where people can add a new form and add fields to that form (the add field brings up several textboxes & dropdown options for that new field). Is there any way to append to a placeholder control when clicking 'add new field'? Also, what is the best way to get the values from those dynamically added controls?
A few simple steps...
1) Create a new instance of the control. Populate any desired properties.
2) Add it to the PlaceHolder using the PlaceHolder's .Controls.Add method.
3) Add the control's event handler. By using a delegate, as shown, you can access the control's values.
DropDownList ddl = new DropDownList();
ListItem li0 = new ListItem(string.Empty, "0");
ListItem li1 = new ListItem("Hello", "1");
ListItem li2 = new ListItem("World", "2");
ddl.Items.Add(li0);
ddl.Items.Add(li1);
ddl.Items.Add(li2);
ddl.AutoPostBack = true;
PlaceHolder1.Controls.Add(ddl);
ddl.SelectedIndexChanged += delegate(object snd, EventArgs evt) { DoSomething(ddl.SelectedValue); };
public void DoSomething(string SelectedValue)
{
//Do something spectacular here...
}
This is the other option (appending to a Literal Control). Each time the user clicks a button, a new field is created. I don't know how to add those dynamic fields to the database. Should I do a foreach?
protected void Button1_Click(object sender, EventArgs e)
{
var thisstring = new StringWriter();
var writer = new HtmlTextWriter(thisstring);
var formLabel = new TextBox();
formLabel.Text = idValue.ToString();
writer.Write("Field Label:");
formLabel.RenderControl(writer);
var typeOptions = new DropDownList();
typeOptions.DataSource = getfieldtypes();
typeOptions.DataTextField = "description";
typeOptions.DataValueField = "id";
typeOptions.DataBind();
writer.Write("Field Type:");
typeOptions.RenderControl(writer);
writer.WriteBreak();
Literal1.Text += thisstring;
}