I have a TextBox control. I have set my KeyPress event of the TextBox so that the user is only allowed to enter digits:
private void txtbxRecurEveryXWeeks_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
}
}
But in addition to that I do not want the user to set the value of the TexBot to zero "0". But they still should be allowed to enter "10" or "3400" as the value. How can I achieve that?
It's probably best to ignore the keypress event and handle the lost focus event and check and ensure the value isn't 0 when the user is done typing.
EDIT: It was pointed out that the user could type "000" and lose focus which would cause this to fail. You can check and confirm the textbox has a value and parse it as an int to confirm it isn't 0.
private void txtbxRecurEveryXWeeks_LostFocus(object sender, EventArgs e)
{
int value;
if(!string.IsNullOrWhitespace(txtbxRecurEveryXWeeks.Text)
&& int.TryParse(txtbxRecurEveryXWeeks.Text, out value)
&& value > 0)
{
//Do something like clear the textbox value
}
}
In the assumption that you use winforms, consider using the NumericUpDown control to enter numbers. It has the Minimum property, which you could set to 1 to avoid zero input.
Use NumericUpDown with minimum value = 1 and hidden up and down buttons.
numericUpDown1.Minimum = 1;
numericUpDown1.Controls[0].Hide();
Related
I have already checked other questions here but the answers are not related to my issue. the following code allows textbox1 to only accept numbers if the physical keyboard (laptop) is pressed:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
char ch = e.KeyChar;
if ( !char.IsDigit(ch))
{
e.Handled = true;
}
}
but this is not what I wanted (I dont use physical laptop keyboard).
As shown in screenshot, I have windows form with buttons and a textbox. I designed this keyboard and it works well but I want textbox1 to only accept numbers and the ".".
There are only two lines of code inside each button (and only code in the project) which is:
private void buttonName_Click(object sender, EventArgs e)
{
// each button only has this code.
textBox1.Focus();
SendKeys.Send(buttonName.Text);
}
I know how to set txtbox to accept numbers if the physical (laptop ) keys are pressed but here in this case I have control buttons in windwos form and I want to set textBox1 to only accept numbers and the ".". Please help in how to achieve this. Thank you
Declare a string variable at form level, use it to store the last valid text and to restore it when an invalid text is entered on the TextChanged event of your textbox.
string previousText;
public Form1()
{
InitializeComponent();
previousText = String.Empty;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
int dummy, changeLenght, position;
if (!String.IsNullOrWhiteSpace(textBox1.Text) && !int.TryParse(textBox1.Text, out dummy))
{
position = textBox1.SelectionStart;
changeLenght = textBox1.TextLength - previousText.Length;
textBox1.Text = previousText;
textBox1.SelectionStart = position - changeLenght;
}
else
{
previousText = textBox1.Text;
}
}
position and changeLenght are used to keep the cursor where it was before restoring the text.
In case you want to accept numbers with decimals or something bigger than 2147483647, just change dummy to double and use double.TryParse instead of int.TryParse.
private void textBox1_TextChanged(object sender, EventArgs e)
{
int changeLenght, position;
double dummy;
if (!String.IsNullOrWhiteSpace(textBox1.Text) && !double.TryParse(textBox1.Text, out dummy))
{
...
}
}
Suppose button1 is your button control, you could do this:
private void allButtons_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
char c = btn.Text[0]; //assuming all buttons have exactly 1 character
if(Char.IsDigit(c) || c == '.')
{
//process
textBox1.Focus();
SendKeys.Send(btn.Text);
}
//otherwise don't
}
I'm assuming you put this in a common handler, to which you already wired all your buttons (i.e. allButtons_Click).
Problem with this approach, it allows you to type values like 0.0.1, which are most likely invalid in your context. Another way to handle this is to process TextChanged event, store previous value, and if new value is invalid, restore the old one. Unfortunately, TextBox class does not have TextChanging event, which could be a cleaner option.
The benefit of you determining the invalid value is modularity. For example, if you later decide your user can enter any value, but only numbers can pass validation, you could move your check from TextChanged to Validate button click or similar.
Why users may want that - suppose one of the options for input is copy/paste - they want to paste invalid data and edit it to become valid, for example abc123.5. If you limit them at the entry, this value will not be there at all, so they now need to manually paste into Notepad, cut out in the invalid characters, and paste again, which goes against productivity.
Generally, before implementing any user interface limitation, read "I won't allow my user to...", think well, whether it's justified enough. More often than not, you don't need to limit the user, even for the good purpose of keeping your DB valid etc. If possible, never put a concrete wall in front of them, you just need to guide them correctly through your workflow. You want users on your side, not against you.
In my program I have a TextBox who's value must be set in a specific integer range. If it is not within this range, it should warn the user and then highlight the incorrect text inside of the TextBox for re-editing (implying that the user must enter a value that is in the correct range before they are allowed to leave the TextBox). How would I change my code so that it performs these operations?
This is what I have so far. I am using a TextChanged event. This code warns the user about the restriction breach and refocuses (I would like to highlight the value instead) on the TextBox, but does not prevent the user from clicking out of it afterward:
int maxRevSpeed;
//Max Rev Speed -- Text Changed
private void maxRevSpeed_textChanged(object sender, RoutedEventArgs e)
{
if (maxRevSpeed_textBox.Text == "" || maxRevSpeed_textBox.Text == " ")
maxRevSpeed = 0;
else
{
maxRevSpeed = Convert.ToInt32(maxRevSpeed_textBox.Text);
if (maxRevSpeed <= 0 || maxRevSpeed > 45)
{
MessageBox.Show("Reverse Sensor speed must be between 0 and 45 FPM", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
}
maxRevSpeed_textBox.Focus();
}
}
Please note that this question is a revisit of a former question of mine. I am aware that it may be "frowned upon" to take this approach to a TextBox, but regardless I would still like to figure out how to implement such a thing. Thank you.
Update 1:
After looking at everyone's suggestions I have updated my code:
//Max Rev Speed -- Text Changed
private void maxRevSpeed_textChanged(object sender, RoutedEventArgs e)
{
if (maxRevSpeed_textBox.Text == "" || maxRevSpeed_textBox.Text == " ") //Is Empty or contains spaces
maxRevSpeed = 0;
else if (!Regex.IsMatch(maxRevSpeed_textBox.Text, #"^[\p{N}]+$")) //Contains characters
maxRevSpeed = 0;
else
maxRevSpeed = Convert.ToInt32(maxRevSpeed_textBox.Text);
}
//Max Rev Speed -- Lost Focus
private void maxRevSpeed_LostFocus(object sender, RoutedEventArgs e)
{
if (maxRevSpeed <= 0 || maxRevSpeed > 45)
{
MessageBox.Show("Reverse Sensor speed must be between 0 and 45 FPM", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
//Supposed to highlight incorrect text -- DOES NOT WORK
maxRevSpeed_textBox.SelectionStart = 0;
maxRevSpeed_textBox.SelectionLength = maxRevSpeed_textBox.Text.Length;
}
}
The integer representing the text in the textBox is now dealt with in the textChanged event. The LostFocus event handles the warning and the re-selection of the incorrect text value. However, the highlight text method works when it is in the textChanged event, but not in it's current location. Why is that, and how can I fix it?
If you just want to stop focus from leaving a TextBox, all you need to do is to set the Handled property of the KeyboardFocusChangedEventArgs object to true in a PreviewLostKeyboardFocus handler when your invalid condition is true:
private void PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
e.Handled = IsInvalidValue;
}
This of course assumes that you have a property named IsInvalidValue that you set to true when the entered data is invalid and false otherwise.
You can prevent the user from entering the text or out of range by using PreviewTextInput handler of textbox, call it like this.
private void textBox1_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (!char.IsDigit(e.Text, e.Text.Length - 1))
{
e.Handled = true;
}
}
The code above is for entering numbers only, you can change it according to your requirements, hope it helps :)
Hi I suppose you are using C#, here you can find a relevant post: C# auto highlight text in a textbox control
As they stated the following code should select the text inside texbox
In Windows Forms and WPF:
maxRevSpeed_textBox.SelectionStart = 0;
maxRevSpeed_textBox.SelectionLength = textbox.Text.Length;
All, I want to catch the event after I finish input the value of DataGridView cell so that I can validate the value. Is there any event DataGridView when focus-lose happen? What is the best way to make it? thanks.
You should use CellValidating event for this, see here MSDN.
Occurs when a cell loses input focus, enabling content validation.
and example (from MSDN as well)
private void dataGridView1_CellValidating(object sender,
DataGridViewCellValidatingEventArgs e)
{
dataGridView1.Rows[e.RowIndex].ErrorText = "";
int newInteger;
// Don't try to validate the 'new row' until finished
// editing since there
// is not any point in validating its initial value.
if (dataGridView1.Rows[e.RowIndex].IsNewRow) { return; }
if (!int.TryParse(e.FormattedValue.ToString(),
out newInteger) || newInteger < 0)
{
e.Cancel = true;
dataGridView1.Rows[e.RowIndex].ErrorText = "the value must be a non-negative integer";
}
}
I am using textbox and here's my problem...
I already have a handler where program will not allow anymore inputs when defined Maximum text length is reached. Here's the code:
private void txtText_KeyPress(object sender, KeyPressEventArgs e)
{
if (txtText.Text.Length > MaxLengthAllowed - 1 && e.KeyChar != 8)
{
e.Handled = true;
Console.Beep(2000, 90);
return;
}
}
Now my problem is when I press and HOLD a key (for example the letter A), it exceeds the "MaxLengthAllowed" then beeps.
Is this a fault or something like a limitation of the textbox? Or am I missing something?
This code is working fine when you are not HOLDING a key. Hence, that's my problem.
Just set the MaxLength property of the textbox. It's as simple as
textboxVar.MaxLength = maxLengthAllowed;
Hope that helps.
You could always subscribe a PropertyChanged event, which you can rig to fire whenever the Text property of the textbox changes. Have a read of how to raise an event on Property Change
You could use the KeyUp event instead. That only fires once when you release the key. KeyPress will be fired multiple times for as long as you hold down the key.
The TextBox.Text is not updated when TextBox.KeyPress is fired. For example, if the Text before KeyPress is A, When user types B, the Text is still A (not AB) in the KeyPress event handler. So you have to define your MaxLengthAllowed to be 1 less than the desired value. The code should look like this:
private void txtText_KeyPress(object sender, KeyPressEventArgs e)
{
if ((txtText.Text.Length > MaxLengthAllowed - 1) && e.KeyChar != 8)
{
e.Handled = true;
Console.Beep(2000, 90);
}
}
I think you should use TextBox.MaxLength property instead, it also supports Beep, the Beep sound is even nicer than the Beep generated by Console.Beep().
how to do validations for numeric,double and empty values for datagridview in c# windows application.Text values should not be allowed to enter the cells which are numeric or double.how to do it?
You Can validate datagrid view cell like this...
private void dataGridView1_CellValidating(object sender,DataGridViewCellValidatingEventArgs e)
{
// Validate the CompanyName entry by disallowing empty strings.
if (dataGridView1.Columns[e.ColumnIndex].Name == "CompanyName")
{
if (e.FormattedValue == null && String.IsNullOrEmpty(e.FormattedValue.ToString()))
{
dataGridView1.Rows[e.RowIndex].ErrorText =
"Company Name must not be empty";
e.Cancel = true;
}
}
}
void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
// Clear the row error in case the user presses ESC.
dataGridView1.Rows[e.RowIndex].ErrorText = String.Empty;
}
This validates only empty values , if you want validate numericals you can do like this...
I hope it will helps you...
If you'd like to restrict anything but numbers from being entered, you need to handle the EditingControlShowing event on the DataGridView. It can be done like this:
dataGridView.EditingControlShowing = new DataGridViewEditingControlShowingEventHandler (dataGridView_EditingControlShowing);
Then, define your handler:
void dataGridView_EditingControlShowing (object sender, DataGridViewEditingControlShowingEventArgs e)
{
TextBox tx = e.Control as TextBox;
tx.KeyPress += new KeyPressEventHandler (tx_KeyPress_int);
}
Then, define your KeyPress handler, and only handle numeric characters:
void tx_KeyPress_int (object sender, KeyPressEventArgs e)
{
if (!(char.IsNumber (e.KeyChar) || e.KeyChar == '\b'))
{
//is NOT number or is Backspace key
e.Handled = true;
}
}
Adjust to suit your exact needs accordingly (i.e. handle only input on a certain column, etc.)
If you want to validate cell values when user trying to leave cell, you should handle DataGridView.CellValidating event and process cell value there.
If you want to validate value when user typing it, you may handle KeyPress event.
To validate numeric values you may use code like this:
int number = 0;
if(!int.TryParce(cell.Value.ToString(), out number))
{
//report about error input
}
Please read this link.
http://msdn.microsoft.com/en-us/library/aa730881(v=vs.80).aspx
##Edit ,
if you try to use your own custom numeric control,
1. you no need to check any additional validation.
2. It is reusable.