Search code examples
c#dynamicsendernumericupdowneventargs

Getting the value from a dynamic NumericUpDown by Sender 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


Solution

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