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.
Related
Is there any possible way to give condition that textbox focus is leave or not in any event
I tried following code but getting error
if (txt_partybillno.Leave == true)
{
// code
}
also
if (this.txt_partybillno.Leave == true)
{
// code
}
In Bills and Adjustments, an error message "Please upload invoice" needs to display if user tries to save without attaching/uploading a document.
I created a bool field, UsrFilesAttached, that does not persist. On Rowselected event, i get a count, set bool if 0 or not.
I tried updating AP.APRegister DAC to [PXUIRequired(typeof(Where>))]
I tried something else in the BLC but I can't find it now.
//in APInvoiceEntry
protected void APInvoice_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{
var inv = (APInvoice)e.Row;
bool attachedFiles = PXNoteAttribute.GetFileNotes(cache, cache.Current).Length != 0;
cache.SetValueExt<APRegisterExt.usrFilesAttached>(inv, attachedFiles);
}
// in DAC AP.APRegister
[PXBool]
[PXUIField(DisplayName="UsrFilesAttached")]
[PXDefault]
[PXUIRequired(typeof(Where<usrFilesAttached, Equal<False>>))]
I expect that if UsrFilesAttached is false an error will appear. I am able to save record whether UsrFilesAttached is true or false. Also, how do I add a custom error message?
This morning, I had a different thought about how to tackle this and it worked. I started over with this and it works:
protected void APInvoice_Hold_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
{
var inv = (APInvoice)e.Row;
if (inv == null)
return;
bool attachedFiles = PXNoteAttribute.GetFileNotes(cache, cache.Current).Length != 0;
if (attachedFiles == false)
{
cache.RaiseExceptionHandling<APRegister.hold>(inv, null, new PXSetPropertyException("Please attach invoice", PXErrorLevel.Error));
inv.Hold = true;
}
}
It makes better sense to do the check when trying to release the hold anyway. It can probably be improved on, so please teach me if you know a cleaner way. :)
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.
I am developing an app in C# which has forms that takes simillar inputs from users at different states.
I need to be able to validate them and for that reason I am using errorproviders
The code is working fine but I notice that with my current knowledge if I wanted to validate multiple forms then I will have to keep copy pasting the validation code for similar forms all over in each of them, I am wondering if there is a simpler way of reusing the validation code by having it in a central location that can be accessed by all of the forms instead of having to code it for each of them.
Below is a snippet of the validation code, in C#
//Methods to verify and user inputs
private bool ValidateName()
{
bool bStatus = true;
if (name.Text == string.Empty)
{
errorProvider2.SetError(name, "");
errorProvider1.SetError(name, "Please Enter Name");
bStatus = false;
}
else
{
errorProvider1.SetError(name, "");
errorProvider2.SetError(name, "Good");
bstatus = true;
}
return bStatus;
}
private void name_Validating(object sender, CancelEventArgs e)
{
ValidateName();
}
What I want to be able to do is have the method ValidateName() defined in such a way that I could just call it in the name_Validating() function of forms which has a textbox called name to validate it.
You'll want something along these lines. Not in front of a project so don't have the precise syntax though. It should point you in the right direction though
//Methods to verify and user inputs
private bool ValidateName(string aName)
{
bool bStatus = true;
// You'll need to fill this bit
// cast or instatiate a textbox here, let's call it txt_box_name
//
// cast : if you pass an object that you know is a textbox
//
// instantiate : you can create an instance of a textbox with Activator.CreateInstance
// more on that here: http://msdn.microsoft.com/en-us/library/system.activator.createinstance%28v=vs.110%29.aspx
//
// and then continue as normal with your generic text box field
if (txt_box_name.Text == string.Empty)
{
// do something
}
else
{
// do something else
}
return bStatus;
}
private void name_Validating(object sender, CancelEventArgs e)
{
ValidateName("name");
// or :
//ValidateName("username");
}
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.).