get and Set not working - c#

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.).

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.

TextBox accepts only int

I have a problem with my textbox. I wanted that one can manually set the interval of the x- and y-axis for a chart in the GUI over two textboxes. That works but when I type a char in or when I typed an int in and delete it, the program crashes immediately and I get a System.FormatException (without clicking the button to accept the changes). How can I solve it that one can just type in different signs without immediately crashing the program? My code below:
public void textBox2_TextChanged(object sender, EventArgs e)
{
x_axis_num = Convert.ToInt32(xAxisBox.Text, usC);
}
private void yAxisBox_TextChanged(object sender, EventArgs e)
{
y_axis_num = Convert.ToInt32(yAxisBox.Text);
}
That gets passed to another event:
chart1.ChartAreas[0].AxisX.Interval = x_axis_num;
chart1.ChartAreas[0].AxisY.Interval = y_axis_num;
In the line x_axis_num = Convert.ToInt32(xAxisBox.Text, usC);, you are taking whatever is in the text box and try to convert it to an integer value.
What do you think the conversion of "Hey, I'm not a number!" will do? It will crash horribly, basically because that text is not, and never will be, a number.
Instead, you can use the Int.TryParse method which will take any text and TRY to convert it to a number.
If the conversion is successful, then no problem. If it was not successful, then you get a false value on a flag indicating the text could not be converted.
Example:
int number;
bool result = Int32.TryParse(YourTextBox.Text, out number);
If the conversion is successful, then number has the value, otherwise, result is false so do something like this then:
if(result)
{
xAxisBox.Text = number.ToString();
x_axis_num = number;
}
else
{
xAxisBox.Text = string.Empty;
// Be careful here with what you set.
// This is the value you will set when the Text box has a non numeric value!
x_axis_num = 0;
}

C# Troubleshooting the error provider -- validating text box data input

everyone:
I'm trying to validate data in text boxes on a form. This is the code I have for my validator, but it's not working when I clearly violate the constraints set in the code (tabbing out of the txtbox, inputting less than 4 characters, etc. Any ideas of why this wouldn't work? The program runs, so it can't be syntax, so I suppose it must be logical error, but I just dont see it.
// Validation for Applicant Name text box
private void txtAppInfoName_Validating(object sender, CancelEventArgs e)
{
// Define what consitiutes a match
Match m = Regex.Match(txtAppInfoName.Text, #"\b[A-Za-z]\b");
if (m.Success == false)
{
errorProvider1.SetError(txtAppInfoName, "Please use only letters to type your name.");
txtAppInfoName.Select();
}
else if (txtAppInfoName.Text.Length < 4)
{
errorProvider1.SetError(txtAppInfoName, "Please type first and last names.");
txtAppInfoName.Select();
}
else if (txtAppInfoName.Text == "")
{
errorProvider1.SetError(txtAppInfoName, "Must enter a name.");
txtAppInfoName.Select();
}
else errorProvider1.SetError(txtAppInfoName, ""); // Remove the error provider
}
Most likely the handler is not even called at all. Make sure the handler txtAppInfoName_Validating is specified in the GUI designer under the Validating event.
If that doesn't work, try to add a breakpoint or throw an exception in the handler and see what happens.
If it stops, you can use the call-stack to inspect the error source.

How do I determine if the value of a string variable changed in C#?

I have something to do under a button click (add values to listbox) only if a particular string changes from its previous value. How do I manage this? Below is a sample of my code:
private void button6_Click(object sender, EventArgs e)
{
string x = //some varying value I get from other parts of my program
listBox1.Items.Clear();
listBox1.Items.Add(x + /*other things*/);
}
I can at times have same value for string x from previous value when clicking button6. In such cases I don't want listBox1 to add the item (string x). How to add to listbox only when value of string changes? There's no way to predetermine string x. It gets value when program is running.
Note: adding values to listBox1 every single time and later deleting the duplicates wont work in my program.
Have you considered keeping a copy of the old string value around in a private field, and simply comparing the new value to the old value to see if they match?
For example:
// holds a copy of the previous value for comparison purposes
private string oldString = string.Empty;
private void button6_Click(object sender, EventArgs e)
{
// Get the new string value
string newString = //some varying value I get from other parts of my program
// Compare the old string to the new one
if (oldString != newString)
{
// The string values are different, so update the ListBox
listBox1.Items.Clear();
listBox1.Items.Add(x + /*other things*/);
}
// Save the new value back into the temporary variable
oldString = newString;
}
Edit: As the other answers suggest, there are certainly other, more complicated solutions, like encapsulating all access to the string value in a property, or wrapping the string in a custom class. Some of these alternatives have the potential to be "cleaner", more object-oriented approaches. But they're all more complicated than simply saving the previous value in a field. It's up to you to decide whether your specific use case merits the complicated solution, or a simpler one. Think about long-term maintainability, not what's easier for you to implement right now.
string last = string.Empty;
private void button6_Click(object sender, EventArgs e)
{
string x = //some varying value I get from other parts of my program
if(x!=last)
{
listBox1.Items.Clear();
listBox1.Items.Add(x + /*other things*/);
last = x;
}
}
If this string is super important and gets passed around alot, maybe you should wrap it in a class. The class can hold the string value as a property, but also keep track of when it has changed.
public class StringValue
{
private bool _changed;
public string StrValue{get; set{ _changed = true;}
public bool Changed{get;set;}
}
this is rudimentery of course
I'm not sure I understand completely, but it sounds like you should be using a property to set String x;
string _x = string.Empty;
public string X
{
set
{
if(value != this._x)
{
DoFancyListBoxWork();
this._x = value;
}
}
get
{
return this._x;
}
}
If this is web application, store your last value into session variable. If this is windows application, store it at a class level variable or in singleton class and use this last value for comparison with new value.
On the page load add the current value to viewstate and at the button click check the current value is equal to the value in the view state. If both are equal we can say that the value is not changed.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["CurrentValue"] = Your Value;
}
}
protected void btnSubmit_click(object sender, EventArgs e)
{
if (NewValue== ViewState["CurrentValue"].ToString())
{
lblmsg.Text = "value is not changed..";
return;
}
else
lblmsg.Text = "value is changed..";
}
You can check the detailed article in this link.
Check Control Value is changed or not
First, I'd like to ask you to check most of the other answers. They are more complete, in that they treat more global issues of tracking the changes of a variable.
Now, I'm assuming, from reading the snippet of code you provided, that you need to track if a string was changed by the user. So, in other words, you probably have a TextBox or other kind of control through which the user can change that value. This is where you should focus your attention: just consume the TextChanged event.
If, however, I'm mistaken and your string comes from any other kind of external source, either use the wrapper class suggested by #Ryan Bennett or, if you are using .Net 4, use a dynamic container, which raises a PropertyChanged event whenever any property is changed.

C# and Winforms TextBox control: How do I get the text change?

I have an event handler for the TextBox.TextChanged event on a form of mine. In order to support undo, I'd like to figure out exactly what has changed in the TextBox, so that I can undo the change if the user asks for it. (I know the builtin textbox supports undo, but I'd like to have a single undo stack for the whole application)
Is there a reasonable way to do that? If not, is there a better way of supporting such an undo feature?
EDIT: Something like the following seems to work -- are there any better ideas? (It's times like this that I really wish .NET had something like the STL's std::mismatch algorithm...
class TextModification
{
private string _OldValue;
public string OldValue
{
get
{
return _OldValue;
}
}
private string _NewValue;
public string NewValue
{
get
{
return _NewValue;
}
}
private int _Position;
public int Position
{
get
{
return _Position;
}
}
public TextModification(string oldValue, string newValue, int position)
{
_OldValue = oldValue;
_NewValue = newValue;
_Position = position;
}
public void RevertTextbox(System.Windows.Forms.TextBox tb)
{
tb.Text = tb.Text.Substring(0, Position) + OldValue + tb.Text.Substring(Position + NewValue.Length);
}
}
private Stack<TextModification> changes = new Stack<TextModification>();
private string OldTBText = "";
private bool undoing = false;
private void Undoit()
{
if (changes.Count == 0)
return;
undoing = true;
changes.Pop().RevertTextbox(tbFilter);
OldTBText = tbFilter.Text;
undoing = false;
}
private void UpdateUndoStatus(TextBox caller)
{
int changeStartLocation = 0;
int changeEndTBLocation = caller.Text.Length;
int changeEndOldLocation = OldTBText.Length;
while (changeStartLocation < Math.Min(changeEndOldLocation, changeEndTBLocation) &&
caller.Text[changeStartLocation] == OldTBText[changeStartLocation])
changeStartLocation++;
while (changeEndTBLocation > 1 && changeEndOldLocation > 1 &&
caller.Text[changeEndTBLocation-1] == OldTBText[changeEndOldLocation-1])
{
changeEndTBLocation--;
changeEndOldLocation--;
}
changes.Push(new TextModification(
OldTBText.Substring(changeStartLocation, changeEndOldLocation - changeStartLocation),
caller.Text.Substring(changeStartLocation, changeEndTBLocation - changeStartLocation),
changeStartLocation));
OldTBText = caller.Text;
}
private void tbFilter_TextChanged(object sender, EventArgs e)
{
if (!undoing)
UpdateUndoStatus((TextBox)sender);
}
You might be better off using the Enter and Leave events instead. When entering, store the current text in a class variable, then when leaving compare the new text to the old.
Yes, don't tie it directly to the textbox. Your forms' state should be in some model object somewhere that isn't directly tied to the form (MVC is one way to do this, MVVM is another). By decoupling them like that, you can compare the new textbox value to the current model value whenever a change request comes in.
Actually, all I can think of is having some kind of collection where you store different string versions (so you can undo many times, not just once).
I would store the reference to TextBox's collections in TextBox.Tag, so it is straightforward to store/use it.
Last but not least, you update your collection of strings during the event TextChange. With no much work, you can maintain a full history, gettinjg the previous value from your own structure.
This is probably overkill for what you're trying to accomplish, but CSLA support n-level undo. CSLA is a great business objects framework written by Rocky Lhotka. The business objects handle the undo history and it flows to the UI through data binding.
Switching your app to use CSLA would be a big commitment, but another option would be to look through the freely available source code to see how he implemented it.
I am actually making an own Syntax-Highlight-System so I also need to know the changed text.
My solution is to watch for an enter or space or an depositioning of the cursor.
As WinForms provide the Keydown event I used the KeyEventArguments (e) and converted them to a char.
After that I storage the char into a string like :
string i="";
i+=convertedToChar; // convertedToChar = kc.ConvertToString(e.KeyData)
And as soon as there is a enter or space or depositioning - "event" I delete the string.
Result:
If a user enters a few chars and hit space I am able to read the last chars (till the last space).
An advantage would be the fact that you can use any delimiter char for that (as soon as they are storaged and provided by e.KeyCode)
However I hope that this is a solution for everybody watching this after 9years :D.
It´s never too late.

Categories