How to fetch data from a dynamically created textbox? - c#

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.

Related

Removing from the list with button click

I'm printing out items from the list each to the label, and a button nearby for removing them from the list. The removal button doesn't seem to work.
private void cart_Click(object sender, EventArgs e)
{
krepselioPanel.Visible = !krepselioPanel.Visible;
krepselioPav.Visible = !krepselioPav.Visible;
int i = 0;
double s = 0;
foreach (Patiekalas preke in prekes)
{
Label prekiulist = new Label();
prekiulist.Location = new Point(0, 26 * i);
prekiulist.Text = preke.GetPatiekalas() + " | " + preke.GetKaina() + "€";
prekiulist.Size = new Size(200, 20);
krepselioPanel.Controls.Add(prekiulist);
s += Convert.ToDouble(preke.GetKaina());
Button removeButton = new Button();
removeButton.Text = "x";
removeButton.Location = new Point(200, 26 * i);
removeButton.Font = new Font(FontFamily.GenericSansSerif, 9);
removeButton.Size = new Size(20, 22);
removeButton.Click += removeButton_Click;
removeButton.Tag = preke;
krepselioPanel.Controls.Add(removeButton);
i++;
}
Label suma = new Label();
suma.Location = new Point(krepselioPanel.Right - 140, 0);
suma.Font = new Font(FontFamily.GenericSansSerif, 13);
suma.Text = "Total: " + s + "€";
suma.Size = new Size(130, 25);
krepselioPanel.Controls.Add(suma);
}
private void removeButton_Click(object sender, EventArgs e)
{
Button b = (Button)sender;
Patiekalas preke = (Patiekalas)b.Tag;
prekes.Remove(preke);
cart_Click(sender, e);
cart_Click(sender, e);
}
}
Just for the interest sake I changed the functions removeButton_Click line
prekes.Remove(preke);
to
prekes.Add(preke);
and this creates a new entry to the list but removal doesn't work however.
The code doesn't seem to remove the previous controls from the panel so each time the controls are added new ones are created. If you have only one item in the cart then the next time nothing seems to happen, nothing added nor removed, but if there's multiple items they will start to multiply.
So remove the controls from the panel and then add new ones and the item will disappear.

C# winforms dynamically created button controls

I have an add user button which dynamically adds a remove button and a username textbox when the user clicks it. The user can click the button as many times as they like and the controls will continue to add.
I am having trouble with the remove button that is created dynamically. It should removed the itself and the username textbox next to it. Instead it will always remove the top row that was added. Also when you click add a new user after you have clicked remove it doesn't automatically fill the blank space - it moves the new textbox and button to the bottom line.
Here is my code:
private void AddUserbtn_Click_1(object sender, EventArgs e)
{
TextBox[] Username = new TextBox[n];
Button[] Remove = new Button[n];
int UsernameX, UsernameY, RemoveX, RemoveY;
UsernameX = 346;
UsernameY = 45;
RemoveX = 946;
RemoveY = 45;
for (int i = 0; i < n; i++)
{
Username[i] = new TextBox();
Username[i].Size = new Size(233, 26);
Username[i].Location = new Point(UsernameX, UsernameY + space);
Username[i].Font = new Font("Arial", 10);
Username[i].Name = "Username" ;
Remove[i] = new Button();
Remove[i].Location = new Point(RemoveX, RemoveY + space);
Remove[i].Text = "Remove";
Remove[i].Font = new Font("Arial", 10);
Remove[i].Size = new Size(95, 23);
Remove[i].UseVisualStyleBackColor = true;
Remove[i].Click += new EventHandler(Remove_Click);
Remove[i].Name = "Remove";
space += 35;
}
for (int i = 0; i < n; i++)
{
CaeUsersPanel.Controls.Add(Username[i]);
CaeUsersPanel.Controls.Add(Remove[i]);
}
}
private void Remove_Click(object sender, EventArgs e)
{
CaeUsersPanel.Controls.Remove(CaeUsersPanel.Controls[("Username")]);
CaeUsersPanel.Controls.Remove(CaeUsersPanel.Controls[("Remove")]);
}
Put a class variant to store Button - TextBox pair, and delete respectively. Quick tested code below - not fine tuned for memory leak / logic etc, just a sample code that fulfills your requirement.
Dictionary<Button, TextBox> pair = new Dictionary<Button, TextBox>(); // A dictionary to store the Button - TextBox pair
private void button1_Click(object sender, EventArgs e) {
int n = 3; // Added for testing
int space = 0; // Added for testing
int UsernameX, UsernameY, RemoveX, RemoveY;
UsernameX = 100; // Modified for testing
UsernameY = 45;
RemoveX = 400; // Modified for testing
RemoveY = 45;
for (int i = 0; i < n; i++) {
var Username = new TextBox();
Username.Size = new Size(233, 26);
Username.Location = new Point(UsernameX, UsernameY + space);
Username.Font = new Font("Arial", 10);
Username.Name = "Username";
var Remove = new Button();
Remove.Location = new Point(RemoveX, RemoveY + space);
Remove.Text = "Remove";
Remove.Font = new Font("Arial", 10);
Remove.Size = new Size(95, 23);
Remove.UseVisualStyleBackColor = true;
Remove.Click += new EventHandler(Remove_Click);
Remove.Name = "Remove";
Controls.Add(Username);
Controls.Add(Remove);
pair.Add(Remove, Username);
space += 35;
}
}
private void Remove_Click(object sender, EventArgs e) {
Controls.Remove((Button)sender); // Removes the delete button
Controls.Remove(pair[(Button)sender]); // Removes the textbox
pair.Remove((Button)sender); // Removes the entry in dictionary
}
Update: Another version for better memory and logic matters. Also shifts up the rest of controls up if it's the OP's desire.
int n = 3; // Added for testing, probably you already have it somewhere
int space = 0; // Added for testing, probably you already have it somewhere
// Moved for logic
// Value modified for testing
int UsernameX = 100;
int UsernameY = 45;
int RemoveX = 400;
int RemoveY = 45;
int SpaceDelta = 35; // Added for logic
List<Button> RemoveButtons = new List<Button>();
List<TextBox> UsernameTextBoxes = new List<TextBox>();
private void button1_Click(object sender, EventArgs e) {
Random rnd = new Random((int)DateTime.Now.Ticks); // Added for testing
for (int i = 0; i < n; i++) {
var Username = new TextBox();
Username.Size = new Size(233, 26);
Username.Location = new Point(UsernameX, UsernameY + space);
Username.Font = new Font("Arial", 10);
Username.Name = "Username";
Username.Text = $"{(int)(rnd.NextDouble() * 100000)}"; // Added for testing
var Remove = new Button();
Remove.Location = new Point(RemoveX, RemoveY + space);
Remove.Text = $"{(int)(rnd.NextDouble() * 100000)}"; // Modified for testing
Remove.Font = new Font("Arial", 10);
Remove.Size = new Size(95, 23);
Remove.UseVisualStyleBackColor = true;
Remove.Click += new EventHandler(Remove_Click);
Remove.Name = "Remove";
Controls.Add(Username);
Controls.Add(Remove);
RemoveButtons.Add(Remove);
UsernameTextBoxes.Add(Username);
space += SpaceDelta;
}
}
private void Remove_Click(object sender, EventArgs e) {
int idx = RemoveButtons.IndexOf((Button)sender);
// Remove button
RemoveButtons[idx].Dispose();
RemoveButtons.RemoveAt(idx);
// Remove textbox
UsernameTextBoxes[idx].Dispose();
UsernameTextBoxes.RemoveAt(idx);
// Shift controls up
for (int i = idx; i < RemoveButtons.Count; i ++) {
RemoveButtons[i].Top -= SpaceDelta;
UsernameTextBoxes[i].Top -= SpaceDelta;
}
space -= SpaceDelta;
}
Remove the two last created :
private void Remove_Click(object sender, EventArgs e)
{
this.Controls.Remove(this.Controls[this.Controls.Count - 1]);
this.Controls.Remove(this.Controls[this.Controls.Count - 1]);
}

Create labels dynamically depending of CheckedListBox c# winforms

I have a checkedListBox in a TabControl
What I want is to create a label and NumericUpDown dynamically, when User check an item of checkedListBox it will show the new label and NumericUpDown
Then , when it Unchecked this item ,The numericUpDown will be clear (empty).
Conclusion: As many checked items , as many w've create labels and NumericUpDowns.
Please, how will I do that ??
For each checkbox item in your checkedListBox in properties switch to events and create subscriber checkBoxName_CheckStateChanged for event CheckStateChanged.
The code in the sucriber can be like this:
private void checkBox1_CheckStateChanged(object sender, EventArgs e)
{
var source = sender as CheckBox;
if (source.Checked == true)
{
this.numericUpDown1.Text = "TextWhenChecked";
this.labelAtTheNumericUpDown.Text = "TextWhenChecked";
}
else
{
this.numericUpDown1.Text = "TextWhenUnchecked";
this.label1.Text = "TextWhenUnchecked";
}
}
You fill the strings as you want. These are only examples.
To have only checkBox checked at a time look at here: https://stackoverflow.com/a/24693858/6650581.
What you need to do is creating Label and NumericUpDown manually and show it by adding to Controls collection. A TableLayoutPanel can help you arranging controls without setting Size and calculate Location manually.
Here is an example:
public class MainForm : Form
{
private CheckedListBox checkedListBox;
private TableLayoutPanel tableLayoutPanel;
public MainForm()
{
InitializeComponent();
//Fill checkedListBox and create controls
for( int i = 0; i <= 5; i++ )
{
checkedListBox.Items.Add( i.ToString() );
Label lbl = new Label()
{
Name = "lbl" + i,
Text = "Label " + i,
Visible = false
};
NumericUpDown num = new NumericUpDown()
{
Name = "num" + i,
Value = i,
Visible = false
};
tableLayoutPanel.Controls.Add( lbl, 0, i );
tableLayoutPanel.Controls.Add( num, 1, i );
}
}
private void checkedListBox_ItemCheck( object sender, ItemCheckEventArgs e )
{
if( e.NewValue == CheckState.Checked )
{
tableLayoutPanel.Controls["lbl" + e.Index].Visible = true;
tableLayoutPanel.Controls["num" + e.Index].Visible = true;
}
else
{
tableLayoutPanel.Controls["lbl" + e.Index].Visible = false;
((NumericUpDown)tableLayoutPanel.Controls["num" + e.Index]).Value = 0M;
}
}
private void InitializeComponent()
{
this.checkedListBox = new System.Windows.Forms.CheckedListBox();
this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
this.SuspendLayout();
//
// checkedListBox
//
this.checkedListBox.Location = new System.Drawing.Point(8, 8);
this.checkedListBox.Name = "checkedListBox";
this.checkedListBox.Size = new System.Drawing.Size(200, 100);
this.checkedListBox.TabIndex = 1;
this.checkedListBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.checkedListBox_ItemCheck);
//
// tableLayoutPanel
//
this.tableLayoutPanel.AutoScroll = true;
this.tableLayoutPanel.ColumnCount = 2;
this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel.Location = new System.Drawing.Point(8, 112);
this.tableLayoutPanel.Name = "tableLayoutPanel";
this.tableLayoutPanel.Size = new System.Drawing.Size(200, 100);
this.tableLayoutPanel.TabIndex = 2;
//
// MainForm
//
this.ClientSize = new System.Drawing.Size(223, 227);
this.Controls.Add(this.tableLayoutPanel);
this.Controls.Add(this.checkedListBox);
this.Name = "MainForm";
this.ResumeLayout(false);
}
}

Dynamic button and create textbox

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.

How do I get the values from a dynamically created NumericUpDown?

How to get the values from dynamic NumericUpDown in C#?
Here is my code,
for (int i=0; i<n;i++)
{
NumericUpDown notele = new NumericUpDown();
notele.Name = "note" + i.ToString();
notele.Location = new System.Drawing.Point(280, 208 + (30 * i));
notele.Size = new System.Drawing.Size(40, 25);
notele.BackColor = System.Drawing.SystemColors.ControlDark;
notele.Maximum = new decimal(new int[] {10,0,0, 0});
this.Controls.Add(notele);
}
Access your controls using the Control collection of your form and pass to it the name of your numericUpDown control:
var numericUpDown = this.Controls["note0"] as NumericUpDown;
if(numericUpDown != null)
{
var value = numericUpDown.Value;
}
You can still utilise the ValueChanged event:
...
notelle.ValueChanged += UpDnValueChangedHandler;
this.Controls.Add(notele);
}
private void UpDnValueChangedHandler(object sender, EventArgs e)
{
// sender references the control which value was changed:
NumericUpDown notelle = sender as NumericUpDown;
// further processing goes here
}

Categories

Resources