I have a Silverlight app with a textbox whose input I want to limit to decimal numbers only. Searching the web I came across the following possible solution (curiously in different places with different people claiming authorship of the same lines of code)
It appears to work well except that after at least 1 numeral has been entered it will then allow the letter 'd' in either upper or lower case to be entered, I can't figure out why that is and thus can't figure out how to prevent that from happening. Could anyone please provide a solution. Many thanks.
private void Unit_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Tab)
{
}
var thisKeyStr = "";
if (e.PlatformKeyCode == 190 || e.PlatformKeyCode == 110)
{
thisKeyStr = ".";
}
else
{
thisKeyStr = e.Key.ToString().Replace("D", "").Replace("NumPad", "");
}
var s = (sender as TextBox).Text + thisKeyStr;
var rStr = "^[0-9]+[.]?[0-9]*$";
var r = new Regex(rStr, RegexOptions.IgnoreCase);
e.Handled = !r.IsMatch(s);
}
You could try the following:
Replace the else with else if (e.Key != Key.D) or
set the Handled property like this:
e.Handled = !r.IsMatch(s) || string.IsNullOrEmpty(thisKeyStr);
// also possible:
e.Handled = !r.IsMatch(s) || e.Key == Key.D;
here is a easier code optimized. NO object creation; NO string comparision and NO regex validation
private static void TextBox_KeyDown(object sender, KeyEventArgs e)
{
//platform code for Hyphen which is not same as Subtract symbol but in our case both give same meaning
const int KEYCODE_Hyphen_OnKeyboard = 189;
const int KEYCODE_Dot_OnKeyboard = 190;
const int KEYCODE_Dot_OnNumericKeyPad = 110;
e.Handled = !(
(!( //No modifier key must be pressed
(Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift
|| (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control
|| (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt
)
&& ( //only these keys are supported
(e.Key >= Key.D0 && e.Key <= Key.D9) || (e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9)
|| e.Key == Key.Subtract || e.Key == Key.Add || e.Key == Key.Decimal
|| e.Key == Key.Home || e.Key == Key.End || e.Key == Key.Delete
|| e.Key == Key.Tab || e.Key == Key.Enter || e.Key == Key.Escape || e.Key == Key.Back
|| (e.Key == Key.Unknown && (
e.PlatformKeyCode == KEYCODE_Hyphen_OnKeyboard
|| e.PlatformKeyCode == KEYCODE_Dot_OnKeyboard || e.PlatformKeyCode == KEYCODE_Dot_OnNumericKeyPad
)
)
)
)
);
}
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
bool isDigit = e.Key >= Key.D0 && e.Key < Key.D9 || e.Key == Key.NumPad0 || e.Key == Key.NumPad1 || e.Key == Key.NumPad2 || e.Key == Key.NumPad3 || e.Key == Key.NumPad4 || e.Key == Key.NumPad5 || e.Key == Key.NumPad6 ||
e.Key == Key.NumPad7 || e.Key == Key.NumPad8 || e.Key == Key.NumPad9 ||e.Key == Key.Back || e.Key == Key.Delete || e.Key == Key.Left || e.Key == Key.Right;
if (isDigit) { }
else
e.Handled = true;
}
Related
I want to validate TextBox to allow only 1 decimal point and up to 2 decimal places after it. For number validate only, i am using InputScope="Number", but it can not avoid pasting letters, so i need any validation for paste too (or just disable pasting). For example the user must be able to insert numbers like 23, 23.1, 23.12 and NOT 23.123, 23.1.2 etc.
private void tb1_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key >= Windows.System.VirtualKey.Number0 && e.Key <= Windows.System.VirtualKey.Number9 || e.Key == Windows.System.VirtualKey.Decimal || e.Key == Windows.System.VirtualKey.GamepadY)
{
string strkey = e.Key.ToString().Substring(e.Key.ToString().Length - 1, e.Key.ToString().Length - (e.Key.ToString().Length - 1));
if (e.Key >= Windows.System.VirtualKey.Number0 && e.Key <= Windows.System.VirtualKey.Number9)
{
TextBox tb = sender as TextBox;
int cursorPosLeft = tb.SelectionStart;
int cursorPosRight = tb.SelectionStart + tb.SelectionLength;
string result1 = tb.Text.Substring(0, cursorPosLeft) + strkey + tb.Text.Substring(cursorPosRight);
string[] parts = result1.Split('.');
if (parts.Length > 1)
{
if (parts[1].Length > 2 || parts.Length > 2)
{
e.Handled = true;
}
}
}
if (((TextBox)sender).Text.Contains(".") && e.Key == Windows.System.VirtualKey.Decimal)
{
e.Handled = true;
}
}
else
{
e.Handled = true;
}
if (e.Key >= Windows.System.VirtualKey.A && e.Key <= Windows.System.VirtualKey.Z ||
e.Key == Windows.System.VirtualKey.Space)
{
e.Handled = true;
}
}
I have previewKeyDown method in my window, and I'd like to know that pressed key is only A-Z letter or 1-0 number (without anyF1..12, enter, ctrl, alt etc - just letter or number).
I've tried Char.IsLetter, but i need to give the char, so e.key.ToString()[0] doesn't work, because it is almost everytime a letter.
Something like this will do:
if ((e.Key >= Key.A && e.Key <= Key.Z) || (e.Key >= Key.D0 && e.Key <= Key.D9) || (e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9))
Of course you will also have to check that no modifier keys like CTRL are pressed according to your requirements.
e.Key is giving you a member of the enum System.Windows.Input.Key
You should be able to do the following to determine whether it is a letter or a number:
var isNumber = e.Key >= Key.D0 && e.Key <= Key.D9;
var isLetter = e.Key >= Key.A && e.Key <= Key.Z;
In your specific case the answer provided by Jon and Jeffery is probably best, however if you need to test your string for some other letter/number logic then you can use the KeyConverter class to convert a System.Windows.Input.Key to a string
var strKey = new KeyConverter().ConvertToString(e.Key);
You'll still need to check to see if any modifier keys are being held down (Shift, Ctrl, and Alt), and it should also be noted that this only works for Letters and Numbers. Special characters (such as commas, quotes, etc) will get displayed the same as e.Key.ToString()
try this, it works.
private void txbNumber_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key >= Key.D0 && e.Key <= Key.D9) ; // it`s number
else if (e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9) ; // it`s number
else if (e.Key == Key.Escape || e.Key == Key.Tab || e.Key == Key.CapsLock || e.Key == Key.LeftShift || e.Key == Key.LeftCtrl ||
e.Key == Key.LWin || e.Key == Key.LeftAlt || e.Key == Key.RightAlt || e.Key == Key.RightCtrl || e.Key == Key.RightShift ||
e.Key == Key.Left || e.Key == Key.Up || e.Key == Key.Down || e.Key == Key.Right || e.Key == Key.Return || e.Key == Key.Delete ||
e.Key == Key.System) ; // it`s a system key (add other key here if you want to allow)
else
e.Handled = true; // the key will sappressed
}
Add a reference to Microsoft.VisualBasic and use the VB IsNumeric function, combined with char.IsLetter().
bit of a cludge but it works :)
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
Regex R = new Regex("^([A-Z]|[0-9]){1}$");
var strKey = new KeyConverter().ConvertToString(e.Key);
if(strKey.Length > 1 )
{
strKey = strKey.Replace("NumPad", "").Replace("D", "");
}
if (strKey.Length == 1)
{
if (!R.IsMatch(strKey))
{
e.Handled = true;
}
}
else
{
e.Handled = true;
}
}
Can you put some code to show what you intend? Shouldn't this work for you
if(e.key.ToString().Length==1)
`Char.IsLetter(e.key.ToString()[0])`
else
//
I'm trying to fire an event perform some work when the user tries to enter only useful data into a form-field using the KeyDown event. But, I keep getting false alarms because the KeyDown event works for just any key!
I'm trying not to make the event fire for buttons such as "Alt, Control, Shift, Esc, the F-keys, etc." What's the best way of doing this?
What I have so far is this:
private void formControl_KeyModified(object sender, KeyEventArgs e)
{
if (e.KeyCode != Keys.Shift && e.KeyCode != Keys.CapsLock && e.KeyCode != Keys.Tab && e.KeyCode != Keys.Escape &&
e.KeyCode != Keys.Insert && e.KeyCode != Keys.Home && e.KeyCode != Keys.End && e.KeyCode != Keys.PageUp &&
e.KeyCode != Keys.PageDown && e.KeyCode != Keys.Up && e.KeyCode != Keys.Down && e.KeyCode != Keys.Left &&
e.KeyCode != Keys.Right && e.KeyCode != Keys.Control && e.KeyCode != Keys.Alt && e.KeyCode != Keys.NumLock &&
e.KeyCode != Keys.Insert && e.KeyCode != Keys.None && e.KeyCode != Keys.PrintScreen && e.KeyCode != Keys.Help &&
e.KeyCode != Keys.ControlKey && e.KeyCode != Keys.ShiftKey && e.KeyCode != Keys.Sleep && e.KeyCode != Keys.LWin &&
e.KeyCode != Keys.RWin && e.KeyCode != Keys.RMenu && e.KeyCode != Keys.LMenu && e.KeyCode != Keys.LShiftKey &&
e.KeyCode != Keys.RShiftKey && e.KeyCode != Keys.Pause && e.KeyCode != Keys.F1 && e.KeyCode != Keys.F2 &&
e.KeyCode != Keys.F3 && e.KeyCode != Keys.F4 && e.KeyCode != Keys.F5 && e.KeyCode != Keys.F6 && e.KeyCode != Keys.F7 &&
e.KeyCode != Keys.F8 && e.KeyCode != Keys.F9 && e.KeyCode != Keys.F10 && e.KeyCode != Keys.F11 && e.KeyCode != Keys.F12 &&
e.KeyCode != Keys.L)
{
// Do some work...
}
}
However, that doesn't quite seem like the best way to handle this to me. Again, I'm just trying to get keys for the characters that could be entered into a textbox (such as 213135udf!##%#!###%15nfaosdf~!#}{:?>, and so on)! Any help at all will be appreciated, thanks!
Sincerely,
Isaac D.
(Edited for clarity and quality)
You could throw all values into a HashSet<T> and check if the KeyCode is in the set.
var invalidKeys = new HashSet<Keys> { Keys.Shift, Keys.CapsLock, Keys.Tab, ... Keys.L };
if (!invalidKeys.Contains(e.KeyCode))
{
// Do some work...
}
Or alternatively, since you're checking for equality, you could just throw all that into a switch statement.
switch (e.KeyCode)
{
case Keys.Shift:
case Keys.CapsLock:
case Keys.Tab:
// ...
case Keys.L:
break;
default:
// Do some work...
break;
}
you can for example (there are many good attempts) check this page for help on the Char class where you can use methods like IsLetterOrDigit or other functions. Now I could not recognise if you are using Windows Forms? If so, use a simple cast like (char)e.KeyCode to get the char.
Example:
private void formControl_KeyModified(object sender, KeyEventArgs e)
{
char c = (char)e.KeyCode;
if (Char.IsLetterOrDigit(c)) {
// useful
}
// might add more checks
// else if (Char.IsPunctuation(c)) ...
}
You can handle the KeyPress event of the form. The mentioned event take a KeyPressEventArgs as its arguments parameter.
Use the Char.IsLetterOrDigit function to check the value of the KeyPressEventArgs.KeyChar property.
private void form_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if (char.IsLetterOrDigit(e.KeyChar)) {}
else { e.Handled = false; }
}
EDIT:
You can also try to make a list of your accepted Char values, then check if the preseed character is included in it:
private void form_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
List<Char> charList = new List<Char>;
charList.AddRange(new Char[] { 'a', 'b' ... });
if (charList.Contains(e.KeyChar)) {}
else { e.Handled = false; }
}
You may need to consider combining both ways or even more to fulfill your requirements.
If you are concerned with the execution time of the if statement, create a SortedList of the Key values and check if the SortedList contains your key.
A possibly better solution is to use the Forms TextBox "TextChanged" event rather than using the KeyDown event.
Like #Daniel states in his comment, perhaps white-listing the valid keys is preferable than black-listing all those that are of no interest to you. So if, let's say, you are interested only in letter keys and numbers, you could do it just like it is described in the msdn Keys example
if(e.KeyCode > Keys.NumPad0 && e.KeyCode < Keys.NumPad9 ||
e.KeyCode > Keys.D0 && e.KeyCode < Keys.D9 ||
e.KeyCode > Keys.A && e.KeyCode < Keys.Z) {
//do useful stuff here
}
On the text box, it should allow the user to enter only six decimal places. For example, 1.012345 or 1,012345.
If seven decimal places are tried, the entry should not be allowed.
Please refer to the below code.
private void textBox1_KeyDown_1(object sender, KeyEventArgs e)
{
bool numericKeys = (
( ((e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) ||
(e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9)) &&
e.Modifiers != Keys.Shift) ||
e.KeyCode == Keys.OemMinus ||
e.KeyCode == Keys.OemPeriod ||
e.KeyCode == Keys.Decimal ||
e.KeyCode == Keys.Oemcomma
);
bool navigationKeys = (
e.KeyCode == Keys.Up ||
e.KeyCode == Keys.Right ||
e.KeyCode == Keys.Down ||
e.KeyCode == Keys.Left ||
e.KeyCode == Keys.Home ||
e.KeyCode == Keys.End ||
e.KeyCode == Keys.Tab);
bool editKeys = (e.KeyCode == Keys.Delete ||
e.KeyCode == Keys.Back);
TextBox aTextbox = (TextBox)sender;
aTextbox.Text = "2,33333";
if (!string.IsNullOrEmpty(aTextbox.Text))
{
double maxIntensity;
string aTextValue = aTextbox.Text;
bool value = double.TryParse(aTextValue,
NumberStyles.Any,
CultureInfo.InvariantCulture.NumberFormat,
out maxIntensity);
if (value)
{
string aText = maxIntensity.ToString();
MessageBox.Show("the value is {0}", aText);
string[] args = aText.Split('.');
if (numericKeys)
{
bool handleText = true;
if (args.Length > 2)
{
handleText = false;
}
else
{
if (args.Length == 2 && args[1] != null && args[1].Length > 5)
{
handleText = false;
}
}
if (!handleText)
{
e.SuppressKeyPress = true;
e.Handled = true;
}
}
}
}
if (!(numericKeys || editKeys || navigationKeys))
{
e.SuppressKeyPress = true;
e.Handled = true;
}
}
To achieve the culture neutrality, the text value is converted to double first and then
the double value is converted to string.
bool value = double.TryParse(aTextValue,
NumberStyles.Any,
CultureInfo.InvariantCulture.NumberFormat,
out maxIntensity);
if (value)
{
string aText = maxIntensity.ToString();
}
Splitting the strings to separate the real part and mantissa part (both are stored are strings), then I check the length of the mantissa part. If the length of the string is more than 5, I'd like to suppress the key.
Is there aother approach to do this?
I've had luck with code similar to the following:
public class RegexMaskedTextBox : TextBox
{
private Regex _regex = new Regex(string.Empty);
public string RegexPattern
{
get { return _regex.ToString(); }
set { _regex = new Regex(value); }
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
string sNewText = this.Text;
string sTextToInsert = e.KeyChar.ToString();
if (this.SelectionLength > 0)
{
sNewText = this.Text.Remove(this.SelectionStart, this.SelectionLength);
}
sNewText = sNewText.Insert(this.SelectionStart, sTextToInsert);
if (sNewText.Length > this.MaxLength)
{
sNewText = sNewText.Substring(0, this.MaxLength);
}
e.Handled = !_regex.IsMatch(sNewText);
base.OnKeyPress(e);
}
}
I think I would solve this by using regular expressions. On the key down event you can check the regex.
Maybe you want to check this out: Regular expression for decimal number
The textbox will only accept numbers and only one decimal point.
For example the textbox contains "12345.56". When the period is pressed a second time on the keyboard it must not appear in the textbox because the textbox already contains a period.
[0-9]+(\.[0-9][0-9]?)?
Go with regular expressions.
hande KeyPress event and assuming its windows
void richTextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == '.' )
{
if (richTextBox1.Text.Contains('.'))
e.Handled = true;
}
}
**//Only numeric with Two decimal place comes in textbox and if user want to enter decimal again or space it will not allowed.**
if ((e.Key >= Key.D0 && e.Key <= Key.D9 ||
e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9 || e.Key == Key.Decimal || e.Key == Key.OemPeriod))
{
string strkey = e.Key.ToString().Substring(e.Key.ToString().Length - 1, e.Key.ToString().Length - (e.Key.ToString().Length - 1));
if (e.Key >= Key.D0 && e.Key <= Key.D9 ||
e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9)
{
TextBox tb = sender as TextBox;
int cursorPosLeft = tb.SelectionStart;
int cursorPosRight = tb.SelectionStart + tb.SelectionLength;
string result1 = tb.Text.Substring(0, cursorPosLeft) + strkey + tb.Text.Substring(cursorPosRight);
string[] parts = result1.Split('.');
if (parts.Length > 1)
{
if (parts[1].Length > 2 || parts.Length > 2)
{
e.Handled = true;
}
}
}
if (((TextBox)sender).Text.Contains(".") && e.Key == Key.Decimal)
{
e.Handled = true;
}
}
else
{
e.Handled = true;
}
if (e.Key >= Key.A && e.Key <= Key.Z ||
e.Key == Key.Space)
{
e.Handled = true;
}
if (Keyboard.Modifiers == ModifierKeys.Shift && e.Key == Key.OemPeriod)
{
e.Handled = true;
}
private bool isValueEnteredExceed100(string textBoxValue, string inputText)
{
var countPeriod = textBoxValue.Count(x => x.ToString().Equals("."));
if (countPeriod <= 1)
{
bool isValidNumber = AreAllValidNumericChars(inputText);
if (isValidNumber == true || inputText == ".")
{
double enterdValue;
bool returnValue = false;
if (textBoxValue != string.Empty || textBoxValue != "")
{
enterdValue = Convert.ToDouble(textBoxValue);
if (enterdValue > 0 && enterdValue <= 100)
{
returnValue = true;
}
}
return returnValue;
}
else
{
return isValidNumber;
}
}
else
{
return false;
}
}
private void AcceptedFromTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
string textBoxValue = AcceptedFromTextBox.Text + e.Text;
if (textBoxValue == ".")
{
textBoxValue = "0" + e.Text;
AcceptedFromTextBox.Text = textBoxValue;
}
e.Handled = !isValueEnteredExceed100(textBoxValue, e.Text);
AcceptedFromTextBox.SelectionStart = AcceptedFromTextBox.Text.Length;
}
private bool AreAllValidNumericChars(string str)
{
Regex regex = new Regex(#"[0-9]$");
return regex.IsMatch(str);
}
Another example ,
private void txtPrice_KeyPress(object sender, KeyPressEventArgs e)
{
if (txtPrice.Text.Length == 0)
{
if (e.KeyChar == '.')
{
e.Handled = true;
}
}
if (!char.IsDigit(e.KeyChar) && e.KeyChar != 8 && e.KeyChar != 46)
{
e.Handled = true;
}
if (e.KeyChar == '.' && txtPrice.Text.IndexOf('.') > -1)
{
e.Handled = true;
}
}
Code on Keypress event of textbox
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && e.KeyChar != '.')
{
e.Handled = true;
}
if (e.KeyChar == '.' && (sender as TextBox).Text.IndexOf('.') > -1)
{
e.Handled = true;
}