Getting the value from a dynamic NumericUpDown by Sender c#

Yenthe picture Yenthe · May 5, 2013 · Viewed 7.5k times · Source

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

Answer

Steve picture Steve · May 5, 2013

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 + "€";

}