Getting the value from a dynamic NumericUpDown by Sender c# - c#

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();
}

Related

Dynamic text boxes and using them

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.

Windows form receive text input

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.

Assign checkboxes to an checkbox-array using a for loop in C#

I'd like to do this:
CheckBox[] boxarray = new CheckBox[4];
boxarray[0] = checkBox1;
boxarray[1] = checkBox2;
boxarray[2] = checkBox3;
boxarray[3] = checkBox4;
using a for loop - because I have about 600 checkboxes. I thought about this:
for (int i = 0 ; i<= 600; i++)
{
boxes[i] = checkBox[i] ;
}
But whatever I tried - it didn't work. I hope you know what I mean.
Thanks for your help!
If you have these CheckBoxes on your form, then you can add them to an array (or List, which would be much easier to do) like that:
List<CheckBox> checkBoxesList = new List<CheckBox>();
foreach (Control ctrl in FormName.Controls)
{
if (ctrl.GetType() == typeof(CheckBox))
{
checkBoxesList.Add(ctrl as CheckBox);
}
}
Remember, simply writing:
checkBox1, checkBox2
won't make it possible to get them like checkBox[0] - it's not an array, it's just a name with '1' or '2' in the end.
Using the current setup, you'll have to use FindControl (assuming ASP.net, winforms and WPF work differently):
for(int i = 0; i <= 600; i++)
{
boxes[i] = Page.FindControl("checkbox" + i);
}
Update for windows forms: There is actually a method you can use to find all controls of a specific type:
How to get ALL child controls of a Windows Forms form of a specific type (Button/Textbox)?
Here's another option for you. I tested it by creating a sample
application, I then put a GroupBox and a GroupBox inside the initial
GroupBox. Inside the nested GroupBox I put 3 TextBox controls and a
button. This is the code I used (even includes the recursion you were
looking for)
public IEnumerable<Control> GetAll(Control control,Type type) {
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAll(ctrl,type))
.Concat(controls)
.Where(c => c.GetType() == type);
}
To test it in the form load event I wanted a count of all controls inside
the initial GroupBox
private void Form1_Load(object sender, EventArgs e) {
var c = GetAll(this,typeof(TextBox));
MessageBox.Show("Total Controls: " + c.Count());
}
And it returned the proper count each time, so I think this will work perfectly for
what you're looking for :)
If you have other checkboxes on your form that you don't want to add, you'll have to use the following method:
for(int i = 0; i <= 600; i++)
{
boxes[i] = this.Controls.Find("checkbox" + i, true).FirstOrDefault() as CheckBox;
}
you are not able to specifiy the name of the checkboxes in the code like you have done, because i wont get changed.
you have to create new instances of CheckBox like:
for (int i = 0 ; i<= 600; i++)
{
//This will create a new instance of a CheckBox
CheckBox cb = new CheckBox()
//At this point the checkbox is empty and not visible anywhere
//So you have to change some properties:
cb.Text = "Check me!";
cb.Top = Ycoord; //you should change this depending on i like +(i*30)
cb.Left = Xcoord;
cb.name = "checkbox" + i.toString();
//To recognize if one of your Checkboxes is checked/unchecked you need to add
//an event like this (for the event see down below)
cb.CheckedChanged += checkedChangedEvent;
//then you need to add the checkbox to your Array
boxes[i] = cb;
//to make those checkboxes visible you need to add them to your form
//or Panel:
myForm.Controls.Add(cb);
}
The Event:
public void checkedChangedEvent(Object sender, EventArgs e)
{
MessageBox.Show(((CheckBox)sender).name + " is now Checked == " + ((CheckBox)sender).Checked.toString();
}
you have to specify which Checkbox was Checked/Unchecked by its name, because every CheckBox is firing the same event.
EDIT2:
to get the number of the checkbox you can do something like this in the event:
int cbNumber = 0;
try
{
cbNumber = System.Convert.toInt32(((CheckBox)sender).name.Replace("checkbox",""));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace);
}

Associate a keypress event with a event handler in a array of textboxes

I've an array of textboxes that generates run-time a variable number of textboxes such the value of a textbox already created into the form.
int n;
TextBox[] tb;
public void AggiungiArmoniche()
{
n = int.Parse(textBox4.Text);
tb = new
TextBox[n];
for (int i = 1; i < tb.Length; i++)
{
tb[i] = new TextBox();
tb[i].Name = "textBox" + i;
tb[i].Location = new Point(100 *i, 163);
tb[i].Size = new Size(48, 20);
tb[i].KeyPress += System.Windows.Forms.KeyPressEventHandler(textBoxP_KeyPress);
groupBox1.Controls.Add(tb[i]);
}
}
private void textBoxP_KeyPress(object sender, KeyPressEventArgs e)
{
// statements of the event
}
When I move to the line in which i associate the event to the event-handler it gives the error it isn't a valid construct in the contest" (in particular in the word keypresseventhandler)
is there a syntactical error in the association?
Remove the KeyPressEventHandler and add the event handler like so
tb[i].KeyPress += textBoxP_KeyPress;
new
tb[i].KeyPress += new System.Windows.Forms.KeyPressEventHandler(textBoxP_KeyPress);

Linking dynamically created text boxes and labels

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.

Categories