I am trying to remove textboxes and labels one by one by pressing a button.
I have a list of textboxes called inputTextBoxes.
Here is the code for adding :
private void onClickAdd(object sender, EventArgs e)
{
inputTextBoxes = new List<TextBox>();
Label label1 = new Label();
label1.Name = "label1";
label1.Text = "w" + i;
label1.Location = new System.Drawing.Point(5, 10 + (20 * i));
label1.Size = new System.Drawing.Size(30, 20);
this.Controls.Add(label1);
TextBox text1 = new TextBox();
text1.Name = "text1";
text1.Location = new System.Drawing.Point(35, 10 + (20 * i));
text1.Size = new System.Drawing.Size(25, 20);
inputTextBoxes.Add(text1);
this.Controls.Add(text1);
i++;
}
For removing I am trying this :
private void onClickRemove(object sender, EventArgs e)
{
foreach(TextBox text1 in inputTextBoxes)
{
this.Controls.Remove(text1);
}
}
But it removes only the last textbox added,clicking againg on the button doesn't do anything.
You are constantly creating a new list in your OnClickAdd() method:
inputTextBoxes = new List<TextBox>();
Try to check if the inputTextBoxes is null and only then do this line of code. Otherwise, just let the rest of the code run.
Also, remember about clearing the inputTextBoxes list after the onClickRemove() method finishes removing textboxes/labels.
You want to remove only one TextBox at a time, why do you need a foreach loop? just grab the last or first TextBox and if it is not null remove it from the Controls:
private void onClickRemove(object sender, EventArgs e)
{
var textBoxToRemove = inputTextBoxes.LastOrDefault();
// or
// var textBoxToRemove = inputTextBoxes.FirstOrDefault();
if (textBoxToRemove != null)
{
this.Controls.Remove(textBoxToRemove);
inputTextBoxes.Remove(textBoxToRemove);
}
}
Make sure you remove it from inputTextBoxes also so the next time you will ask to remove a TextBox it will not try to remove it again and go on to the next one.
Edit
#Piotr Nowak has pointed one more problem you have, you allocate a new list for inputTextBox every time you add a new TextBox, you should allocate the list only once when you create your class.
Remove this from onClickAdd method:
inputTextBoxes = new List<TextBox>();
And use this when you declare the list as a field it your class:
private readonly inputTextBoxes = new List<TextBox>();
Related
I'm building that To-Do list app and I'm trying to create a "Add New task" button.
I wanted to create a new Task (TextBox) on the button click and also move the button bellow the TextBox added. So, I tried to create multiple panels and when the button was clicked, move the "New Task" button to the second panel and add the new textbox created to the first panel. And after that if the user wanted to remove that Task (TextBox), to repositionate the button and Tasks according to that.
Can someone please help me with that??
`
private void btnNewTask_Click(object sender, EventArgs e)
{
// Creating new Textbox
TextBox txtTask = new TextBox();
btnNewTask.Location = new Point(panel2);
// txtTask parameter
txtTask.BorderStyle = BorderStyle.None;
txtTask.ReadOnly = false;
txtTask.PlaceholderText = "Input a new Task.";
txtTask.Location = new Point(panel1);
//Adding txtTask.
this.Controls.Add(txtTask);
}
`
I founded The Solution. I deleted the panels and leaved the btnNewTask on the form.
On button click I needed to create and set the txtTask location as the btnNewTask location and change the Y location of btnNewTask to move it bellow. After that check if there was any other control that had the same or less Y location than txtTask, and if there was any, add 35 to his Y location too.
There is my new Code:
int c = 0;
private void btnNewTask_Click(object sender, EventArgs e)
{
// Creating new Textbox
TextBox txtTask = new TextBox();
// txtTask parameter
Font font = new Font("Segoe UI", 10.0f);
txtTask.Name = "txtTask" + ++c;
txtTask.BorderStyle = BorderStyle.None;
txtTask.ReadOnly = false;
txtTask.PlaceholderText = "Input a new Task.";
txtTask.Size = new Size(817, 31);
txtTask.Font = font;
txtTask.Location = new Point(btnNewTask.Location.X , btnNewTask.Location.Y); // txtTask will get the "btnNewTask" Location
btnNewTask.Location = new Point(txtTask.Location.X , btnNewTask.Location.Y + 35); // That should add 35 to the Y location
foreach (Control item in this.Controls)
{
if (item.Location.Y >= txtTask.Location.Y)
{ // if there is an item that has greater Y location
item.Location = new Point(item.Location.X, txtTask.Location.Y + 35); // It should increase its value as 35 too.
}
this.Controls.Add(txtTask);
}
There's an example:
Thank for the help and ideas!
I have really been struggling with this question for a long time.
I add a textbox and a button on tab press . I put text inside the textboxes:
Now, my question, how do I remove the textbox next to the button I click and move all the textboxes down, so I won't get any open space. If I press on the button next to the 7th textbox, I want it to look like this:
here's my code:
private void Form1_Load(object sender, EventArgs e)
{
//creates a textbox(t0) and a button(b0) on load
TextBox t0 = new TextBox();
t0.Name = "t0";
t0.Location = new Point(16, 12);
t0.Width = 200;
t0.PreviewKeyDown += new PreviewKeyDownEventHandler(PreviewKeyDown);
Button b0 = new Button();
b0.TabStop = false;
b0.Text = "x";
b0.Location = new Point(216, 11);
b0.Size = new System.Drawing.Size(20, 22);
b0.Click += new EventHandler(buttonclicked);
panel1.Controls.Add(t0);
panel1.Controls.Add(b0);
}
private new void PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
//if I press tab in the last textbox it creates a new textbox(t + amount of textboxes) and button(b + amount of textboxes)
if (e.KeyData == Keys.Tab)
{
int counter2 = 0;
foreach (TextBox box in panel1.Controls.OfType<TextBox>())
{
counter2++;
}
counter2 = counter2 - 1;
string Name = "t" + Convert.ToString(counter2);
counter2++;
foreach (TextBox box in panel1.Controls.OfType<TextBox>())
{
if (Name == box.Name && box.Focused)
{
TextBox t0 = new TextBox();
Button b0 = new Button();
t0.Location = new Point(16, 12 + counter - panel1.VerticalScroll.Value);
t0.Width = 200;
t0.Name = "t" + Convert.ToString(counter2);
t0.PreviewKeyDown += new PreviewKeyDownEventHandler(PreviewKeyDown);
b0.TabStop = false;
b0.Text = "x";
b0.Name = "b" + Convert.ToString(counter2);
b0.Location = new Point(216, 11 + counter - panel1.VerticalScroll.Value);
b0.Size = new System.Drawing.Size(20, 22);
b0.Click += new EventHandler(buttonclicked);
panel1.Controls.Add(t0);
panel1.Controls.Add(b0);
counter = counter + 25;
}
}
}
}
private void buttonclicked(object sender, EventArgs e)
{
//Remove the textbox next to it.
}
Any help is appreciated
I suggest you use a TableLayoutPanel. Set the GrowStyle on the TableLayoutPanel to AddRows or AddColumns and then you can add/remove controls to it and it will resize automatically. Set the height of each row to a number a little bigger than the height of the textbox. Set the column widths to a value so the textbox and the button can fit in them. You need 2 columns in it.
You do not need to set the location of the controls to a static location. They will be handled by the TableLayoutPanel for you.
Here is how you can add new controls to it.
yourTableLayoutPanel.Controls.Add(yourTextbox1, 0 /* Column Index */, 0 /* Row index */);
I made dynamic textboxes and keep it List
private void ConvertButton_Click(object sender, EventArgs e)
{
List<TextBox> textBoxes = new List<TextBox>();
foreach (Control item in this.Controls)
{
if (item is TextBox)
{
TextBox txt = item as TextBox;
textBoxes.Add(txt);
}
}
}
I get all of textboxes value but i have a problem. For examples; if user add 3 label like (A,B,C) and add Textboxes for them like (labelA has 2,labelB has 3,labelC has 1) and textboxes get value like array (textboxes[0] has value).The problem is i dont know which label has which value.
I added Textbox just like this:
private void addNewTextbox(object sender, EventArgs e)
{
Button button = (Button)sender;
List<TextBox> textBoxes = button.Tag as List<TextBox>;
if (textBoxes == null)
button.Tag = textBoxes = new List<TextBox>();
TextBox textBox = new TextBox();
textBoxes.Add(textBox);
textBox.Location = new Point(90 * textBoxes.Count, button.Top);
textBox.Size = new Size(50, 50);
this.Controls.Add(textBox);
}
I try to show screen for example;
LabelA-->Textbox1 , Textbox2
</br>
labelB -->Textbox3
</br>
LabelC --> Textbox4 , Textbox5 , TextBox6
Every control that is added has a Name property. Use this property to link the different controls together. For example (and you should come up with your own naming convention), you could do this:
LabelA --> TextboxA1, TextboxA2
LabelB --> TextboxB1
LabelC --> TextboxC1, TextboxC2, TextboxC3
If you wish to have a more complete (i.e. complex) solution, you could:
Create your own control that inherits from TextBox
Add a property for the name of the associated Label control
Set this property when a new control is instantiated
Label[] labelArray = new Label[10];
for (int i = 0; i < labelNumber; i++)
{
labelArray[i] = new Label();
labelArray[i].Text = states[i] + "-->";
this.Controls.Add(labelArray[i]);
labelArray[i].Top = 100 + i * 30;
labelArray[i].Left = 10;
labelArray[i].Width = 30;
}
i did label-created just like this.labelnumber is how many label user wants.#interceptwind
I am trying very hard to understand your question, I guess you are trying to link the user-created textboxes to specific labels? Forgive me if I am completely wrong. How about structure your code to something like this:
Note: Edited with OP's new code
Dictionary<Int, List<TextBox>> label_Textboxes_Dict = new Dictionary<Int, List<TextBox>>();
List<Label> labelArray = new List<Label>(); //I suggest use list as you don't know the array size beforehand
void addLabel(int labelNumber)
{
int currentLabelArrayCount = labelArray.count; //So that users can add multiple times
for (int i = currentLabelArrayCount; i < currentLabelArrayCount +labelNumber; i++)
{
labelArray.Add(new Label());
labelArray[i].Text = states[i] + "-->";
this.Controls.Add(labelArray[i]);
labelArray[i].Top = 100 + i * 30;
labelArray[i].Left = 10;
labelArray[i].Width = 30;
label_Textboxes_Dict.Add(i, new List<TextBox>());
}
}
void addTextBoxForLabel(int labelNum)
{
TextBox t1 = new TextBox();
TextBox t2 = new TextBox();
//etc...
if (label_Textboxes_Dict.ContainsKey(labelNum))
{
label_Textboxes_Dict[labelNum].Add(t1);
label_Textboxes_Dict[labelNum].Add(t2);
}
}
void doSomethingForAllTextboxesOfLabel(int labelNum)
{
List<TextBox> listOfTextBoxes;
if(label_Textboxes_Dict.TryGetValue(labelNum, out listOfTextBoxes))
{
foreach(TextBox tb in listOfTextBoxes)
{
//do your stuff
}
}
}
I have used a button for creating a set of textboxes as follows:
public partial class Form1 : Form
{
private int a = 75;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.textBox1.Location = new System.Drawing.Point(50, a);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(100, 20);
this.textBox1.TabIndex = 0;
this.Controls.Add(this.textBox1);
this.textBox2 = new System.Windows.Forms.TextBox();
this.textBox2.Location = new System.Drawing.Point(200, a);
this.textBox2.Name = "textBox2";
this.textBox2.Size = new System.Drawing.Size(100, 20);
this.textBox2.TabIndex = 0;
this.Controls.Add(this.textBox2);
this.button1.Location = new System.Drawing.Point(650, a);
a += 25;
}
}
So there might be created many textbox1 and textbox2 for many button clicks. Say 10 textbox1 and 10 textbox2. How can I get data from all of them and to store in database. each textbox1 and textbox2 to be in a row of table?
Any help will be welcomed.
First of all: I think you are looking for a DataGrid.
If not, there are several steps to be taken. First of all, textbox1 and textbox2 are members of the class and not the method, so with every click you edit the same TextBoxes again and again. To create new TextBoxes use
TextBox newBox = new TextBox();
inside the method and continue using it instead of this.textbox1 (or textbox2). Keep in mind, that you should change to Location of the TextBoxes every time you click the button so that they don't overlap. You could use a class variable as click count.
I think the easiest way would be to store the created TextBoxes in a collection, for example a Dictionary:
public partial class...
{
Dictionary<TextBox, TextBox> tbPairs = new Dictionary<TextBox, TextBox>();
private void button1_Click(...)
{
... //create newBox1 and newBox2
tbPairs[newBox1] = newBox2; //adds the Pair to the Dictionary
}
}
To recall the content of the Dictionary after the TextBoxes are filled use
foreach (KeyValuePair<TextBox, TextBox> in tbPairs)
{
... //write to Server here - but that is an issue too big for handling here - look it up
}
For how to write Data to a database check out how to use SqlCommands
Hello I am making a program that has 2 textboxes and 2 buttons
When I press the add button then it will make 2 new textboxes using this code :
private void ADD_ROW_Click(object sender, EventArgs e)
{
//Make the NEW_TEXTBOX_1
HOW_FAR += 1;
TextBox NEW_TEXTBOX_1 = new TextBox();
NEW_TEXTBOX_1.Name = "NAME_TEXTBOX_" + HOW_FAR.ToString();
//Set NEW_TEXTBOX_1 font
NEW_TEXTBOX_1.Font = new Font("Segoe Print", 9);
NEW_TEXTBOX_1.Font = new Font(NEW_TEXTBOX_1.Font, FontStyle.Bold);
//Set pos and size and then create it.
NEW_TEXTBOX_1.Location = new System.Drawing.Point(16, 71 + (35 * HOW_FAR));
NEW_TEXTBOX_1.Size = new System.Drawing.Size(178, 29);
this.Controls.Add(NEW_TEXTBOX_1);
//Make the PRICE_TEXTBOX_
TextBox NEW_TEXTBOX_2 = new TextBox();
NEW_TEXTBOX_2.Name = "PRICE_TEXTBOX_" + HOW_FAR.ToString();
//Set NEW_TEXTBOX font
NEW_TEXTBOX_2.Font = new Font("Segoe Print", 9);
NEW_TEXTBOX_2.Font = new Font(NEW_TEXTBOX_2.Font, FontStyle.Bold);
//Set pos and size and then create it.
NEW_TEXTBOX_2.Location = new System.Drawing.Point(200, 71 + (35 * HOW_FAR));
NEW_TEXTBOX_2.Size = new System.Drawing.Size(89, 29);
this.Controls.Add(NEW_TEXTBOX_2);
//Change pos of the add button
ADD_ROW.Location = new System.Drawing.Point(295, 71 + (35 * HOW_FAR));
this.Height = 349 + (35 * HOW_FAR);
this.Width = 352;
}
This works very well but now I want to get the text from a newly made textbox back how do I do this?
This doesn't work because it says : NAME_TEXTBOX_1 Does not exist in the current context.
private void button2_Click(object sender, EventArgs e)
{
string tmpStr = NAME_TEXTBOX_1.Text;
}
You need to move the variable declaration outside of the ADD_ROW_Click event handler so that it's accessible outside that block;
TextBox NEW_TEXTBOX_1;
private void ADD_ROW_Click(object sender, EventArgs e)
{
//Make the NEW_TEXTBOX_1
HOW_FAR += 1;
NEW_TEXTBOX_1 = new TextBox(); //remove "TextBox" since we declared it above
NEW_TEXTBOX_1.Name = "NAME_TEXTBOX_" + HOW_FAR.ToString();
//...
The alternative, and possibly better depending on the number of textboxes, is to add each TextBox you create into a List. You can then iterate that List from and find the TextBox you want. For example
List<TextBox> allTextBoxes = new List<TextBox>();
private void ADD_ROW_Click(object sender, EventArgs e)
{
//Make the NEW_TEXTBOX_1
HOW_FAR += 1;
TextBox NEW_TEXTBOX_1 = new TextBox();
//...fill out the properties
//add an identifier
NEW_TEXTBOX_1.Tag = 1;
allTextBoxes.Add(NEW_TEXTBOX_1);
}
Then when you want a particular TextBox
private void button2_Click(object sender, EventArgs e)
{
TextBox textBox1 = allTextBoxes.Where(x => x.Tag == 1).FirstOrDefault();
string tmpStr = "";
if(textBox1 != null)
tmpStr = textBox1.Text;
}
Alternatively, and especially if you're going to have a lot of TextBoxes, you could store them in a Dictionary as Corak suggested in the comments.
you're declaring NAME_TEXTBOX_1 within the ADD_ROW_Click method, which is why it isn't available within the button2_Cick method.
You can declare the textbox at the class level to access it in both places.
(You should work on renaming your variables too - e.g. TextBoxPrice)
One simple solution:
Make a private field called "NEW_TB" for example.
In your button2_Click(..) { string tmpStr = NEW_TB.Text; }
Add in your ADD_ROW_Click(..) method NEW_TB = NAME_TEXTBOX_1;
If I understood your question right, this should work.
Make global your textboxes:
TextBox NEW_TEXTBOX_1;
then initiate them in your method:
NEW_TEXTBOX_1 = new TextBox();
OMG Never mind sorry guys I found a good way :D
var text = (TextBox)this.Controls.Find("PRICE_TEXTBOX_1", true)[0];
text.Text = "PRO!";
This works pretty well :)