Windows Form. Limit User input to a certain range - c#

I am creating a windows form program for class and I am trying to limit input for a 'weight' textbox from 1-1000. I got the user input to parse to a double but some reason the error message I created will not popup at the right time as intended. (The error message will popup only if I enter digits passed 5 digits... so I can enter 2222 or 10000 without an error)
private void Weight_KeyPress(object sender, KeyPressEventArgs e)
{
var sourceValue = Weight.Text;
double doubleValue;
if (double.TryParse(sourceValue, out doubleValue))
{
if (doubleValue > 1000 )
{
MessageBox.Show("Cannot be greater than 1000");
}
}
}

instead of using KeyPress you should use TextChanged event
because if you use keypress the new char is not part of the control text yet.
private void inputTextBox_TextChanged(object sender, EventArgs e)
{
var inputTextBox = sender as TextBox;
var sourceValue = inputTextBox.Text;
double doubleValue;
if (double.TryParse(sourceValue, out doubleValue))
{
if (doubleValue > 1000)
{
MessageBox.Show("Cannot be greater than 1000");
}
}
}

Related

Windows Form App Float to String

Below is some of my code that isn't working. I wanted to see it could count the number of spaces in the text box so I'm having it display the number in a message box and it currently just throws a blank one. The problem is either in the float to string conversion or in the counter.
private static string _globalVar = "n";
public static string GlobalVar
{
get { return _globalVar; }
set { _globalVar = value; }
}
public Form1()
{
InitializeComponent();
button1.Text = "Enter";
}
string LNum { get; set; }
public void button1_Click_1(object sender, EventArgs e)
{
MessageBox.Show(LNum);
}
public void richTextBox1_TextChanged(object sender, System.Windows.Forms.KeyEventArgs e)
{
float n = 0;
if (Control.ModifierKeys == Keys.Space)
{
n = n + 1; ;
}
string.Format("{0:N1}", n);
string LNum = Convert.ToString(n);
}
What you are doing is an excellent way to learn how and when the events are raised and how they can be leveraged to customize an applications behavior and is something similar to what many of us have done over the years.
Based on what you say you are wanting to do, there are several issues. If you take a look at this code, it will do what you want.
public void button1_Click(object sender, EventArgs e)
{
int n = 0;
for (int counter = 0; counter < richTextBox1.TextLength; counter++)
{
if (richTextBox1.Text[counter] == ' ')
{
n++;
}
}
MessageBox.Show(n.ToString("N1"));
}
The key difference is that I am only looking at the entered text when the button is clicked. (TextChanged is run every time there is a change in the text displayed). I chose not to use a float variable to store the count of spaces as the count will always be an integer.
In addition, the parameter to TextChanged System.Windows.Forms.KeyEventArgs e is incorrect and will never compile if correctly bound to the TextChanged event.
The KeyEventArgs parameter is used by the KeyUp and KeyDown events. If you use these events, you will be looking to count every time the space bar is pressed and not the number of spaces in the text box. And like their name suggests, the events are raised every time a Key on the keyboard goes Up (Pressed) and Down (Released).

C# - Copy input from one textbox to another and vise versa

this is my first post and I'm fairly new to C#
I'm trying to create a Celsius to Fahrenheit converter and vise versa.
I have two textboxes, the user can either input a number into the Celsius textbox and the Fahrenheit will automatically be calculated and displayed into the Fahrenheit textbox or the user can input into the Fahrenheit and the Celsius value will be calculated and output.
Here is the code I have so far, this is a WFA.
private void txtCelsius_TextChanged(object sender, EventArgs e)
{
///*
if(string.IsNullOrEmpty(txtCelsius.Text))
{
txtFahrenheit.Clear();
return;
}
txtFahrenheit.Text = ((double.Parse(txtCelsius.Text)) * 1.8 + 32).ToString();
//*/
}
private void txtFahrenheit_TextChanged_1(object sender, EventArgs e)
{
///*
if (string.IsNullOrEmpty(txtFahrenheit.Text))
{
txtCelsius.Clear();
return;
}
txtCelsius.Text = ((double.Parse(txtFahrenheit.Text)) / 1.8 - 32).ToString();
//*/
}
Clearly, when I run this and input a value into either one of the textbox it will create an infinite loop. If I comment one or the other out it works for the other one.
Can someone help? Is there a way I can do something like the following pseudocode.
if textbox1 is getting input
textbox2.input = disabled
do calculations and display
if textbox2 is getting input
textbox1.input = disabled
do calculations and display
If tried searching for a solution but finding it hard to word what I'm looking for and coming up with no solutions.
PS. I keep seeing this in other posts, this is not homework, I'm just trying to come up with small programs to learn.
You are getting into an infinite loop because each time you update the other text boxes value it's firing the TextChanged event. To handle this add a variable to control when to update use TextChanged code.
bool _updating = false;
private void txtCelsius_TextChanged(object sender, EventArgs e)
{
if (!_updating)
{
try
{
_updating = true;
///*
if(string.IsNullOrEmpty(txtCelsius.Text))
{
txtFahrenheit.Clear();
return;
}
txtFahrenheit.Text = ((double.Parse(txtCelsius.Text)) * 1.8 + 32).ToString();
//*/
}
finally
{
_updating = false;
}
}
}
private void txtFahrenheit_TextChanged_1(object sender, EventArgs e)
{
if (!_updating)
{
try
{
_updating = true;
///*
if (string.IsNullOrEmpty(txtFahrenheit.Text))
{
txtCelsius.Clear();
return;
}
txtCelsius.Text = ((double.Parse(txtFahrenheit.Text)) / 1.8 - 32).ToString();
//*/
}
finally
{
_updating = false;
}
}
}

C# - refresh textbox while typing value

How can i make auto refresh textbox while typing value like this?
i tried to do the same but it did not work. i always to hit ENTER to refresh or click on up/down arrows to refresh the value
here is the code
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
try
{
double a = double.Parse(s1.Text); //textbox 1
double b = double.Parse(s2.Text); //textbox 2
double s = a * b;
resultSpeed.Text = "" + s; //s is the result
}
catch
{
MessageBox.Show("Please input the number");
}
}
Just use event KeyUp. It will trigger every time you put a symbol.
ValueChanged isn't working because it only triggers when you are done with editing - you press enter or change focus.
So basically change your event from ValueChanged to KeyUp.
I'm not posting any code because the only change will be subcribing to other event. Your function is fine, however you should change its name :)
Put your code into textbox's TextChanged Event.
Like this
private void textBox1_TextChanged(object sender, EventArgs e)
{
calculate();
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
calculate();
}
private void calculate()
{
double a = 0, b = 0, demo;
if (double.TryParse(textBox1.Text, out demo))
a = double.Parse(textBox1.Text); //textbox 1
if (double.TryParse(textBox2.Text, out demo))
b = double.Parse(textBox2.Text); //textbox 2
double s = a * b;
textBox3.Text = s.ToString(); //s is the result
}

Why are numeric keystrokes appearing twice?

I'm new to C#. Using the code below, whenever I press a number key on my keyboard, it will display twice in the textbox. When I press "1" on the keyboard it will display
"11", and when I press "2" it will display "22". Why is this?
private void Window_TextInput(object sender, TextCompositionEventArgs e)
{
if(!isNumeric(e.Text))
{
string display = string.Empty;
display += e.Text;
displayNum(display);
}
else
{
String inputOperator = string.Empty;
inputOperator += e.Text;
if (inputOperator.Equals("+"))
{
ApplySign(sign.addition, "+");
}
}
}
private bool isNumeric(string str)
{
System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex("[^0-9]");
return reg.IsMatch(str);
}
private void window_keyUp(object sender, KeyEventArgs e)
{
if (e.Key >= Key.D0 && e.Key <= Key.D9)
{
int num = e.Key - Key.D0;
outputText2.Text += num;
}
}
private void BtnNum_Click(object sender, RoutedEventArgs e)
{
Button num = ((Button)sender);
displayNum(num.Content.ToString());
}
private void displayNum(String n)
{
if (operator1 == 0 && double.Parse(n) == 0)
{
}
else
{
if (operator1 == 0)
{
outputText2.Clear();
}
outputText2.Text += n;
operator1 = double.Parse(outputText2.Text);
outputText2.Text = Convert.ToString(operator1);
}
}
You have two events that are handeling the Keyboard events. Although not really sure what the displayNum() method is doing
I am assuming the Window_TextInput event is the event you wish to primarily handle the event.
Try adding
e.Handled = true;
In the Window_TextInput method. If that doesn't solve the problem can you post the displayNum() method?
EDIT:
After further review of the code and trying the same I do not see the relevance for the window_keyUp method as your Window_TextInput handles the input characters and has more applicable logic for handling the TextInput changes.
After I removed the window_keyUp event method the output appeared as expected (although commented out the ApplySign() method.
You've subscribed to two window-level text-related events - TextInput and KeyUp - and both of them end up appending input to the TextBox.
window_keyUp appends numbers to the TextBox
It looks like Window_TextInput is supposed to append non-numeric characters, but your RegEx is incorrect ([^0-9] matches anything that is not numeric, so IsNumeric returns True if the input is not a number)
The effect is that every numeric key press shows up twice.

Event located immediately after DataSource Update from ActiveEditor in Grid

What I need to do is calculated the value of one field in the grid, based on the values of other fields in the grid. I need to run this calculation After the value in one of the dependent cells is changed, but only if the value was a Valid entry. The EditValueChanged, Validating, and Validated events of the editor/repository all occur before the data is posted back into the datasource. I am wondering if there is any event I can hook into that will allow me to fire this calculation after the data has been post back into the datasource, but before control is returned to the user.
Sample Code
//calculation functions
private void SetCalcROP(MyObjectt Row)
{
//rop = m/hr
TimeSpan ts = Row.ToTime - Row.FromTime;
double diffDepth = Row.EndDepth - Row.StartDepth;
if (ts.TotalHours > 0)//donot divide by 0
Row.ROP = diffDepth / ts.TotalHours;
else
Row.ROP = 0;
}
private void SetCalcDeltaP(MyObject Row)
{
Row.DeltaPress = Row.SPPOnBtm - Row.SPPOffBtm;
}
//events
private void repNumberInput_Validated(object sender, EventArgs e) //is actaully ActiveEditor_Validated
{
if (vwDDJournal.FocusedColumn.Equals(colSPPOff) || vwDDJournal.FocusedColumn.Equals(colSPPOn))
SetCalcDeltaP(vwDDJournal.GetFocusedRow() as MyObject);
}
private void repNumberInput_NoNulls_Validated(object sender, EventArgs e) //is actaully ActiveEditor_Validated
{
if (vwDDJournal.FocusedColumn.Equals(colStartDepth) || vwDDJournal.FocusedColumn.Equals(colEndDepth))
SetCalcROP(vwDDJournal.GetFocusedRow() as MyObject);
}
private void repTimeEdit_Validated(object sender, EventArgs e) //is actaully ActiveEditor_Validated
{
SetCalcROP(vwDDJournal.GetFocusedRow() as MyObject);
}
private void repNumberInput_NoNulls_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
TextEdit TE = sender as TextEdit;
//null is not valid for this entry;
if (string.IsNullOrEmpty(TE.Text))
{
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "This Column may not be blank");
return;
}
else
{
double tmp;
if (!Double.TryParse(TE.Text, out tmp))
{
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "This Column must contain a number");
return;
}
}
}
private void repNumberInput_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
TextEdit TE = sender as TextEdit;
//null is not valid for this entry;
if (!string.IsNullOrEmpty(TE.Text))
{
double tmp;
if (!Double.TryParse(TE.Text, out tmp))
{
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "This Column must contain a number");
return;
}
}
}
private void repTimeEdit_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
if (vwDDJournal.FocusedColumn.Equals(colToTime))
{//dont bother to check from time
//TIME TRAVEL CHECK!!!!
DateTime FromTime = Convert.ToDateTime(vwDDJournal.GetRowCellValue(vwDDJournal.FocusedRowHandle, colFromTime));
TimeEdit te = sender as TimeEdit;
DateTime ToTime = Convert.ToDateTime(te.EditValue);
if (ToTime < FromTime)
{//TIME TRAVEL
e.Cancel = true;
vwDDJournal.SetColumnError(vwDDJournal.FocusedColumn, "To Time must be greater than From Time");
return;
}
}
}
the problem is that everywhere I call this from, and whether I use vwDDJournal.GetRowCellValue(...) or vwDDJournal.GetFocusedRow() as MyObject, I still get the old edit value.
Requirements
I have to have the input validated before running the calculation.
I have to run the calculation immediately after making the change.
... What I need to do is calculated the value of one field in the grid, based on the values of other fields in the grid.
The best way to accomplish this task is using Unbound Columns feature.
The following example demonstrates how to implement this feature by handling the ColumnView.CustomUnboundColumnData event:
// Provides data for the Total column.
void gridView1_CustomUnboundColumnData(object sender, CustomColumnDataEventArgs e) {
if (e.Column.FieldName == "Total" && e.IsGetData) e.Value =
getTotalValue(e.ListSourceRowIndex);
}
// Returns the total amount for a specific row.
decimal getTotalValue(int listSourceRowIndex) {
DataRow row = nwindDataSet.Tables["Order Details"].Rows[listSourceRowIndex];
decimal unitPrice = Convert.ToDecimal(row["UnitPrice"]);
decimal quantity = Convert.ToDecimal(row["Quantity"]);
decimal discount = Convert.ToDecimal(row["Discount"]);
return unitPrice * quantity * (1 - discount);
}
Original example: How to: Add an Unbound Column Storing Arbitrary Data
You can also implement calculated value for unbound column using expressions:
GridColumn columnTotal = new GridColumn();
columnTotal.FieldName = "Total";
columnTotal.Caption = "Total";
columnTotal.UnboundType = DevExpress.Data.UnboundColumnType.Decimal;
columnTotal.UnboundExpression = "[Quantity] * [UnitPrice] * (1 - [Discount])";
gridView1.Columns.Add(columnTotal);
How about CustomCellValue?
After posting back to the data source refresh the data.
It's called whenever data is updated or view is changed.

Categories