I've generated some textboxes and i want to the user input data in them after it added to form and then i use the data in them for some calculations.
how can i use the data?
TextBox t3 = new TextBox();
t3.Top = 222 + ((addalternativebutton - 3) * 60);
t3.Left = 214;
t3.Width = 76;
t3.Height = 22;
t3.Name = "txtwaste" + addalternativebutton.ToString();
this.tabore.Controls.Add(t3);
ww[addalternativebutton] = Convert.ToDouble(t3.Text);
As I mentioned in the comments you need to preserve the textbox instances which you are creating dynamically. You can either use generic dictionary, if you need to deal with the names assigned to them or you can use generic list.
Following solution I provide you which uses generic list.
First thing needed is a list which will preserve the textboxes.
public partial class Form1 : Form
{
private List<TextBox> textBoxes;
private int textBoxCount; //This is used to provide unique names to the
//textboxes and to track the number of dynamic textboxes.
public Form2()
{
InitializeComponent();
}
}
Now in click event of the button the textbox is created, positioned and added to the list as well as Form.Controls.
private void button1_Click(object sender, EventArgs e)
{
textBoxCount += 1;
TextBox t3 = new TextBox();
t3.Top = 20 + (22 * textBoxCount); //You can put your own logic to set the Top of textbox.
t3.Left = 120;
t3.Width = 50;
t3.Height = 20;
t3.Name = "txtwaste" + textBoxCount; //You can use your own logic of creating new name.
this.Controls.Add(t3);
this.textBoxes.Add(t3);
}
Now when you want to calculate the sum of the values of all the textboxes on click of another button.
private void button2_Click(object sender, EventArgs e)
{
double totalValue = 0;
foreach (var textBox in textBoxes)
{
double currentValue;
if (double.TryParse(textBox.Text, out currentValue))
{
totalValue += currentValue;
}
}
// Displaying totalValue in a label.
lblTotalValue.Text = "Total Value : " + totalValue;
}
This should help you resolve your issue.
Related
I have a windows form in C# project that keeps some information. I created a bunch of textbox and combobox dynamically, depend upon user input.
So here there is two rows since user has given the input as 2. All the components in the image are dynamically created. For each component i have created a class to set the property and its behaviour.
Now the issue is I need to traverse the component using tab.
When i tried to set tabindex = 1 for the first textbox and tabindex = 2 for the second textbox. I'm traversing the components vertically like mentioned below
Actual Output : enter image description here
The code in which i have added are following.
public class addDynamicCptboxComponents : add_components
{
public override void add_dynamic_components(int getNoOfTxtBox, int pointX, int pointY, Form1 f)
{
TextBox txtBox = new TextBox();
f.panel1.Controls.Add(txtBox);
txtBox.Location = new Point(pointX, pointY);
txtBox.Size = new System.Drawing.Size(75, 23);
f.panel1.Controls.Add(txtBox);
txtBox.Name = "Add_txtBox" + getNoOfTxtBox;
//assigned the tabindex as 2 for the second textbox
txtBox.TabIndex = 2;
}
}
public class addDynamicDateofServiceComponents : add_components
{
public override void add_dynamic_components(int getNoOfTxtBox, int pointX, int pointY, Form1 f)
{
TextBox txtBox = new TextBox();
f.panel1.Controls.Add(txtBox);
txtBox.Location = new Point(pointX, pointY);
txtBox.Size = new System.Drawing.Size(75, 23);
f.panel1.Controls.Add(txtBox);
txtBox.Name = "Add_dos_txtBox" + getNoOfTxtBox;
//assigned the tabindex as 1 for first textbox
txtBox.TabIndex = 1;
}
}
But what i need is , I need to traverse the components horizontally as mentioned below.
Expected Ouput: enter image description here
The Requried tab order is specified in the above image.
Guessing from the name of your class you are adding rows dynamically to your form. But since you are hard coding the tab index the result per row looks like in your expected output. This means by tabbing you go from index 1 to index 1 to index 2 to index 2 and so on and so forth.
I'd advise you to have an incrementing tab index stored somewhere in your application which is incremented after it is assigned to a new dynamically created control.
As a really simple example I created a fresh forms project which just has two buttons. The first one adds a new textbox and the second button switches into a new row. And in this example everything has the tab index you require. The code behind looks like this:
public partial class Form1 : Form
{
private int currentX = 0;
private int currentY = 0;
private const int tbWidth = 75;
private const int tbHeight = 23;
private int currentTabIndex = 0;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var textBoxOne = new TextBox();
this.Controls.Add(textBoxOne);
textBoxOne.Location = new Point(this.currentX, this.currentY);
textBoxOne.Size = new Size(tbWidth, tbHeight);
textBoxOne.TabIndex = currentTabIndex;
textBoxOne.Text = $"{currentTabIndex}";
currentTabIndex++;
this.currentX += tbWidth + 5;
}
private void button2_Click(object sender, EventArgs e)
{
currentY += tbHeight + 5;
currentX = 0;
}
}
Please bare in mind this is just a simple example. I could help you better in the context of your application if I knew more about it.
Hey guys/girls I got myself stuck and I was hoping I could get some help with it. simply said I'm trying to make a soccerpool on windows form. Because the player can put in as many team's as he/she wants I put the code that makes the betting panels in a (for)loop with the text as 0. very handy if I say so myself but now I can't retrieve the correct input from the user or without breaking the loop. any idea's?
for (int i = 0; i < hometable.Rows.Count; i++)
{
DataRow dataRowHome = hometable.Rows[i];
DataRow dataRowAway = awayTable.Rows[i];
Label lblHomeTeam = new Label();
Label lblAwayTeam = new Label();
TextBox txtHomePred = new TextBox();
TextBox txtAwayPred = new TextBox();
lblHomeTeam.TextAlign = ContentAlignment.BottomRight;
lblHomeTeam.Text = dataRowHome["TeamName"].ToString();
lblHomeTeam.Location = new Point(15, txtHomePred.Bottom + (i * 30));
lblHomeTeam.AutoSize = true;
txtHomePred.Text = "0";
txtHomePred.Location = new Point(lblHomeTeam.Width, lblHomeTeam.Top - 3);
txtHomePred.Width = 40;
txtAwayPred.Text = "0";
txtAwayPred.Location = new Point(txtHomePred.Width + lblHomeTeam.Width, txtHomePred.Top);
txtAwayPred.Width = 40;
lblAwayTeam.Text = dataRowAway["TeamName"].ToString();
lblAwayTeam.Location = new Point(txtHomePred.Width + lblHomeTeam.Width + txtAwayPred.Width, txtHomePred.Top + 3);
lblAwayTeam.AutoSize = true;
pnlPredCard.Controls.Add(lblHomeTeam);
pnlPredCard.Controls.Add(txtHomePred);
pnlPredCard.Controls.Add(txtAwayPred);
pnlPredCard.Controls.Add(lblAwayTeam);
So what my end goal is, is recieving the input from the user validating them and then storing them in a database.
Well, depending on how the user activates an event that requires the reading of the TextBox you have a few possible solutions.
Here is one where the TextBox (read all TextBox's) waits for enter:
private void Form_Load(object sender, EventArgs e)
{
while(someLoop)
{
TextBox theTextBox = new TextBox();
theTextBox.Name = "SomeUniqeName";//Maybe team name?
theTextBox.KeyUp += TheTextBox_KeyUp;
}
}
private void TheTextBox_KeyUp(object sender, KeyEventArgs e)
{
if ( e.KeyCode == Keys.Enter )
{
TextBox textbox = (TextBox) sender;//Get the textbox
//Just an example
listOfTeams.First( r => r.TeamName == textbox.Name )
.SomeOtherProperty = textbox.Text;
}
}
The textbox's are now identifiable by their name and all have an event. No matter how many you make.
If you will store the data later with 1 click of a button (and another loop) this solution might be better:
string[] Teams = { "teamA", "teamB", "teamC" };
private void Form1_Load(object sender, EventArgs e)
{
for ( int i = 0; i < Teams.Length; i++ )
{
TextBox theTextBox = new TextBox();
//Prefix the name so we know this is a betting textbox
//Add the 'name' (teams[i] in this case) to find it
theTextBox.Name = "ThePrefix" + Teams[i];
}
}
private void someButton_Click(object sender, EventArgs e)
{
//We want all betting textbox's here but also by team name
for ( int i = 0; i < Teams.Length; i++ )
{
//Because we set the name, we can now find it with linq
TextBox textBox = (TextBox) this.Controls.Cast<Control>()
.FirstOrDefault( row => row.Name == "ThePrefix" + Teams[i] );
}
}
This way each textbox is identifiable and won't conflict with other textbox's (because of 'ThePrefix'). This is essentially the other way around from the first method as it looks for the textbox based on data rather than data based on textbox name.
In my main form I have a textbox namely textBoxTotalTotal and I want all the dynamically added textbox to be the added/sum in my textBoxTotalTotal How can I achieve that?
In my main form I have this:
textBoxTotalTotal
Then in my User Control I have this
public void textBoxTranspo_TextChanged(object sender, EventArgs e)
{
int intTranspo = 0, intBoxDaily = 0;
if (int.TryParse(textBoxTranspo.Text, out intTranspo) && int.TryParse(textBoxDaily.Text, out intBoxDaily))
textBoxTotalAmount.Text = (intTranspo + intBoxDaily).ToString();
}
and
public void textBoxDaily_TextChanged(object sender, EventArgs e)
{
int intTranspo = 0, intBoxDaily = 0;
if (int.TryParse(textBoxTranspo.Text, out intTranspo) && int.TryParse(textBoxDaily.Text, out intBoxDaily))
textBoxTotalAmount.Text = (intTranspo + intBoxDaily).ToString();
}
Note that I am dynamically adding that User Control via button in the main form as many times I like. So the textBoxTotalTotal should just add them up wheter a new 2 textbox comes up.
Assuming that UserControls' Parent is Form1 and User Control type MyUserControl:
(You should set the correct parent, and user control type)
MyUserControl[] controls = Form1.Controls.OfType<MyUserControl>().ToArray();
int Total = 0;
for(int i=0;i<controls.Length;i++){
controls[i].Controls.OfType<TextBox>().ToList()
.ForEach(txt => Total += int.Parse(txt.Text));
}
If you are doing it from the UserControl itself then:
MyUserControl[] controls = Parent.Controls.OfType<MyUserControl>().ToArray();
int Total = 0;
for(int i=0;i<controls.Length;i++){
controls[i].Controls.OfType<TextBox>().ToList()
.ForEach(txt => Total += int.Parse(txt.Text));
}
I've ran into quite an annoying problem.
I've got these global variables (for keeping the name etc)
List<object> NumeriekVakken = new List<object>();
List<decimal> bedragenLijst = new List<decimal>();
List<string> namenlijstVanNumericFields = new List<string>();
List<string> namenLijst = new List<string>();
Afterwards I have a function that makes NumericUpDowns, depending on the number of records in the db.
The function looks like this:
private void InitializeComponentControlArrayKnoppenTextboxenEnLabels()
{
foreach (DataRow dr in blCategorie.getAlleCategorieenMetLimieten())
{
double limiet = (double) dr.Field<double>("maximumBedrag");
NumericUpDown numeriekVak = new NumericUpDown();
numeriekVak.Name = "numeriekvak" + i;
numeriekVak.Width = 100;
numeriekVak.Maximum = 30000;
numeriekVak.Minimum = 0;
numeriekVak.Increment = 10;
numeriekVak.Value = Convert.ToDecimal(limiet);
numeriekVak.Location = new Point(250, beginhoogte + verhogenMet);
this.Controls.Add(numeriekVak);
NumeriekVakken.Add(numeriekVak);
bedragenLijst.Add(numeriekVak.Value);
namenlijstVanNumericFields.Add(numeriekVak.Name);
namenLijst.Add(categorie);
//to make unique names for my Numerics etc.
i++;
counter++;
//click event aanmaken
button.Click += new EventHandler(buttonWijzig_Click);
}
}
And in the ending I want to update a record whenever the numericUpDown is changed by the user (by clicking on the numericupdown or changing the numbers)
private void buttonWijzig_Click(object sender, EventArgs e)
{
Button knop = (Button)sender;
NumericUpDown numeriekvak = (NumericUpDown)sender;
for (int i = 0; i < counter; i++)
{
if (knop.Name == "knop" + i)
{
int id = i, maximumBedrag = 0;
if (namenlijstVanNumericFields[i] == "numeriekvak" + i)
{
// update limit
DBManager.LimietRow limiet = new DBManager.LimietDataTable().NewLimietRow();
maximumBedrag = Convert.ToInt32(numeriekvak.Value);
blLimiet.updateLimiet(id, maximumBedrag);
}
labelBevestigingLimiet.Text = "Limiet " + namenLijst[i].ToString() + " is succesvol gewijzigd naar " + maximumBedrag + "€";
//stopping of loop if right button is found.
break;
}
}
}
But evertime I run this I get the same problem..
"Can't convert the object from the type System.Windows.Forms.Button to the type
System.Windows.Forms.NumericUpDown"
How can I fix this and update the record depending on the new number thats filled in on the NumericUpDown? I can't get this working, I've got a feeling it has to do with the sender thats not working good..
Thanks for all the help!
Yenthe
You have assigned the event handler buttonWijzig_Click to a control button.
This control is not defined anywhere in your code above.
(By the way, you assign the method at the same control for every loop)
I think you want to assign your event handler to every NumericUpDown created in the loop as
numeriekVak.Click += new EventHandler(buttonWijzig_Click);
Of course the event handler now receives a NumericUpDown control in the sender argument and not a button, so the code of the event handler should be changed accordingly
private void buttonWijzig_Click(object sender, EventArgs e)
{
NumericUpDown numeriekvak = (NumericUpDown)sender;
int id = 0, maximumBedrag = 0;
// The ID could be extracted from the control name starting at 11 position
id = Convert.ToInt32(numeriekvak.Name.Substring(11));
// update limit
DBManager.LimietRow limiet = new DBManager.LimietDataTable().NewLimietRow();
maximumBedrag = Convert.ToInt32(numeriekvak.Value);
blLimiet.updateLimiet(id, maximumBedrag);
// The control name is already available, no need to use the list to retrieve it
labelBevestigingLimiet.Text = "Limiet " + numeriekVak.Name + " is succesvol gewijzigd naar " + maximumBedrag + "€";
}
However, let me say that for your stated purpose:
And in the ending I want to update a record whenever the numericUpDown
is changed by the user (by clicking on the numericupdown or changing
the numbers)
it is better to use the ValueChanged event because this will be fired also when the user changes the value manually and not with up/down buttons. The code above will fit as well for the ValueChanged event
EDIT
Based on your comment below then the assignment of the event handler goes back to the button (there is no code to create the button, so I have assumed that you have followed the same naming convention as for yours NumericUpDown), but insted of using a list to keep track of your NumericUpDown I would use a Dictionary<int, NumericUpDown> where the integer is the id needed to retrieve the corresponding NumericUpDown from the button name.
In declaration change
Dictionary<int, NumericUpDown> NumeriekVakken = new Dictionary<int, NumericUpDown> ();
In Initialization inside InitializeComponentControlArrayKnoppenTextboxenEnLabels change
namenlijstVanNumericFields.Add(i, numeriekVak);
In button click code
private void buttonWijzig_Click(object sender, EventArgs e)
{
Button knop = sender as Button;
int id = 0, maximumBedrag = 0;
// The ID could be extracted from the control name starting at 4th position
id = Convert.ToInt32(knop.Name.Substring(4));
// The ID is the key to find the corresponding NUmericUpDown in the dictionary
NumericUpDown numeriekvak = NumeriekVakken[id];
// update limit
DBManager.LimietRow limiet = new DBManager.LimietDataTable().NewLimietRow();
maximumBedrag = Convert.ToInt32(numeriekvak.Value);
blLimiet.updateLimiet(id, maximumBedrag);
// The control name is already available, no need to use the list to retrieve it
labelBevestigingLimiet.Text = "Limiet " + numeriekVak.Name + " is succesvol gewijzigd naar " + maximumBedrag + "€";
}
The problem is: since you event is fired by a button, you cannot convert the sender to numeric updown.
I see you have only one button and it's not declared in you code.
I assume it's in the form, right???
Did you mean to add that click event many times to a single button???
Or did you mean to add events to each NumericUpDown???
If it's the second option, you should add the click event to each numeric updown.
See this line in your code.
//click event aanmaken
button.Click += new EventHandler(buttonWijzig_Click);
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if(e.RowIndex >= 0) {
DataGridViewRow row = this.dataGridView1.Rows[e.RowIndex];
iD_supplierNumericUpDown.Value = row.Cells["ID"].Selected(); // this is the problem
nSupplierTextBox.Text = row.Cells["NSupplier"].Value.ToString();
e_mailTextBox.Text = row.Cells["E_mailTextBox"].Value.ToString();
phoneTextBox.Text = row.Cells["Phone"].Value.ToString();
}
I created an array of of TextBoxes and an array of Labels. When the information is updated in the TextBox I want it to change the Labels. How would I be able to do this? Below is piece of my code. I have not created the EvenHandler that I think is the part I need help with. All in C# using windows application form.
textBoxes = new TextBox[value];
labels = new Label[value];
for (int i = 1; i < value; i++)
{
textBoxes[i] = new TextBox();
textBoxes[i].Location = new Point(30, ToBox.Bottom + (i * 43));
labels[i] = new Label();
labels[i].Location = new Point(TopBox3[i].Width + 140, TopBox3[i].Top +3);
textboxes[i].ValueChanged += new EventHandler(this.TextBox_ValueChanged) ;
this.Controls.Add(labels[i]);
this.Controls.Add(textBoxes[i]);
}
You can remember the index of the TextBox in the Tag property
textBoxes[i].Tag = i;
and then use this value in your eventhandler to get the corresponding label (assuming that you hold the labels array as a local variable)
protected void TextBox_ValueChanged(object sender, EventArgs e)
{
TextBox textbox = sender as TextBox;
if(textbox==null)
return;
int index = Convert.ToInt32(textbox.Tag);
if(index >= 0 && index < this.labels.Length)
{
Label label = this.labels[index];
/* ... */
}
}
You should write something like this:
private void textBox1_ValueChanged(object sender, EventArgs e)
{
TextBox changedTxt = sender as TextBox;
for (int i = 1; i < value; i++)
if (textBoxes[i] == changedTxt)
{
Label lblToChange = labeld[i];
lblToChange.Text = changedTxt.Text;
break;
}
}
In the method the TextBox whose text has changed is passed as "sender". You look into your array for it, so you identify the index "i" which can be used to access the corresponding Label and to set its text.
BTW as Tim said, the event is TextChanged, not ValueChanged. Furthermore be aware that the event is triggered for every change in the text, i.e. as soon as you press a key the label will be updated. If you prefer to update your labels only when the user has finished to enter its text Leave is the event you should use.