Dynamic button and create textbox - c#

I have a textbox and button on c# form and users can enter number.I create a label which users want and each label have a button.Here if I click those buttons i wanna create textbox but if users continue to click,i want to create more textbox.
Button[] Btn= new Button[10];
for (int i = 0; i < labelNumber; i++)
{
Btn[i] = new Button();
Btn[i].Text = "Add";
Btn[i].Location = new Point(40, 100 + i * 29);
Btn[i].Size = new Size(50,20);
this.Controls.Add(Btn[i]);
Btn[i].Click += new EventHandler(addNewTextbox);
}
on the code above; for example; if labelNumber == 3 so i have 3 label and 3 button with them, if i click add button i wanna create textbox near thislabel.
private void addNewTextbox(object sender, EventArgs e)
{
TextBox[] dynamicTextbox = new TextBox[10];
Button dinamikButon = (sender as Button);
int yLocation = (dinamikButon.Location.Y - 100) / 29;
//int xLocation = dinamikButon.Location.X - 100;
dynamicTextbox[yLocation] = new TextBox();
dynamicTextbox[yLocation].Location = new Point(100, 100 + yLocation * 29);
dynamicTextbox[yLocation].Size = new Size(40, 50);
this.Controls.Add(dynamicTextbox[yLocation]);
}
here i change textbox y coordinates but i couldn't it for X. if i change this
dynamicTextbox[yLocation].Location = new Point(100*x, 100 + yLocation * 29);
x++;
it sort equals all of them.
Label1 Button1
Label2 Button2
Label3 Button3
if i click Button1 4 times,it has to create 4 textbox alongside label1. and if i click Button2 2 times,it has to create 2 textbox alongside label2
Please Help ME.

The simplest way is to keep a list containing the created textboxes in the button's Tag property like this
private void addNewTextbox(object sender, EventArgs e)
{
var button = (Button)sender;
var textBoxes = button.Tag as List<TextBox>;
if (textBoxes == null)
button.Tag = textBoxes = new List<TextBox>();
var textBox = new TextBox();
textBoxes.Add(textBox);
textBox.Location = new Point(100 * textBoxes.Count, button.Top);
textbox.Size = new Size(40, 50);
this.Controls.Add(textBox);
}
This way you not only can add a new text box, but also can easily determine the created text boxes by each button at any time if needed.

Related

Creating a new control property for certain amount of time in C# Winform

Say if I want to create a multiple button on my form based on a loop value of 3 then 3 buttons should be created into that form, in my case I have this textbox input that should determine the loop value on button click. What I've tried:
void Button4Click(object sender, EventArgs e)
{
int get_col_range = Convert.ToInt32(textBox3.Text);
for(int i=0; i<get_col_range; i++) {
Button btn = new Button();
btn.Text = Convert.ToString(i);
this.Controls.Add(btn);
}
}
I put on value of 2 on the TextBox input as test value but turned out that nothing happened why?.
Try the following on a form with no controls in a button click event.
int top = 10;
int heightPadding = 30;
for (int index = 0; index < 3; index++)
{
var button = new Button()
{
Text = $"Button {index}",
Name = $"Button{index}",
Location = new Point(10, top)
};
Controls.Add(button);
top += heightPadding;
}

C# activeform controls property

I am unable to get the controls count on the newly created form on the newly created button, I have created 5 controls but only one is showing. If I cannot get the total control count then I cannot also get the control type, name etc.
private void button2_Click(object sender, EventArgs e)
{
Form frm = new Form();
frm.Text = "new form";
TableLayoutPanel tlp = new TableLayoutPanel();
tlp.AutoSize = true;
Button btn = new Button();
btn.Text = "ok";
tlp.Controls.Add(btn, 0, 4);
frm.Controls.Add(tlp);
for (int i = 3, ii = 0; i >= 0; i--, ii++)
{
TextBox tbx = new TextBox();
tlp.Controls.Add(tbx, 0, ii);
}
frm.Show();
string str = frm.Controls.Count.ToString();
btn.Click += (s, args) =>
{
MessageBox.Show(frm.Text);
MessageBox.Show(ActiveForm.Text);
MessageBox.Show(str);
};
}
In your code the only Control that you've added to your form is a TableLayoutPanel that contains TextBox controls. That is why the count is 1.

We have a number of buttons being created on runtime as anonymous objects.Can we add an onlick event on those buttons?

As the title says i have buttons being created as anonymous objects after an event occurs(the click of another button).What i am trying to do is to make this buttons show a Messagebox when they are being clicked.I can't add this functionality to the buttons and i haven't found anything that solves my problem.Maybe it just can't happen this way.
Controls.Add(new Button { Size = new Size(50, 50),
Location = new Point(40 + i * 60, 100),
Text = i.ToString(),
BackColor = c,
//eventforshowingmessage()
});`
You could assign button to variable first, and then register event:
public AddButton()
{
var newButton = new Button { Text = "Button 1" };
newButton.Click += MyEventListener;
this.Controls.Add(newButton);
}
private void MyEventListener(object sender, EventArgs e)
{
var button = (Button)sender;
MessageBox.Show($"{button.Text} says: Hello, world");
}
I suggest a different syntax: Parent instead of Controls.Add:
for (int i ....) { // whatever loop
...
new Button {
Size = new Size(50, 50),
Location = new Point(40 + i * 60, 100),
Text = $"{i}", // May appear more readable than i.ToString()
BackColor = c,
Parent = this, // <- instead of this.Controls.Add
}.Click += eventforshowingmessage;
...
}
Demo: For instance, let's create 5 buttons and show up which button has been clicked:
for (int i = 0; i < 5; ++i) {
new Button {
Size = new Size(50, 50),
Location = new Point(40 + i * 60, 100),
Text = $"{i}",
BackColor = SystemColors.Control,
Parent = this,
}.Click += (ss, ee) => {
// Lambda: what shall we do on click
MessageBox.Show($"{(ss as Control).Text} clicked!");
};
}

How to fetch data from a dynamically created textbox?

This is a follow up question for my previous question.
However in this question, I created such a Control so whenever I click on the button, two TextBoxes will appear (Indefinite count/click) in a row. Whenever I input again a value, they will do the addition and put the result in the third TextBox of their row.
private void buttonNewRow_Click(object sender, EventArgs e)
{
int count = 1;
DateTimePicker date = new DateTimePicker();
count = panel1.Controls.OfType<DateTimePicker>().ToList().Count;
date.Location = new Point(0, 15 * count);
date.Size = new Size(91, 20);
panel1.Controls.Add(date);
//Textbox 1
TextBox textboxTranspo = new TextBox();
textboxTranspo.Location = new Point(576, 45 * count);
textboxTranspo.Size = new Size(81, 20);
panel1.Controls.Add(textboxTranspo);
//Textbox 2
TextBox textboxDaily = new TextBox();
textboxDaily.Location = new Point(663, 45 * count);
textboxDaily.Size = new Size(81, 20);
panel1.Controls.Add(textboxDaily);
//Textbox 1 + Textbox 2 result
TextBox textboxTotal = new TextBox();
textboxTotal.Location = new Point(772, 45 * count);
textboxTotal.Size = new Size(100, 20);
panel1.Controls.Add(textboxTotal);
}
How can I accomplish this?
You can add event handlers like this:
private void buttonNewRow_Click(object sender, EventArgs e)
{
DateTimePicker date = new DateTimePicker();
int count = panel1.Controls.OfType<DateTimePicker>().ToList().Count;
date.Location = new Point(0, 15 * count);
date.Size = new Size(91, 20);
panel1.Controls.Add(date);
//Textbox 1
TextBox textboxTranspo = new TextBox();
textboxTranspo.Location = new Point(576, 45 * count);
textboxTranspo.Size = new Size(81, 20);
panel1.Controls.Add(textboxTranspo);
//Textbox 2
TextBox textboxDaily = new TextBox();
textboxDaily.Location = new Point(663, 45 * count);
textboxDaily.Size = new Size(81, 20);
panel1.Controls.Add(textboxDaily);
//Textbox 1 + Textbox 2 result
TextBox textboxTotal = new TextBox();
textboxTotal.Location = new Point(772, 45 * count);
textboxTotal.Size = new Size(100, 20);
panel1.Controls.Add(textboxTotal);
EventHandler textChanged = (o, e) => {
int intTranspo, intDaily;
if (int.TryParse(textboxTranspo.Text, out intTranspo)
&& int.TryParse(textboxDaily.Text, out intDaily))
textboxTotal.Text = (intTranspo + intDaily).ToString();
};
textboxTranspo.TextChanged += textChanged;
textboxDaily.TextChanged += textChanged;
}
I will address my comment above as an answer.
First you have to define a UserControl and named it whatever you like but let us name it Uc1.
In the designer drag the datetimepicker and the 3 textboxes to the Uc1. Supposed we name the control dt1 for datetimepicker and txtTranspo for textbox1 and txtDaily for textbox2 and txtTotal for the last one. And since we need to compute the value of txtTranspo and txtDaily i want to add 1 button named btnCompute for computation logic for simplicity sake.
then inside the Uc1
class Uc1
{
public Uc1()
{
InitializeComponent();
this.wireEvents();
}
// This will handle all controls events for well organized form sakes.
private void wireEvents()
{
this.btnCompute.Click += OnBtnComputeEvent;
}
private void OnBtnComputeEvent(object sender, EventArgs e)
{
// i used int since i do not know exactly how to do this.
int transpo = Int32.Parse(this.txtTranspo.Text);
int daily = Int32.Parse(this.txtDaily.Text);
double total = ((transpo + daily) / 100 * 100) // <--- this is just a random computation.
this.txtTotal.Text = string.Format("{0:c}", total); // this will format the total to a currency.
}
}
Then build the solution. or click the combination of Ctrl + Shift + B. After this the Uc1 will appear to your toolbox as a new control.
Then you can simply do this to your own logic.
private void buttonNewRow_Click(object sender, EventArgs e)
{
Uc1 c = new Uc1();
c.Dock = DockStyle.Top;
c.BringToFront();
this.panel.Controls.Add(c);
}
You are good to go.

Adding textboxes over the panel height

So I need to add textboxes to a panel with a click of a button. Every click adds one textbox under the last one and so on. But when it goes over the panel height it suddenly makes bigger space between the texboxes even though the int is still the same.
Here's my code so far.
List<TextBox> textboxes = new List<TextBox>();
private void button1_Click(object sender, EventArgs e)
{
tbY += 30;
TextBox tb = new TextBox();
tb.Left = 3;
tb.Top = tbY;
tb.Font = new Font("Verdana", 12, FontStyle.Bold);
tb.Size = new Size(325, 25);
tb.BorderStyle = BorderStyle.None;
button1.Top = tbY;
panel1.Controls.Add(tb);
textboxes.Add(tb);
ScrollToBottom(panel1);
}
The Top of a Control is calculated relative to the scroll position of its Parent.
You are always scrolling to the bottom of your Panel, so you need to set it like this, taking the curent scroll position into account:
tb.Top = tbY + panel1.AutoScrollPosition.Y;
Note that the AutoScrollPosition.Y is negative when you have scrolled downward, so we need to add it!
You might as well use a flowLayoutPanel for this purpose. Use the following properties on your flowLayoutPanel and it'll work as you intend. (without having to do the manual calculation)
List<TextBox> textboxes = new List<TextBox>();
public Form1()
{
InitializeComponent();
flowLayoutPanel1.FlowDirection = FlowDirection.TopDown;
flowLayoutPanel1.WrapContents = false;
flowLayoutPanel1.AutoScroll = true;
}
private void button1_Click(object sender, EventArgs e)
{
TextBox tb = new TextBox();
tb.Left = 3;
tb.Font = new Font("Verdana", 12, FontStyle.Bold);
tb.Size = new Size(325, 25);
tb.Text = tb.Top.ToString();
tb.BorderStyle = BorderStyle.None;
flowLayoutPanel1.Controls.Add(tb);
textboxes.Add(tb);
}

Categories

Resources