C# skipping if not null - c#

I have a click event handler which has to check if two text boxes are null or not, if both aren't the values are given to two variables and passed to another method.
One variable is a String, the other an integer. If the String is null but the integer isn't, it will work fine(Which it shouldn't!). But, if the integer is null and the String isn't, it will give me an error which is expected because it should not have reached that point.
Here's the code:
private void btnInsert_Click(object sender, EventArgs e)
{
String ActorName;
int Position;
if ((txtPosition.Text != null))
{
if ((txtActorName.Text != null))
{
ActorName = txtActorName.Text;
Position = int.Parse(txtPosition.Text);
InsertIntoArrayList(ActorName, Position);
PopulateActors();
}
else
{
MessageBox.Show("Please enter an Actor Name");
return;
}
}
else
{
MessageBox.Show("Please enter a position");
return;
}
}
As you can see, if txtPosition is not null, it then tests txtActorName. If either are null, it throws the relevant message. Assuming both are not null, it assigns the values to the variables and passes these to the InsertIntoArrayLIst method, followed by a call to the PopulateActors method.
If I enter an Actor name and a position, everything works fine. It's only if I don't enter a position that it somehow misses the fact that nothings entered, then slips up at the line Position = int.Parse(txtPosition.Text); because txtPosition is null.
Any help would be greatly appreciated!

Try using e.g. !string.IsNullOrEmpty(txtPosition.Text) instead of txtPosition.Text != null.
Alternatively, just use txtPosition.Text != "". After all, the Text property should never actually be null.
And of course, you should apply the same fix to both values, txtPosition and txtActor.

Don't confuse null and empty strings. They aren't the same thing.
The Text property of any control will only ever be null if you explicitly set it to null. In most cases you don't need to check this at all for that property; just comparing to an empty string is good enough
The String.IsNullOrEmpty() and String.IsNullOrWhitespace() methods are your friends.
There's no reason to nest the If blocks. Just use guard clauses to check one followed by the other for cleaner code:
.
private void btnInsert_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhitespace(txtPosition.Text))
{
MessageBox.Show("Please enter a position");
return;
}
if (string.IsNullOrWhitespace(txtActorName.Text))
{
MessageBox.Show("Please enter an Actor Name");
return;
}
int Position;
if (!int.TryParse(txtPosition.Text, out Position))
{
MessageBox.Show("Please enter a number in the position field");
return;
}
InsertIntoArrayList(txtActorName.Text, Position);
PopulateActors();
}

You could also use if (!string.IsNullOrWhiteSpace(txtPosition.Text) if you want to check for white spaces as well. Although performance wise it is a bit slower then using the standard string.IsNullOrEmtpy
if (txtPosition.Text != string.Empty) is another way to check.

Try This, it may resolve your Problem
ActorName = txtActorName.Text;
Position = int.Parse(txtPosition.Text=="" ? "0" : txtPosition.Text);

Related

C# backspace on textbox creating errors immediately

I am creating an event where if someone types into a text box it will show an error using this code:
try
{
dblCostSqFt = double.Parse(txtCost.Text);
}
catch
{
MessageBox.Show("Error. You must enter valid numbers. Please correct.");
txtCost.Select();
return;
}
The issue with this is if I input a backspace it will throw that error message immediately I would like to make it to where that doesn't happen.
You're working with userinput here. Therefore i'd suggest to use Double.TryParse()
If you've got a string, and you expect it to always be a double (say, if some web service is handing you a double in string format), you'd use Double.Parse().
If you're collecting input from a user, you'd generally use Double.TryParse(), since it allows you more fine-grained control over the situation when the user enters invalid input.
With tryparse() your code will be something like this:
if (!double.TryParse(txtCost.Text, out var dblCostSqFt))
{
MessageBox.Show("Error. You must enter valid numbers. Please correct.");
txtExample.Select(0, txtCost.Text.Length);
return;
}
To make the example complete and address the issue one could simply check if the Text is not null or empty by using String.IsNullOrEmpty() making the whole code:
// makes sure your app isn't crashing upon backspaces.
if(string.IsNullOrEmpty(textCost.Text))
{
// Personally i'd indicate the user nothing is typed in (yet).
return;
}
if (!double.TryParse(txtCost.Text, out var dblCostSqFt))
{
// The user filled in something that can't be parse to doubles.
MessageBox.Show("Error. You must enter valid numbers. Please correct.");
txtExample.Select(0, txtCost.Text.Length);
return;
}
// All is great; Do stuff with dblCostSqFt.
Assuming you are using WPF for your UI without straying too far from what you have I would use something like below (as LarsTech suggested, use TryParse to test if the value can be converted). Note the if block surrounding the core code within the function, you can avoid execution entering the if block by checking if the key pressed was backspace. I also added a check for the enter key as many users would press the enter key to close the MessageBox, which would cause the event to trigger once again.
private void txtExample_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key != Key.Back && e.Key != Key.Enter)
{
double dblCostSqFt = 0;
if (!double.TryParse(txtExample.Text, out dblCostSqFt))
{
MessageBox.Show("Error. You must enter valid numbers. Please correct.");
txtExample.Select(0, txtExample.Text.Length);
}
}
}
Never rely on exception handling to control the workflow of your application, exceptions have a ton of overhead and it is typically a bad practice in general.
You can accomplish the same thing in WinForms as well using the following...
private void txtExample_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode != Keys.Back && e.KeyCode != Keys.Enter)
{
double dblCostSqFt = 0;
if (!double.TryParse(txtExample.Text, out dblCostSqFt))
{
MessageBox.Show("Error. You must enter valid numbers. Please correct.");
txtExample.Select();
}
}
}
It looks like you are using WinForms because your textbox.Select function call does not supply any arguments, only WinForms supports an overload of the select function without any arguments.

Clearing out a c# form text box

I am making a simple hangman style game in a C# form. I have it set as textBox1_TextChanged. Except everytime the user backspaces their guess letter it takes in blank space. How can I make it so after the message saying right/wrong it clears the space. I am getting annoyed at it telling the user they made a wrong guess after they backspace. This is my first post on this forum so sorry if the code text is weird. I just want the program to clear the text in the textBox after they guess.
UPDATE: Added suggested information. Now it does everything it is supposed to do. Except it pops up a windows saying " was found in the target word". This happens if guessLetter == null || guessLetter == correct || guessLetter == false.
private void textBox1_TextChanged(object sender, EventArgs e)
{
string guessLetter = textBox1.Text;
//textBox1.ReadOnly = true;
if (targetWord == null)
{
MessageBox.Show("Please start a new game.");
textBox1.Text = ("");
}
else
{
if (targetWord.Contains(guessLetter))
{
MessageBox.Show(guessLetter + " was found in the word");
}
else
{
MessageBox.Show(guessLetter + " was not found in the word");
incorrectGuessCtr++;
textBox3.Text = incorrectGuessCtr.ToString();
}
textBox1.Text = ("");
}
}
Don't only check if the targetWord is null, but also the guessLetter. You'd better use string.IsNullOrEmpty too, since it also checks if the string is empty:
if (!string.IsNullOrEmpty(targetWord) && !string.IsNullOrEmpty(guessLetter))
{
...
}
I guess you should also check if there is exactly one letter entered. That would mean this additional check:
if (guessLetter.Length == 1)
{
...
}
You will enter this event when you write code that changes Text property in textbox. I mean this.
textBox3.Text = incorrectGuessCtr.ToString();
Put something in function arguments or set some flags so that you can identify whether the event is called from user input or your clearing the text.
Just check how many times this function is called when user press backspace. You will get the idea.

Validation Logic

I am trying to create some validation for a form I have. There are two text boxes and two radio buttons on the form. My logic for this validation I know is a little rusty at the moment so any suggestions would be great.
Here is the code for what I have so far:
Keep in mind that the int errors is a public variable in the class
Start Button code:
private void btnStart_Click(object sender, EventArgs e)
{
errors = validateForm();
//Here I want the user to be able to fix any errors where I am little
stuck on that logic at the moment
//validate the form
while (errors > 0)
{
validateForm();
errors = validateForm();
}
}
ValidateForm Method:
private int validateForm()
{
errors = 0;
//check the form if there are any unentered values
if (txtDest.Text == "")
{
errors++;
}
if (txtExt.Text == "")
{
errors++;
}
if (validateRadioBtns() == true)
{
errors++;
}
return errors;
}
ValidateRadioBtns Method:
private Boolean validateRadioBtns()
{
//flag - false: selected, true: none selected
Boolean blnFlag = false;
//both of the radio buttons are unchecked
if (radAll.Checked == false && radOther.Checked == false)
{
blnFlag = true;
}
//check if there is a value entered in the text box if other is checked
else if(radOther.Checked == true && txtExt.Text == "")
{
blnFlag = true;
}
return blnFlag;
}
Overall I feel like this can somehow be more stream lined which I am fairly stuck on.
Any suggestions would be greatly appreciated since I know this is such a nooby question.
Well first since you have said that you want to validate for non-entered values, did you consider white spaces as an entry? since someone can just press space and then your validation would pass.
Aside from that, you might want to indicate which textbox they did not fill out or which group they did not click, it seems like you are using web forms so here is a walkthrough http://msdn.microsoft.com/en-us/library/vstudio/a0z2h4sw(v=vs.100).aspx.
If you are using windows forms you can use this walkthrough http://msdn.microsoft.com/en-us/library/ms229603(v=vs.110).aspx.
If you need to keep the existing logic, I would suggest extracting the repeating logic into separate functions and temporary btnFlag is not necessary also as you can return true and return false at the end.
private Boolean validateRadioBtns()
{
if (radAll.Checked == false && radOther.Checked == false)
return true;
else if(radOther.Checked == true && txtExt.Text.Trim().Length == 0 ) //just a quick sample of how you can trim the spaces and check for length
return true;
return false;
}
See the documentation for the validation patterns. You have chosen the explicit validation strategy, for which you would use the ContainerControl.ValidateChildren method and either perform your "Start" action or not.
Windows Forms has dedicated events for validation that allow you to react accordingly for each of your controls. You'll use Control.Validating and Control.Validated events.
So, unless ValidateChildren returns true, you don't need to initiate your "Start" action, i.e. the logic would become trivial.
P.S. you also probably don't need the errors variable as a class member since you return it from your validation function. For showing the error, prefer the "Tell, Don't Ask" idea by separating the error visualization in a separate component.

Check if unassigned variable exists in Request.QueryString

Within the context of an ASP.NET page, I can use Request.QueryString to get a collection of the key/value pairs in the query string portion of the URI.
For example, if I load my page using http://local/Default.aspx?test=value, then I can call the following code:
//http://local/Default.aspx?test=value
protected void Page_Load(object sender, EventArgs e)
{
string value = Request.QueryString["test"]; // == "value"
}
Ideally what I want to do is check to see if test exists at all, so I can call the page using http://local/Default.aspx?test and get a boolean telling me whether test exists in the query string. Something like this:
//http://local/Default.aspx?test
protected void Page_Load(object sender, EventArgs e)
{
bool testExists = Request.QueryString.HasKey("test"); // == True
}
So ideally what I want is a boolean value that tell me whether the test variable is present in the string or not.
I suppose I could just use regex to check the string, but I was curious if anybody had a more elegant solution.
I've tried the following:
//http://local/Default.aspx?test
Request.QueryString.AllKeys.Contains("test"); // == False (Should be true)
Request.QueryString.Keys[0]; // == null (Should be "test")
Request.QueryString.GetKey(0); // == null (Should be "test")
This behavior is different than PHP, for example, where I can just use
$testExists = isset($_REQUEST['test']); // == True
Request.QueryString.GetValues(null) will get a list of keys with no values
Request.QueryString.GetValues(null).Contains("test") will return true
I wrote an extension method to solve this task:
public static bool ContainsKey(this NameValueCollection collection, string key)
{
if (collection.AllKeys.Contains(key))
return true;
// ReSharper disable once AssignNullToNotNullAttribute
var keysWithoutValues = collection.GetValues(null);
return keysWithoutValues != null && keysWithoutValues.Contains(key);
}
Request.QueryString is a NameValueCollection, but items are only added to it if the query string is in the usual [name=value]* format. If not, it is empty.
If your QueryString was of the form ?test=value, then Request.QueryString.AllKeys.Contains("test") would do what you want. Otherwise, you're stuck doing string operations on Request.Url.Query.
I use this.
if (Request.Params["test"] != null)
{
//Is Set
}
else if(Request.QueryString.GetValues(null) != null &&
Array.IndexOf(Request.QueryString.GetValues(null),"test") > -1)
{
//Not set
}
else
{
//Does not exist
}
TRY this one, it solved my issue!
It will count either the query string has a value or empty and then you can check the required query string value with the Key.
if (!Page.IsPostBack)
{
if (Request.QueryString.Count > 0)
{
if (Request.QueryString["departmentId"] != null)
{
GetSurveyByDeptAndStatus(departmentId: Request.QueryString["departmentId"], status: "Not Surveyed");
rbListEmpsSurvey.Items[1].Selected = true;
}
else if (Request.QueryString["SurveyStatus"] != null)
{
SatisfactionStatus = Request.QueryString["SurveyStatus"] "";
GetSurveyByDeptAndStatus(status: SatisfactionStatus);
GetDepartments();
}}}
Request.QueryString.ToString().Contains("test")
This works in the special case where you're looking for a single querystring parameter, e.g. MyFile.aspx?test
For more complex, general, cases then other solutions would be better.

get and Set not working

I am writing the following get and set for validating an input from a Text Box. Basically it is supposed to check if the user has entered all of the values.
When I leave the TextBoxes empty , it does nothing and shows a '0' in output where that variable was being used. It does however show the system generated exception and stops the execution, but I wonder why doesn't it validate the input through the properties?
Here is my code:
public double RecoDoseSize
{
get
{
return recoDoseSize;
}
set
{
if (!(value>0))
{
MessageBox.Show("Please Enter the recommended dose size for this product");
textBox8.Focus();
}
recoDoseSize = value;
}
}
private void Submit2_Click(object sender, RoutedEventArgs e)
{
TotalContentProduct = double.Parse(textBox7.Text);
recoDoseSize = double.Parse(textBox8.Text);
NoOfDosespUnit = TotalContentProduct/recoDoseSize;
}
You are setting recoDoseSize, the backing field, not RecoDoseSize, the property which has your code in it. Thus, your code isn't executed. You need to change the second line of your method body to
RecoDoseSize = double.Parse(textBox8.Text);
(note the capital R).
Other have given the correct answer to the question as stated. Namely that you should call the uppercased RecoDoseSize if you want to use the getter/setter.
However it is extremely bad practice to show a message box inside the setter, because it violates the Principle of Least Surprise.
When someone looks at the line RecoDoseSize = double.Parse(textBox8.Text); it is not at all obvious that this operation could cause a message box to appear.
There are occasionally exceptions where it does make sense to have a setter trigger UI changes (for instance the Visible property on controls) however the default should always be to not do this unless you are sure it will be more confusing to not do so (for instance it would be surprising if you set Visible = false however it was still visible).
Regarding your comment on how you should implement it, the checking should be done in the click handler and the property can just be an auto-property, like so:
public double RecoDoseSize { get; set; }
private void Submit2_Click(object sender, RoutedEventArgs e)
{
TotalContentProduct = double.Parse(textBox7.Text);
double enteredSize;
if (!double.TryParse(textBox8.Text, out enteredSize) || enteredSize <= 0)
{
MessageBox.Show("Please Enter the recommended dose size for this product");
textBox8.Focus();
return;
}
RecoDoseSize = enteredSize;
NoOfDosespUnit = TotalContentProduct / recoDoseSize;
}
You'll want to use TryParse because with Parse you'll get an error if the text isn't a valid double. What TryParse does is return true or false depending on whether it succeeded, and it populates the out parameter with the result if it's successful.
So what this does is if it either failed to parse the result, or the result is <= 0 it shows the message box. In that case it also returns from the method so the rest of it isn't executed. Alternatively the rest of the method could be in an else block in which case the return isn't needed. It's a matter a style which way is preferred.
You're never actually using the getter/setter. You are using the actual field name: recoDoseSize directly. Change it to RecoDoseSize.
private void Submit2_Click(object sender, RoutedEventArgs e)
{
TotalContentProduct = double.Parse(textBox7.Text);
RecoDoseSize= double.Parse(textBox8.Text);
NoOfDosespUnit = TotalContentProduct/recoDoseSize;
}
You shouldn't be handling focus in your set statement.
Also, you need to make sure that value is not null, otherwise you can't compare it to anything (greater-than, etc.).

Categories