c# calculator minus not working properly - c#

I've got to make a calculator for school, everything works except the minus button: 5-5 = -5 for example.
I know that the problem exists somewhere in my case "minus" but I just
can't get it figured out..
Here's the code.
Most of the variables are in dutch, I hope that won't be a problem!
Note: this problem exists when i do this: 5 - 5, so not using the equals button.
private int totaal = 0;
private Boolean lastClicked, equalsPressed, tussen = false;
public MainWindow()
{
InitializeComponent();
}
private void button_Click(object sender, EventArgs e)
{
switch(((Button)sender).Name){
case "one":
if (tussen)
{
uitkomstBox.Text = "";
tussen = false;
}
if (equalsPressed)
{
uitkomstBox.Text = uitkomstBox.Text + "1";
equalsPressed = false;
}
else
{
uitkomstBox.Text = uitkomstBox.Text + "1";
}
break;
case "two":
if (tussen)
{
uitkomstBox.Text = "";
tussen = false;
}
if (equalsPressed)
{
uitkomstBox.Text = uitkomstBox.Text + "2";
equalsPressed = false;
}
else
{
uitkomstBox.Text = uitkomstBox.Text + "2";
}
break;
case "three":
if (tussen)
{
uitkomstBox.Text = "";
tussen = false;
}
if (equalsPressed)
{
uitkomstBox.Text = uitkomstBox.Text + "3";
equalsPressed = false;
}
else
{
uitkomstBox.Text = uitkomstBox.Text + "3";
}
break;
case "four":
if (tussen)
{
uitkomstBox.Text = "";
tussen = false;
}
if (equalsPressed)
{
uitkomstBox.Text = uitkomstBox.Text + "4";
equalsPressed = false;
}
else
{
uitkomstBox.Text = uitkomstBox.Text + "4";
}
break;
case "five":
if (tussen)
{
uitkomstBox.Text = "";
tussen = false;
}
if (equalsPressed)
{
uitkomstBox.Text = uitkomstBox.Text + "5";
equalsPressed = false;
}
else
{
uitkomstBox.Text = uitkomstBox.Text + "5";
}
break;
case "six":
if (tussen)
{
uitkomstBox.Text = "";
tussen = false;
}
if (equalsPressed)
{
uitkomstBox.Text = uitkomstBox.Text + "6";
equalsPressed = false;
}
else
{
uitkomstBox.Text = uitkomstBox.Text + "6";
}
break;
case "seven":
if (tussen)
{
uitkomstBox.Text = "";
tussen = false;
}
if (equalsPressed)
{
uitkomstBox.Text = uitkomstBox.Text + "7";
equalsPressed = false;
}
else
{
uitkomstBox.Text = uitkomstBox.Text + "7";
}
break;
case "eight":
if (tussen)
{
uitkomstBox.Text = "";
tussen = false;
}
if (equalsPressed)
{
uitkomstBox.Text = uitkomstBox.Text + "8";
equalsPressed = false;
}
else
{
uitkomstBox.Text = uitkomstBox.Text + "8";
}
break;
case "nine":
if (tussen)
{
uitkomstBox.Text = "";
tussen = false;
}
if (equalsPressed)
{
uitkomstBox.Text = uitkomstBox.Text + "9";
equalsPressed = false;
}
else
{
uitkomstBox.Text = uitkomstBox.Text + "9";
}
break;
case "zero":
if (tussen)
{
uitkomstBox.Text = "";
tussen = false;
}
if (equalsPressed)
{
uitkomstBox.Text = uitkomstBox.Text + "0";
equalsPressed = false;
}
else
{
uitkomstBox.Text = uitkomstBox.Text + "0";
}
break;
case "plus":
totaal = totaal + Convert.ToInt32(uitkomstBox.Text);
uitkomstBox.Text = totaal.ToString();
tussen = true;
lastClicked = true;
break;
case "minus":
totaal = totaal - Convert.ToInt32(uitkomstBox.Text);
uitkomstBox.Text = totaal.ToString();
tussen = true;
lastClicked = false;
break;
case "clear":
uitkomstBox.Text = "";
totaal = 0;
break;
case "equals":
if (lastClicked)
{
uitkomstBox.Text = (totaal + Convert.ToInt32(uitkomstBox.Text)).ToString();
}
else
{
uitkomstBox.Text = (Convert.ToInt32(uitkomstBox.Text) - totaal).ToString();
}
equalsPressed = true;
totaal = 0;
break;
}
}
}
}

The problem is that you are subtracting the number twice. Once in the switch statement and then again here:
if (lastClicked)
{
uitkomstBox.Text = (totaal + Convert.ToInt32(uitkomstBox.Text)).ToString();
}
else
{
// You have already subtracted the number but then you are subtracting it again!
uitkomstBox.Text = (Convert.ToInt32(uitkomstBox.Text) - totaal).ToString();
}

It's the logic of the plus and minus buttons you need to check.
Take yourself through the code step by step.
In the beginning, totaal = 0 and uitkomnstBox.Text is empty. Then you click "5". So uitkomstBox.Text is "5". Then you click the "minus" button. totaal now changes to -5. i.e. before you have even entered a number to subtract from it. Then you click "5" again (to complete 5 - 5) but totaal doesn't change in this case until you click the equals button, at which point it hits that lastClicked logic which I don't really get... (I think it should end up as zero after that but you said the problem exists if you don't click "equals").
So it's not just that you're subtracting twice but you're subtracting before you even have a number to subtract.
As a possible solution, what I'd suggest is something like this: execute the logic of the operation ("plus" or "minus") after the next number is complete.
i.e. When someone clicks "minus" save this in memory somewhere until they have finished entering the next number, then subtract it from the total, or if they clicked "plus" add it. For the first number, process "plus" (e.g. 5 - 5 is processed as if it was entered as + 5 - 5)
private char operation = '+'; // Default first operation to "plus"
// Your other code...
// ...
// ...
case "plus" :
if (operation == '+') {
totaal += Convert.ToInt32(uitkomnstBox.Text);
}
if (operation == '-') {
totaal -= Convert.ToInt32(uitkomnstBox.Text);
}
operation = '+';
// anything else you want
break;
case "minus" :
if (operation == '+') {
totaal += Convert.ToInt32(uitkomnstBox.Text);
}
if (operation == '-') {
totaal -= Convert.ToInt32(uitkomnstBox.Text);
}
operation = '-';
// anything else you want
break;
case "equals" :
if (operation == '+') {
totaal += Convert.ToInt32(uitkomnstBox.Text);
}
if (operation == '-') {
totaal -= Convert.ToInt32(uitkomnstBox.Text);
}
operation = '+'; // Set back to default for next calculation
// anything else you want
break;

It looks like you are subtracting from totaal twice. Are you sure that adding works correctly? Check the code for your "=" button.

Also, maybe consider storing numbers for calculation in some counter int (or any other number type, if you are planning to allow fractions), rather than in textbox, since then you have to convert it back and forth just for the calculation.

Related

How do you pause between cases in switch statements? c#. 3second delay before executing the next case

This is a sample of my code. I want to have a 3 second delay before executing the next case (display picturebox). But When I tried using timer/stopwatch, the 3 second delay will only be on the 1st case and case2 will execute the same time as case1 (with no delay).
private void button1_Click(object sender, EventArgs e)
{
string input = (input1.Text).ToString();
char[] letters = input.ToCharArray();
int stringlength = letters.Length;
int length = stringlength - 1;
int state = 1;
int position = 0;
string validation = " ";
switch (state)
{
case 1:
//insert timer here
if (letters[position] == 'a')
{
pictureBox2.Visible = true;
validation = "Invalid";
label1.Text = validation;
break;
}
else if (letters[position] == 'b')
{
if (position == length)
{
validation = "Invalid";
label1.Text = validation;
break;
}
pictureBox2.Visible = true;
position = position + 1;
goto case 2;
}
break;
case 2:
//Insert Timer here
if (letters[position] == 'a')
{
pictureBox3.Visible = true;
if (position == length)
{
validation = "Invalid because it does not end at final state";
label1.Text = validation;
break;
}
position = position + 1;
goto case 3;
}
else if (letters[position] == 'b')
{
if (position == length)
{
validation = "Invalid";
label1.Text = validation;
break;
}
position = position + 1;
goto case 4;
}
break;
}
}
By the way, I can't use Task.Delay or async/await because I use the .Net 4.0 framework.
You can perform this by using:
System.Threading.Thread.Sleep(3000);
So Your code should look like:
private void button1_Click(object sender, EventArgs e)
{
int state = 1;
//some code
switch (state)
{
case 1:
System.Threading.Thread.Sleep(3000);
//some case code
break;
case 2:
System.Threading.Thread.Sleep(3000);
//some case code
break;
default:
System.Threading.Thread.Sleep(3000);
//some default code
break;
}
//rest of the code
}
Just to let You know, there should be other (and better) way to going through this, rather than using switch and this type of GOTO case this and this. Making the code unreadable in future.
Thread.Sleep(3000) you can use

How to shorten if-else-if statement in c#

Can someone shorten this code?
There are 14 Buttons and 8 text Boxes. The action will be perform if the textbox is not empty and if it is not empty, then when you click it the button corresponding with the letter in the textbox will be visible again making the textbox empty.
private void txt1_Click(object sender, EventArgs e)
{
if (txt1.Text == "J")
{
txt1.Text = "";
btn1.Visible = true;
}
else if (txt1.Text == "M")
{
txt1.Text = "";
btn2.Visible = true;
}
else if (txt1.Text == "Y")
{
txt1.Text = "";
btn3.Visible = true;
}
else if (txt1.Text == "E")
{
if (btn4.Visible == true)
{
txt1.Text = "";
btn5.Visible = true;
}
else
{
txt1.Text = "";
btn4.Visible = true;
}
}
else if (txt1.Text == "Q")
{
txt1.Text = "";
btn6.Visible = true;
}
else if (txt1.Text == "L")
{
if (btn7.Visible == true)
{
txt1.Text = "";
btn10.Visible = true;
}
else
{
txt1.Text = "";
btn7.Visible = true;
}
}
else if (txt1.Text == "B")
{
txt1.Text = "";
btn8.Visible = true;
}
else if (txt1.Text == "C")
{
txt1.Text = "";
btn9.Visible = true;
}
else if (txt1.Text == "P")
{
txt1.Text = "";
btn11.Visible = true;
}
else if (txt1.Text == "I")
{
txt1.Text = "";
btn12.Visible = true;
}
else if (txt1.Text == "K")
{
txt1.Text = "";
btn13.Visible = true;
}
else if (txt1.Text == "O")
{
txt1.Text = "";
btn14.Visible = true;
}
}
Assuming all the btn variables are part of the state of your class then you can declare a method like so:
public Button Click(String txt) {
switch(txt) {
case "J":
return btn1;
case "M":
return btn2;
case "Y":
return btn3;
case "E":
return (btn4.Visible ? btn5 : btn4);
case "Q":
return btn6;
case "L":
return (btn7.Visible ? btn10 : btn7);
case "B":
return btn8;
case "C":
return btn9;
case "P":
return btn11;
case "I":
return btn12;
case "K":
return btn13;
case "O":
return btn14;
}
return null;
}
and then you call it:
var button = Click(txt1.Text);
if(button != null) {
button.Visible = true;
txt1.Text = "";
}
If however the btn variables have local scope, than instead of a method you can just define an inline Func<String,Button> delegate as so:
Func<String, Button> Click = txt => {
switch(txt) {
...
}
};
You'd still have to handle the special cases ("E" and "L") but you could use a Dictionary<string, Button> which would allow you to do a lookup:
var buttonDictionary = new Dictionary<string, Button>();
buttonDictionary["J"] = btn1;
buttonDictionary["M"] = btn2;
//etc...
if (buttonDictionary.Keys.Contains(txt1.Text))
{
txt1.Text = "";
buttonDictionary[txt1.Text].Visible = false;
}
That would reduce most of the repetitive code.
Looking at this: I'd suggest you go back think of more logical way to do whatever you're doing.
Out of my experience, any enormous chains of if-else in code represent that there has been a logical issue somewhere.
Also, familiarize yourself with switch statements

Exception : 'System.InvalidOperationException' in System.Windows.Forms.dll [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have no clue what the problem is.
Here is my code:
namespace TimeClock
{
public partial class Form1 : Form
{
String Code;
String Name;
String InOut;
String allTextIn;
String allTextOut;
Boolean Joshua = false;
int JoshuaInt = 1;
Boolean Alec = false;
int AlecInt = 3;
Boolean Kyle = false;
int KyleInt = 5;
Boolean Jeffrey = false;
int JeffreyInt = 7;
Boolean Carl = false;
int CarlInt = 9;
Boolean Angela = false;
int AngelaInt = 11;
Boolean Kendra = false;
int KendraInt = 13;
Boolean Susan = false;
int SusanInt = 15;
Boolean Kory = false;
int KoryInt = 17;
Boolean Jeanine = false;
int JeanineInt = 19;
Boolean Daniel = false;
int DanielInt = 21;
Boolean Steven = false;
int StevenInt = 23;
Boolean Jacob = false;
int JacobInt = 25;
Boolean Mario = false;
int MarioInt = 27;
int Index;
String csvPath = "C:/Users/Public/TimeClockData.csv";
StringBuilder Header = new StringBuilder();
StringBuilder csvData = new StringBuilder();
private static SpeechSynthesizer synth = new SpeechSynthesizer();
Thread saveData;
Thread clock;
Thread location;
public Form1()
{
InitializeComponent();
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
TopMost = true;
Header.AppendLine("Timestamp, Name");
File.AppendAllText(csvPath, Header.ToString());
textBox1.Font = new Font("Arial", 30, FontStyle.Bold);
clock = new Thread(new ThreadStart(Clock));
clock.Start();
location = new Thread(new ThreadStart(GetPugsleyLocation));
location.Start();
}
private void Clock()
{
DateTime timeStamp = DateTime.Now;
textBox2.Text = timeStamp.ToString();
}
private void GetPugsleyLocation()
{
Ping ping = new Ping();
string ip = "";
IPAddress address = IPAddress.Parse(ip);
PingReply pong = ping.Send(address);
if (pong.Status == IPStatus.Success)
{
textBox3.Text = "Pugsley is here now";
}
else
{
textBox3.Text = "Pugsley is not here right now";
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
FormBorderStyle = FormBorderStyle.Sizable;
WindowState = FormWindowState.Normal;
TopMost = false;
}
}
public static void SpeakNow(string message)
{
synth.SelectVoiceByHints(VoiceGender.Male);
synth.Speak(message);
synth.Rate = -2;
}
public void saveDataThread()
{
DateTime timeStamp = DateTime.Now;
csvData.AppendLine(timeStamp + "," + Name + "," + InOut);
File.AppendAllText(csvPath, csvData.ToString());
csvData.Clear();
InOut = null;
}
private void Number_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
Code = Code + button.Text;
textBox1.Text = Code;
}
private void Enter_Click(object sender, EventArgs e)
{
//in or out
Button button = (Button)sender;
Name = "";
var list = new List<string>();
list.Add("107");
list.Add("104");
list.Add("115");
list.Add("131");
list.Add("113");
list.Add("112");
list.Add("126");
list.Add("117");
list.Add("130");
list.Add("116");
list.Add("108");
list.Add("133");
list.Add("122");
list.Add("106");
if (list.Contains(Code))
{
if (Code == "107")
{
Name = "Joshua";
Index = JoshuaInt;
if (Joshua == false)
{
InOut = "In";
Joshua = true;
goto done;
}
if (Joshua == true)
{
InOut = "Out";
Joshua = false;
goto done;
}
}
if (Code == "104")
{
Name = "Alec";
Index = AlecInt;
if (Alec == false)
{
InOut = "In";
Alec = true;
goto done;
}
if (Alec == true)
{
InOut = "Out";
Alec = false;
goto done;
}
}
if (Code == "115")
{
Name = "Kyle";
Index = KyleInt;
if (Kyle == false)
{
InOut = "In";
Kyle = true;
goto done;
}
if (Kyle == true)
{
InOut = "Out";
Kyle = false;
goto done;
}
}
if (Code == "131")
{
Name = "Jeffrey";
Index = JeffreyInt;
if (Jeffrey == false)
{
InOut = "In";
Jeffrey = true;
goto done;
}
if (Jeffrey == true)
{
InOut = "Out";
Jeffrey = false;
goto done;
}
}
if (Code == "113")
{
Name = "Carl";
Index = CarlInt;
if (Carl == false)
{
InOut = "In";
Carl = true;
goto done;
}
if (Carl == true)
{
InOut = "Out";
Carl = false;
goto done;
}
}
if (Code == "112")
{
Name = "Angela";
Index = AngelaInt;
if (Angela == false)
{
InOut = "In";
Angela = true;
goto done;
}
if (Angela == true)
{
InOut = "Out";
Angela = false;
goto done;
}
}
if (Code == "126")
{
Name = "Kendra";
Index = KendraInt;
if (Kendra == false)
{
InOut = "In";
Kendra = true;
goto done;
}
if (Kendra == true)
{
InOut = "Out";
Kendra = false;
goto done;
}
}
if (Code == "117")
{
Name = "Susan";
Index = SusanInt;
if (Susan == false)
{
InOut = "In";
Susan = true;
goto done;
}
if (Susan == true)
{
InOut = "Out";
Susan = false;
goto done;
}
}
if (Code == "130")
{
Name = "Kory";
Index = KoryInt;
if (Kory == false)
{
InOut = "In";
Kory = true;
goto done;
}
if (Kory == true)
{
InOut = "Out";
Kory = false;
goto done;
}
}
if (Code == "116")
{
Name = "Jeanine";
Index = JeanineInt;
if (Jeanine == false)
{
InOut = "In";
Jeanine = true;
goto done;
}
if (Jeanine == true)
{
InOut = "Out";
Jeanine = false;
goto done;
}
}
if (Code == "108")
{
Name = "Daniel";
Index = DanielInt;
if (Daniel == false)
{
InOut = "In";
Daniel = true;
goto done;
}
if (Daniel == true)
{
InOut = "Out";
Daniel = false;
goto done;
}
}
if (Code == "133")
{
Name = "Steven";
Index = StevenInt;
if (Steven == false)
{
InOut = "In";
Steven = true;
goto done;
}
if (Steven == true)
{
InOut = "Out";
Steven = false;
goto done;
}
}
if (Code == "122")
{
Name = "Jacob";
Index = JacobInt;
if (Jacob == false)
{
InOut = "In";
Jacob = true;
goto done;
}
if (Jacob == true)
{
InOut = "Out";
Jacob = false;
goto done;
}
}
if (Code == "106")
{
Name = "Mario";
Index = MarioInt;
if (Mario == false)
{
InOut = "In";
Mario = true;
goto done;
}
if (Mario == true)
{
InOut = "Out";
Mario = false;
goto done;
}
}
}
else
{
goto clear;
}
done:
InOut = button.Text;
saveData = new Thread(new ThreadStart(saveDataThread));
saveData.Start();
String[] textIn = System.IO.File.ReadAllLines(#"C:\Users\Public\textIn.txt");
String[] textOut = System.IO.File.ReadAllLines(#"C:\Users\Public\textOut.txt");
allTextIn = textIn[Index];
allTextOut = textOut[Index];
if (InOut == "In")
{
if (allTextIn != "/")
{
SpeakNow(allTextIn);
}
else
{
SpeakNow("Hello" + Name);
}
}
else
{
if (allTextOut != "/")
{
SpeakNow(allTextOut);
}
else
{
SpeakNow("Goodbye" + Name);
}
}
clear:
Code = null;
textBox1.Text = Code;
}
private void Backspace_Click(object sender, EventArgs e)
{
//Backspace
if (Code.Length >= 1)
{
Code = Code.Substring(0, Code.Length - 1);
textBox1.Text = Code;
}
}
private void Clear_Click(object sender, EventArgs e)
{
//Clear
Code = null;
textBox1.Text = Code;
}
}
}
It runs for a couple of seconds, then crashes. I am newish to C# and visual studio. Like I said, I have no clue what the problem is. I read that it might be caused by the threads changing the UI, but another version worked with the threads changing the UI, so I have no clue. Please help me!
You can't access the UI directly from your threads like you're doing.
Call Invoke on your controls first:
private void Clock()
{
textBox2.Invoke(new Action(() => textBox2.Text = DateTime.Now.ToString()));
}
private void GetPugsleyLocation()
{
...
...
textBox3.Invoke(new Action(() =>
textBox3.Text = "Pugsley is " + (pong.Status == IPStatus.Success ? "" : "not") + " here now"));
}

How to manage Label in c#

I am trying to organize Label and TextBoxes in c# i have two function :
private void BtnKaydet_Click(object sender, EventArgs e)
{
_service = new Client.BioAuthenticationService.BioAuthenticationService();
int warningcase = 0;
if ((string.IsNullOrEmpty(TbTcNo.Text) || string.IsNullOrWhiteSpace(TbTcNo.Text)))
{
warningcase = 1;
TextLabelManagement(warningcase);
}
else if ((string.IsNullOrEmpty(TbId.Text) || string.IsNullOrWhiteSpace(TbId.Text)))
{
warningcase = 2;
TextLabelManagement(warningcase);
}
else if ((string.IsNullOrEmpty(TbName.Text) || string.IsNullOrWhiteSpace(TbName.Text)))
{
warningcase = 3;
TextLabelManagement(warningcase);
}
else if ((string.IsNullOrEmpty(TbSurname.Text) || string.IsNullOrWhiteSpace(TbSurname.Text)))
{
warningcase = 4;
TextLabelManagement(warningcase);
}
else if ((string.IsNullOrEmpty(TbDepartment.Text) || string.IsNullOrWhiteSpace(TbDepartment.Text)))
{
warningcase = 5;
TextLabelManagement(warningcase);
}
else
{
if (_imageIndex == 3)
{
bool enrollResult = _service.CheckAndEnrollUser(image1, image2, image3, 300, 6);
}
else
{
warningcase = 6;
TextLabelManagement(warningcase);
}
}
}
Here i write cases if TextBox is null i will give error message to fill them. Here is my cases :
private void TextLabelManagement(int cases)
{
switch (cases)
{
case 1:
LblWarning.Visible = true;
LblWarning.Text = "* Lütfen Bu Alanları Doldurunuz..";
LblTcNo.Text = "* TC No";
LblTcNo.ForeColor = System.Drawing.Color.Red;
LblWarning.ForeColor = System.Drawing.Color.Red;
break;
case 2:
LblWarning.Visible = true;
LblWarning.Text = "* Lütfen Bu Alanları Doldurunuz..";
LblId.Text = "* ID";
LblId.ForeColor = System.Drawing.Color.Red;
LblWarning.ForeColor = System.Drawing.Color.Red;
break;
case 3:
LblWarning.Visible = true;
LblWarning.Text = "* Lütfen Bu Alanları Doldurunuz..";
LblName.Text = "* Ad";
LblName.ForeColor = System.Drawing.Color.Red;
LblWarning.ForeColor = System.Drawing.Color.Red;
break;
case 4:
LblWarning.Visible = true;
LblWarning.Text = "* Lütfen Bu Alanları Doldurunuz..";
LblSurname.Text = "* Soyad";
LblSurname.ForeColor = System.Drawing.Color.Red;
LblWarning.ForeColor = System.Drawing.Color.Red;
break;
case 5:
LblWarning.Visible = true;
LblWarning.Text = "* Lütfen Bu Alanları Doldurunuz..";
LblDepartment.Text = "* Soyad";
LblDepartment.ForeColor = System.Drawing.Color.Red;
LblWarning.ForeColor = System.Drawing.Color.Red;
break;
case 6:
LblFingerWarning.Visible = true;
LblFingerWarning.Text = "Lütfen Parmak İzinizi Üç Kez Veriniz.";
LblFingerWarning.ForeColor = System.Drawing.Color.Red;
break;
default:
break;
}
}
However when user click Save button it will enter first IF condition. Then Else If .. But here is my problem. How i can organize these items. For example if user did't fill all boxes i want to give him all warning message not step by step.
You can use a validator for text box. The validator controls that you would find in toolbox.
Try the link
Use if instead of else if because when first if is true it will not enter into else if, so only one message is displayed. Use it as :
if ((string.IsNullOrEmpty(TbTcNo.Text) || string.IsNullOrWhiteSpace(TbTcNo.Text)))
{
warningcase = 1;
TextLabelManagement(warningcase);
}
if ((string.IsNullOrEmpty(TbId.Text) || string.IsNullOrWhiteSpace(TbId.Text)))
{
warningcase = 2;
TextLabelManagement(warningcase);
}
if ((string.IsNullOrEmpty(TbName.Text) || string.IsNullOrWhiteSpace(TbName.Text)))
{
warningcase = 3;
TextLabelManagement(warningcase);
}
Winforms user control validation = http://msdn.microsoft.com/en-us/library/ms229603(v=vs.110).aspx
ASP.NET user control validation = http://msdn.microsoft.com/en-us/library/7kh55542.ASPX

Stackoverflow exception from updating combobox in winforms/C#

I'm geting a StackOverflowException. Somehow, posting here seemed appropriate.
I'm using Windows Forms in a C# application. This application is intended to run on Linux, FreeBSD and Mac-OS, so I can't use WPF, so please don't suggest it.
My guess is that I'm missing a nuance of WinForms, but I cant seem to figure out what.
The ComboBox is generated by the GUI form builder in VS 2010.
The specific lines of code that are throwing the error are here:
if(cur_num_is_valid)
{
cbx_material_num.Text = num;
}
else
{
num = "0";
//I only have one of the following two at a time. Both overflow
cbx_material_num.SelectedIndex = 0;
cbx_material_num.Text = "0";
}
Since the code is somewhat complex, here's the whole function code. 'cbx_' indicates a combo box. 'txtb_' is a text box.
private void cbx_material_numobj_SelectedIndexChanged(object sender, EventArgs e)
{
string obj = cbx_material_obj.Text;
string num = cbx_material_num.Text;
int selnum = 0;
int n = 0;
//do we need to recreate the numbers array?
bool cur_num_is_valid = false;
cbx_material_num.Items.Clear();
if(obj != lastobj)
{
n = m_demo.get_object_modifiers(obj);
for(int i = 0; i <= n; i++)
{
string s = i.ToString();
if(s == num && i < n) cur_num_is_valid = true;
cbx_material_num.Items.Add(s);
}
}
if(cur_num_is_valid)
{
cbx_material_num.Text = num;
}
else
{
num = "0";
//Overflow here:
cbx_material_num.SelectedIndex = 0;
}
try
{
selnum = int.Parse(num);
}
catch(Exception)
{
MessageBox.Show("Error, second select menu after 'object modifiers' must be a number, not '"+num+"'.");
cbx_material_num.Text="0";
return;
}
if(selnum >= n)
{
txtb_material_param1.Text = "0";
txtb_material_param2.Text = "0";
txtb_material_param3.Text = "0";
txtb_material_param4.Text = "0";
}
else
{
MaterialFace face;
MaterialParameter parameter;
int typeid;
object paramdata;
m_demo.get_object_modifiers_material(obj, selnum, out face, out parameter, out typeid, out paramdata);
cbx_material_face.Text = face.ToString();
cbx_material_paramtype.Text = parameter.ToString();
switch(typeid)
{
case 0:
txtb_material_param1.Text = ((float)paramdata).ToString();
cbx_material_datatype.Text = "float";
goto case -1;
case 1:
float[] parsf = ((float[])paramdata);
txtb_material_param1.Text = parsf[0].ToString();
txtb_material_param2.Text = parsf[1].ToString();
txtb_material_param3.Text = parsf[2].ToString();
txtb_material_param4.Text = parsf[3].ToString();
cbx_material_datatype.Text = "float[]";
break;
case 2:
txtb_material_param1.Text = ((int)paramdata).ToString();
cbx_material_datatype.Text = "int";
goto case -1;
case 3:
int[] parsi = ((int[])paramdata);
txtb_material_param1.Text = parsi[0].ToString();
txtb_material_param2.Text = parsi[1].ToString();
txtb_material_param3.Text = parsi[2].ToString();
txtb_material_param4.Text = parsi[3].ToString();
cbx_material_datatype.Text = "int[]";
break;
case -1: //can't actuall be returned, used to 'blank' the last three as '0'
txtb_material_param2.Text = "0";
txtb_material_param2.Text = "0";
txtb_material_param3.Text = "0";
break;
case 4:
OpenTK.Graphics.Color4 paramc = ((OpenTK.Graphics.Color4)paramdata);
txtb_material_param1.Text = paramc.R.ToString();
txtb_material_param2.Text = paramc.G.ToString();
txtb_material_param3.Text = paramc.B.ToString();
txtb_material_param4.Text = paramc.A.ToString();
cbx_material_datatype.Text = "Color4";
break;
default: //5
Vector4 paramv = ((Vector4)paramdata);
txtb_material_param1.Text = paramv.X.ToString();
txtb_material_param2.Text = paramv.Y.ToString();
txtb_material_param3.Text = paramv.Z.ToString();
txtb_material_param4.Text = paramv.W.ToString();
cbx_material_datatype.Text = "Vector4";
break;
}
}
}
You need to check that the SelectedIndex isn't already 0 before you try to set it:
if (cbx_material_num.SelectedIndex != 0){
cbx_material_num.SelectedIndex = 0;
}
Otherwise you're re-firing the event every time through.
I think that whenever you set this cbx_material_num.SelectedIndex = 0; within the EventHandler you invoke your
cbx_material_numobj_SelectedIndexChanged(object sender, EventArgs e)
Each call invokes another eventHandler so the stack fills up after some time.
Basically, the fact that it is called SelectedIndexChanged doesn't mean that the value has to be different from the previous one but that the value is set through its setter.

Categories

Resources