try catch not working - c#

I can't figure out how to get the try catch to work. Need to have an error message box pop up when a non number is entered in the text boxes.
private void btnAdd_Click(object sender, EventArgs e)
{
int x = int.Parse(txtIn1.Text);
int y = int.Parse(txtIn2.Text);
txtIn1.Text = x.ToString();
txtIn2.Text = y.ToString();
lstOut.Items.Add((x + y).ToString("N0"));
try
{
int.Parse(txtIn1.Text);
int.Parse(txtIn2.Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}

With minimal modifications: move all the code into the try so it catches when any Exception is hit. You're encountering your exception outside of the try block. You are only going to ever see your catch triggered if something within the corresponding try block is throw an exception.
private void btnAdd_Click(object sender, EventArgs e) {
try {
int x = int.Parse(txtIn1.Text);
int y = int.Parse(txtIn2.Text);
txtIn1.Text = x.ToString();
txtIn2.Text = y.ToString();
lstOut.Items.Add((x + y).ToString("N0"));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}
Edit: As suggested by commenters, I think this answer is incomplete without stating that a Try/Catch block is overkill in this instance.
A better approach would be to use the built-in TryParse method (which can return a boolean regarding the success of the parse attempt, and an output value). Here is one way you could accomplish this:
private void btnAdd_Click(object sender, EventArgs e) {
var xSuccess = int.TryParse(txtIn1.Text, out int x);
var ySuccess = int.TryParse(txtIn2.Text, out int y);
if(!xSuccess)
MessageBox.Show($"{x} could not be parsed to int!");
if(!ySuccess)
MessageBox.Show($"{y} could not be parsed to int!");
if(xSuccess && ySuccess)
lstOut.Items.Add((x + y).ToString("N0"));
}

You shouldn't use try-catch as a control block as explained in this SO post. Use if for that. Try catch is really meant to be used when you can't do otherwise or when something that you didn't expect happened.
You can use this SO post as an example and your code could look like this
private void btnAdd_Click(object sender, EventArgs e)
{
int x;
int y;
if(!int.TryParse(txtIn1.Text, out x) || !int.TryParse(txtIn2.Text, out y))
MessageBox.Show("Parse failed !");
}
You can use
Console.WriteLine(x);
Console.WriteLine(y);
to verify that the vars were properly given a value
For more information about the int.TryParse() method vs int.Parse() see this post

As other have mentioned, it's the first int.Parse() functions that are tripping things up - the ones outside the Try/Catch block.
I wanted to expand on the TryParse() function - and why should probably be using that.
Exceptions are expensive - they're a rather large overhead in terms of Time/CPU/etc. They're also not user-friendly. You want to say "Please enter a valid number" to the user, not "An exception occurred: ..."
Instead, you can use TryParse, which returns whether the parsing worked; the output of the parse is an "out" parameter in the inputs list:
int myValue;
bool parseWorked = int.TryParse("3", out myValue);
This doesn't have the Exception overhead - it runs quickly, regardless of whether the input's valid.

Why not use a different approach?
Use the TextBox.KeyPress event:
private void txtIn1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsDigit(e.KeyChar) /* || add more conditions*/)
e.Handled = true; // Prevent key to be added to the TextBox' text.
}
Now you don't have to check if there are non-numbers in your string.
Your statement int.Parse(txtIn1.Text); will surely work.

Related

Prevent other Methods from running under a condition is met in a previous Method

My problem is when the user clicks on myButton the program operates perfectly fine. But if the user was to input a value less than 3 in the first textbox a message box will appear to the user stating that the value must be greater than 3 metres. If you click OK the next method in myButton runs anyway and the result message box appears anyway.
I've tried looking around to solve this problem of mine using Nested For Loops but failed to get them to work (most likely a fault on my end). I also prefer not to use Goto because it isn't exactly good programming practice to use. Of course you can tell me otherwise if you want :) .
// Button
private void myButton_Click(object sender, EventArgs e)
{
checkIfNumericalValue();
testIfTextBoxOnesMinimumIsMet();
testIfTextBoxTwosMinimumIsMet();
displayResultToUser();
resetOrClose();
}
// Textbox One
public void testIfTextBoxOnesMinimumIsMet()
{
if (length < 3)
{
MessageBox.Show("length must be greater than 3 metres");
}
}
Help would be greatly appreciated this is also my second attempt at C# on Visual Studio 2012. Do not worry this has nothing to do with my year 10 schooling as my school doesn't have a programming subject. This problem occurs in testIfTextBoxOnesMinimumIsMet() and testIfTextBoxOnesMinimumIsMet() as well but if someone can help me with this one method I should be able to fix the rest :)
You could throw an exception from your inner functions and catch it from your button's function, something like this:
// Button
private void myButton_Click(object sender, EventArgs e)
{
try
{
checkIfNumericalValue();
testIfTextBoxOnesMinimumIsMet();
testIfTextBoxTwosMinimumIsMet();
displayResultToUser();
resetOrClose();
}
catch (ArgumentException ex)
{
// The error message we defined at the exception we threw
MessageBox.Show(ex.Message);
}
}
// Textbox One
public void testIfTextBoxOnesMinimumIsMet()
{
if (length < 3)
{
throw new ArgumentException("Length must be greater than 3 meters.");
}
}
An alternative would be to deal with the validation within your button like so:
// Button
private void myButton_Click(object sender, EventArgs e)
{
checkIfNumericalValue();
if (length < 3)
{
MessageBox.Show("Length must be greater than 3 meters.");
return;
}
testIfTextBoxTwosMinimumIsMet();
displayResultToUser();
resetOrClose();
}
What happens above is that the return will leave that function without further processing anything else.
So, if I'm understanding this correctly, if the text boxes contain numerical values, text box 1 meets the minimum and text box 2 meets the minimum, you want to displayResultToUser() and then resetOrClose().
If that's the case, you can have the 3 methods checkIfNumericalValue(), testIfTextBoxOnesMinimumIsMet() and testIfTextBoxTwosMinimumIsMet() return a bool depending on what the minimum condition is and then write something like this:
private void myButton_Click(object sender, EventArgs e)
{
if (checkIfNumericalValue() && testIfTextBoxOnesMinimumIsMet(Convert.ToInt32(txtBoxOne.Text)) && testIfTextBoxTwosMinimumIsMet(Convert.ToInt32(txtBoxTwo.Text)))
{
displayResultToUser();
resetOrClose();
}
}
public bool testIfTextBoxOnesMinimumIsMet(int length)
{
if (length < 3)
{
MessageBox.Show("length must be greater than 3 metres");
return false;
}
return true;
}
It appears that you need some other variable to track whether or not you have encountered errors. To do this, you could have a bool noErrors variable defined, and you should return a boolean from your error check methods that is True if there were no errors, otherwise False. This way you know if you ran into any problems.
Finally, you should check for the state of errrorsFound before running any of your other methods.
For example:
// Button
private void myButton_Click(object sender, EventArgs e)
{
bool noErrors =
isNumericalValue() &&
textBoxOnesMinimumIsMet() &&
textBoxTwosMinimumIsMet();
if (noErrors)
{
displayResultToUser();
resetOrClose(); // I'm not sure if this should happen regardless of errors?
}
}
// Textbox One
public bool textBoxOnesMinimumIsMet()
{
if (length < 3)
{
MessageBox.Show("length must be greater than 3 metres");
return false;
}
return true;
}

Form Validation Before Storing to SQLite DB in C#

I have a save button. When a user clicks it. The data-input in the the form will be validated before it will be send to the db. How can I achieve it?
Here's the code of my save button.
private void save_Click(object sender, EventArgs e)
{
try
{
int civil_caseI = int.Parse(civil_case.Text);
}
catch (Exception cc)
{
MessageBox.Show("Enter Number Only on CIVIL CASE");
}
string areaI = area.Text;
if (areaI.Length <= 0)
{
MessageBox.Show("Area Field must not be Empty");
}
string addressI = address.Text;
if (addressI.Length <= 0)
{
MessageBox.Show("Address Field must not be Empty");
}
// HERE WILL BE THE QUERY TO INSERT THE DATA AFTER THE FORM IS VALIDATED.
}
You are not returning from your method if there is an error in validation. return early from your method if there is an exception/failure in rule validation. You can just add return; statement after showing the error message.
A better way would be to use int.TryParse to parse int values instead of try-catch. Remember exceptions are expensive. You can also use string.IsNullOrWhiteSpace instead of addressI.Length <= 0 which will consider white space as invalid values (if you are using .Net framework 4.0 or higher, otherwise use `string.IsNullOrEmpty).
private void save_Click(object sender, EventArgs e)
{
int civil_caseI;
if (!int.TryParse(civil_case.Text, out civil_caseI))
{
MessageBox.Show("Enter Number Only on CIVIL CASE");
return; //add that - early return
}
string areaI = area.Text;
if (string.IsNullOrEmpty(areaI.Trim()))
{
MessageBox.Show("Area Field must not be Empty");
return;
}
string addressI = address.Text;
if (string.IsNullOrEmpty(addressI.Trim())) //or addressI.Trim().Length <= 0
{
MessageBox.Show("Address Field must not be Empty");
return;
}
//HERE WILL BE THE QUERY TO INSERT THE DATA AFTER THE FORM IS VALIDATED.
}
You can also extract out the logic of your validation in a separate method returning bool and then call that method for validation.

Computing Form Location with Button

I'm working on a programming assignment, and I'm trying to make this button take the values from two textboxes, and calculate the new location for the form window. I'm having trouble converting the textbox values to type int, and being made usable by the btnCompute_click method.
private void btnCompute_Click(object sender, EventArgs e)
{
int x = Convert.ToInt32(txtXvalue);
int y = Convert.ToInt32(txtYvalue);
Location = new Point(x,y);
}
private void xValue_TextChanged(object sender, EventArgs e)
{
int xValue =
Convert.ToInt32(txtXvalue);
}
private void yValue_TextChanged(object sender, EventArgs e)
{
int y =
Convert.ToInt32(txtYvalue);
}
I forgot to add some additional info, the acceptable values for x and y must be positive. Would I use an if...else statement to control the acceptable values?
user29... i have no idea why death... replied that. it makes no sense to me. but you question makes sense to me. i suppose death... did not understand your question.
First off, everything you ask does not need anything in the TextChanged methods.
Do all your handling in the btnCompute_Click() method because you want to do something *when you click your button, not when the user edits the text of the text boxes, according to your question.
The code that is in your TextChanged() methods will get executed whenever the Text values of those text boxes change. that's not what you asked for it to do. But you could use these events for example, if you wanted a label to become visible or hidden and to set the text of a label which shows text, so you can use it as an error message label, for instance if the integer value of a text box is negative or even if it cannot be parsed.
So in your btnCompute_Click() methods, you first want to get the int values. You need to decide exactly what you want your code to do if the text is not integers. In my opinion, most beginners code things like message boxes or something. I like to give the user feedback with Labels or a status bar message, depending on what I feel is appropriate. Since my first choice would be to use a Label to show the 'error' message when text boxes cannot be parsed to integers, then i would simply return from the button click method without doing anything when the values are not what i want. That way the user gets their messages without annoying popup message boxes or anything. But it's up to you whether you want to pop up a message box or not. Others have given you good code to do that. I want to give you good code that avoids what i consider annoying popup boxes.
When converting strings to an int, Convert.ToInt32 will throw an error if the string cannot be parsed. int.TryParse is the silver bullet for truly parsing strings to integers without any error. Here is the entire code i would use. I made a new project just to make sure i'm not giving you buggy code. I give you my code on how I handle this.
In your updated prerequisite, you mention x & y must be positive and not negative. I note to you that these are not the same. For instance, 0 is neither positive nor negative. I assume that you technically mean that x and y cannot be negative, (and that it does not need to be positive, since 0 should be allowed).
private void Form1_Load(object sender, EventArgs e)
{
lblErrorX.Text = null;
lblErrorY.Text = null;
}
private void btnMoveForm_Click(object sender, EventArgs e)
{
int x = 0; if (int.TryParse(txtX.Text, out x) == false) { return; }
int y = 0; if (int.TryParse(txtY.Text, out y) == false) { return; }
if (x < 0 || y < 0) { return; }
this.Location = new Point(x, y);
}
private void txtX_TextChanged(object sender, EventArgs e)
{
int x = 0;
if (int.TryParse(txtX.Text, out x) == false)
{ lblErrorX.Text = "X is not an valid integer."; return; }
if (x < 0) { lblErrorX.Text = "X cannot be negative."; return; }
lblErrorX.Text = null;
}
private void txtY_TextChanged(object sender, EventArgs e)
{
int y = 0;
if (int.TryParse(txtY.Text, out y) == false)
{ lblErrorY.Text = "Y is not an valid integer."; return; }
if (y < 0) { lblErrorY.Text = "Y cannot be negative."; return; }
lblErrorY.Text = null;
}
In my project, on the form, in the following left to right order: lblX, txtX, lblErrorX. I have the same corresponding for Y: lblY, txtY, lblErrorY. Then i have one Button: btnMoveForm. So my txtX corresponds to your txtXvalue. my btnMoveForm corresponds to your btnCompute, but to me, 'compute' means to calculate, which is not really what this button is doing. this button is moving the form, so that's why i name it as such.
I have played with setting both the Location and the DesktopLocation and it seems to do the same thing. I've always used Location and i just learned that DesktopLocation works too, but since Location is shorter, i use it.
Someone asked why i don't use if(!int.TryParse(...)) { return; } rather than my if(int.TryParse(...) == false) { return; }. My reason is unfortunately that i think ! is an easy one character to miss when reading code, so i avoid it, especially when that little mistake means the opposite of what the code really would do. So my use of '== false' is always for human clarity. But i do like the C# ease of only needing one character. I just think it's a shame that in my opinion, it's a lot safer to write code that is better for humans so we don't mistake it. That's the only reason i use '== false' instead of !. Use ! if you like. It's quite convenient. I regret not using it. hehe.
Oh, and the reason i set the lblErrorX.Text = null; and lblErrorY.Text = null; is on my form in design view, i give them a text value so i can see them. :) so when the program runs, i set the Text to be blank. But you can use the Visible property if you prefer. I just leave them always visible and only set their Text properties.
Based on your expanded criteria you can check for negative numbers conditionally or use Math.Abs to get the absolute value. Something like this.
int x, y;
if (int.TryParse(txtXvalue.Text, out x) && int.TryParse(txtYvalue.Text, out y))
{
if (x < 0 || y < 0)
{
MessageBox.Show("Negative numbers not allowed");
}
else
Location = new Point(x, y);
}
else
{
MessageBox.Show("Must be an Integer");
}
or
int x, y;
if (int.TryParse(txtXvalue.Text, out x) && int.TryParse(txtYvalue.Text, out y))
{
Location = new Point(Math.Abs(x), Math.Abs(y));
}
else
{
MessageBox.Show("Must be an Integer");
}
I think you are looking for this.
private void btnCompute_Click(object sender, EventArgs e)
{
int x = Convert.ToInt32(txtXvalue.Text);
int y = Convert.ToInt32(txtYvalue.Text);
DesktopLocation = new Point(Math.Abs(x), Math.Abs(y));
}
This gets the location for the desktop. Also you need the .Text to get the text inside the textbox. You should also check to make sure the text is not null or empty before using or it will cause an error.
If this isn't what you are looking for please explain a little more.

Simple C# Windows App - Catch statement always executes no matter what

Here's the code for the event handler involved:
private void textBox1_TextChanged(object sender, EventArgs e)
{
try
{
seed = Convert.ToInt32(this.Text);
}
catch (FormatException)
{
MessageBox.Show("Input string is not a sequence of digits.");
}
catch (OverflowException)
{
MessageBox.Show("The number cannot fit in an Int32.");
}
}
It's supposed to ensure a user doesn't type anything but a number allowable by Int32 into the text box, but the first catch statement executes EVERY time you try to type ANYTHING into the box. I've looked around but I can't seem to figure out why...
Probably because this.Text doesn't read from the input box, but rather the class the handler is defined in.
I believe what you want is:
try
{
seed = Convert.ToInt32(((TextBox)caller).Text);
}
It might be helpful to see the error message, using the following (temporarily of course):
catch (FormatException exception)
{
MessageBox.Show("Input string is not a sequence of digits."
+ "Exception message was: " + exception.getMessage());
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
try
{
seed = Convert.ToInt32(textBox1.text);
}
catch (FormatException)
{
MessageBox.Show("Input string is not a sequence of digits.");
}
catch (OverflowException)
{
MessageBox.Show("The number cannot fit in an Int32.");
}
}
Please use the above statement and it should work correctly. If you type in a number the first exception will not execute.

How to catch the control name that caused exception in C#?

I have few text boxes that should allow a certain format, but when a user enters it in a wrong format in a textbox, I would like to catch the control name and clear the text of the textbox.
Clearing the user input because it's not in a given format is very user-unfriendly. What if only one of ten characters was wrong? They'd have to type it all over again. Just use a MaskedTextBox with a Mask for the pattern you expect.
When using a MaskedTextBox, you can subscribe to the MaskInputRejected event as described here:
public void Form1_Load(Object sender, EventArgs e)
{
... // Other initialization code
maskedTextBox1.Mask = "00/00/0000";
maskedTextBox1.MaskInputRejected += new MaskInputRejectedEventHandler(maskedTextBox1_MaskInputRejected)
}
void maskedTextBox1_MaskInputRejected(object sender, MaskInputRejectedEventArgs e)
{
toolTip1.ToolTipTitle = "Invalid Input";
toolTip1.Show("We're sorry, but only digits (0-9) are allowed in dates.", maskedTextBox1, maskedTextBox1.Location, 5000);
}
Throwing exceptions for expected behaviour is never right as they are very expensive. If you need to see where the exception originated just check the top line of the stack trace.
debug only
you can get control name in debug mode from the yourForm.cs . i dont think this code will run on relese cuz. the source file wont be in ther release right?
using System.Diagnostics;
public void ParseControlText()
{
try
{
var doubleval = Double.Parse(tb_double.Text);
var intval = Int32.Parse(tb_int.Text);
//... bunch of controls need to be parssed to calculate something
}
catch (FormatException ex)
{
var stlast = new StackTrace(ex,true).GetFrames().Last();
//this requires form.cs to exist . how am i gonna do this in release? idk
var stLine = File.ReadLines(stlast.GetFileName())
.ToList()[stlast.GetFileLineNumber()-1];
var m = Regex.Match(stLine ,#"\((.*?)\..*?\)");
var ctrlname = m.Groups[1].Value;
MessageBox.Show( ctrlname + " control's text coundnt be Parsed! " );
}
}

Categories

Resources