   C# forms event handling
  so i've recently started tinkering with C# and decided to create a forms program, i thought that creating a D&D-style character generator would be an interesting little project. the program allows a user to spend a number of points on their atributes, allowing them to create a set of attributes suitable for the chatacter they want to create (say a super strong fighter, or a really smart wizard, you get the idea).the program has a set of numericUpDown controls for each stat (6 in total) each time you increase an ability, you spend an ability point, when you reduce an ability, that point is returned to you, so you can spend it elsewhere.the problem is, this ability point storage doesn't update propperly, each time a button is pressed, the stats are updated, to allow the remaining AP (ability points) to be calculated, the initial AP is calculated by running this update function when the form loads, however for some reason, the player is able to spend all their alotted points, plus an additional one.the code for the numeric buttons reads like so:private void strScore_ValueChanged(object sender, EventArgs e)   { updateStats();    }meaning any time the value changes, the updateStats(); function is run.the update stats function reads like this:private void updateStats()   {    int initialAPAvailable;  initialAPAvailable = 75;    //temporary values for all of the stats  int STRstat;  int DEXstat;  int CONstat;  int INTstat;  int WISstat;  int CHAstat;  int tempTotalAbilities;  //make the temporary scores equal to the current values (convert from string to int)  STRstat = int.Parse(strScore.Text);  DEXstat = int.Parse(dexScore.Text);  CONstat = int.Parse(conScore.Text);  INTstat = int.Parse(intScore.Text);  WISstat = int.Parse(wisScore.Text);  CHAstat = int.Parse(chaScore.Text);  //add up the total ability scores  tempTotalAbilities = STRstat + DEXstat + CONstat + INTstat + WISstat + CHAstat;  //calculate the number of ability points that remain  remainingAPTemp = initialAPAvailable - tempTotalAbilities;  //convert the remaining ability points from an int to a string and place the string in the text box  apRemaining.Text = remainingAPTemp.ToString();  //if there are no ability points left to be spent, disable the buttons to add more ability  //points to all of the stats  if (remainingAPTemp < 1)  { strScore.Enabled = false; dexScore.Enabled = false; conScore.Enabled = false; intScore.Enabled = false; wisScore.Enabled = false; chaScore.Enabled = false;  }  else { strScore.Enabled = true; dexScore.Enabled = true; conScore.Enabled = true; intScore.Enabled = true; wisScore.Enabled = true; chaScore.Enabled = true;    }}so why is it that the update stats function does not appear to run the first time the buttons are pressed, and subsequently they always appear to run one click behind (you can spend a point, and nothing will happen, reduce the stat and return that point, and the point will be spent for the first increase, then increase the stat again, resulting in you having one point added to a stat for free).i added a "refresh" button which will allow you to work out the actual number of points spent, and this results in showing the true value - by the time you have spent all your points, you hit that button and discover you've actually got -1 points remaining. this button simply runs the updatestats function again.thank you in advance for any help you can give, and i appologise for the long-winded nature of this post :D   
  You should probably move the variable declarations outside of the ValueChanged event.As for the one-over problem, the ValueChanged event occurs after the value has changed and not before. What you're seeing is:Initial = 0Press up, increment, value = 1, event fired, condition check to disablePress up, increment, value = 2, event fired, condition check to disablePress up, increment, value = 3, event fired, condition check to disablePress down, decrement, value = 2, event fired, condition check to disableI could make the above test case as long as I wanted, but I hope you see what's happening. When you hit your max (75 in your case), it's going to allow an over amount because the conditional doesn't check until after the value has already changed and been displayed.   ;  Sorry, I should have mentioned looking into DomainUpDown instead of NumericUpDown in my original reply.   ;  I've not come across the DomainUpDown control yet, i'm not sure i've even heard of it (like i said, only recently taken up C#, much more used to working in C++) so i'll look into that.as for the way you explained the update, i see what's happening, but i still don't get it, because the sequence of events runs:change value,run update(),change value,run update().and so on.this means that the final check should see the remaining value is now 0, and disable all the numeric controls. i also run the update function when the form loads, so that should set any initial values propperly.sadly, there seems no way to control this event so that when there are no points left to spend, it won't allow the controls to be active.   ;  update:looks like the domainUpDown doesn't do anything diferent, except that it handles strings rather than just number values. as such, it's not really appropriate for the use i have planned, wheras the numericUpDown is designed for just this kind of task.   ;  Are you using Visual Studio? Have you played with the debugger yet?Try setting a breakpoint on the updateStats(); line by placing your cursor on that line an press F9. You'll see it highlight the line and there will be a circle in the left margin by the line. Run the program and change a value. The program should run to that breakpoint and pause, putting an arrow in the margine showing the next line to be run. This way you can verify that the event is being called.Hit run again (or press F5) to resume the program.If you want to do some more in-depth debugging, after your program stops at a breakpoint, use F10 to run the next line or F11 to go into the function being called at that line. After you run a line, you can put your mouse pointer over your variables to see what they are set to. There's more advanced debugging techniques but that should get you started on figuring out what's happening.Hope that helps some,Randy   ;  Sorry about the DomainUpDown suggestion, I misunderstood its application.Anyway, I played around with your code for a little bit and the fix is pretty simple. Instead of using Int.parse on the Text value of the NumericUpDown objects, just take the Value and cast to an int (it's naturally a decimal).The lines I changed to get it to work properly (that is be used on the first click and stop at 75 instead of 76) was change the following:STRstat = int.Parse(strScore.Text);DEXstat = int.Parse(dexScore.Text);CONstat = int.Parse(conScore.Text);INTstat = int.Parse(intScore.Text);WISstat = int.Parse(wisScore.Text);toSTRstat = (int)strScore.Value;DEXstat = (int)dexScore.Value;CONstat = (int)conScore.Value;INTstat = (int)intScore.Value;WISstat = (int)wisScore.Value;Now, don't ask me why this works because I don't know the difference between straight up casting and using the Int.parse method on strings. Let me know if this works for you like it worked for me.   ;  Thinking about it for a little bit made me realize that it really had nothing to do with the cast more than it did with using the right property for the right event. Previously, you were using the ValueChanged event which fires when the NumericUpDown.Value property changes, but you were referencing the NumericUpDown.Text property when obtaining your values. I would suspect that the issue would revolve around that.Hope I helped a bit.   ;  ah, of course. yes, that makes much more sense, and it works just fine now. thanks for the assistance :)   