Within our application, there is a usercontrol, which allows to enter a number (inside a numericupdown) followed by a combobox which allows to select the SI-Prefix ([p, n, µ, m, -, k, M, G, T] small to big)
Now, for easier usage, I thought it would be nice to capture the KeyPress-Event on the numericUpDown and set the combobox accordingly. (If m is pressed, select mili (m), if G is pressed, select Giga (G))
This works flawless with the following handler / selector:
private void numericUpDown1_KeyPress(object sender, KeyPressEventArgs e)
{
if (char.IsLetter(e.KeyChar))
{
//Check, if its valid for si prefixes.
if (this.siSelector1.TrySelect(e.KeyChar)
{
e.Handled = true;
}
}
}
Where TrySelect does nothing but the following:
public Boolean TrySelect(Char chr)
{
var entry = this.comboBox_siPrefix.Items.Cast<KeyValuePair<String,Double>>().Where(e => e.Key.Contains("(" + chr + ")")).FirstOrDefault();
if (!entry.Equals(new KeyValuePair<String, Double>()))
{
this.comboBox_siPrefix.SelectedItem = entry;
return true;
}
return false;
}
That's fine, but everytime the user hears a "BING" whenever a non-numeric Key is pressed on the numericupdown.
I read about e.SuppressKeyPress, which unfortunately isn't available with KeyPressEventArgs - it's only available for KeyEventArgs.
So, trying the whole thing with the KeyDown-Event works. (No "BING") - but I wasn't able to capture capital keys, as every KeyDown will fire the Event immediately...
private void numericUpDown1_KeyDown(object sender, KeyEventArgs e)
{
KeysConverter kc = new KeysConverter();
if (char.IsLetter(kc.ConvertToString(e.KeyCode)[0]))
{
//Check, if its valid for si prefixes.
if (this.siSelector1.TrySelect(kc.ConvertToString(e.KeyCode)[0]))
{
e.Handled = true;
e.SuppressKeyPress = true;
}
}
}
Any Ideas?
Figured out a way:
When Using KeyDown-Event, you can use e.Modifiers to check, if another key is down'd at the same time.
I dunno why, but for the KeyDown-Event e.KeyValue as well as e.KeyCode always return the CAPITAL version of the key.
So, I modified the handler to convert every char to lower-case, and only convert it to upper-Case if SHIFT is pressed at the same time:
Works - no "BING" (for valid SI-Prefixes). :-)
private void numericUpDown1_KeyDown(object sender, KeyEventArgs e)
{
KeysConverter kc = new KeysConverter();
char c = char.ToLower(kc.ConvertToString(e.KeyValue)[0]);
if (char.IsLetter(c))
{
//Caps?
if (e.Modifiers == Keys.Shift)
{
c = char.ToUpper(c);
}
//Check, if its valid for si prefixes.
if (this.siSelector1.TrySelect(c))
{
e.Handled = true;
e.SuppressKeyPress = true;
}
}
}
The above solution does not apply for µ (CTRL+ALT+m or ALT GR+m)
Update: This is not 100%, but I didn't get it by now:
IF the ALT-Key is pressed, The Char-Code always reports a "M".
Update 2:
So, I had to exclude the "m" from beeing matched with char.isLetter() (if alt is pressed) and finally add another check.
I found, that comparing e.KeyValue==77 worked as expected, while comparing c=='m' didn't... (then µ was inserted into the numericupdown, which it shouldn't)
if (ctrl && alt && c=='m'):
if (ctrl && alt && e.KeyValue==77)
Dunno why - Ideas?
private void numericUpDown1_KeyDown(object sender, KeyEventArgs e)
{
KeysConverter kc = new KeysConverter();
char c = char.ToLower(kc.ConvertToString(e.KeyValue)[0]);
Boolean ctrl = e.Control;
Boolean alt = e.Alt;
Boolean shift = e.Shift;
int keyPadStart = (int)Keys.NumPad0;
int keyPadEnd = (int)Keys.NumPad9;
if (e.KeyValue >= keyPadStart && e.KeyValue <= keyPadEnd)
{
//send to numeric updown.
return;
}
if (char.IsLetter(c) && !alt)
{
if (shift) c = char.ToUpper(c);
//Check, if its valid for si prefixes.
if (this.siSelector1.TrySelect(c))
{
e.Handled = true;
e.SuppressKeyPress = true;
}
}
//not working: if (ctrl && alt && c=='m')
if (ctrl && alt && e.KeyValue==77)
{
//Check, if its valid for si prefixes.
if (this.siSelector1.TrySelect('µ'))
{
e.Handled = true;
e.SuppressKeyPress = true;
}
}
}
Related
Why when i click for example "a" on my keyboard program seems bad key "F8".
Diffrent examples:
"1" = "NumPad7"
"A" = "V"
"B" = "W"
Problem is in:
label.Content = (Key)key;
When i change (Key) for (char) it works but only for a-z and A-Z keys. How can i properly detect my keyboard?
public void Window_KeyDown(object sender, KeyEventArgs e)
{
if (condition == true)
{
int key;
int keyState;
for (key = 0; key < 127; key++)
{
keyState = GetAsyncKeyState(key);
if (keyState == 1 || keyState == -32767)
{
if(Keyboard.IsKeyDown(Key.LeftShift) ||
Keyboard.IsKeyDown(Key.RightShift ))
{
Save_With_Big_Letters(key);
label.Content = (Key)key;
}
else
{
Save_With_Small_Letters(key);
label.Content = (Key)(key + 32);
}
}
}
}
}
GetAsyncKeyState uses the older, WindowsForms key values. To make this work, either use System.Windows.Forms.Keys enum, or just use the KeyEventArgs.Key value.
Like this:
label.Content = (System.Windows.Forms.Keys)key;
or the better way:
label.Content = e.Key;
How to prohibit the introduction of letters in textBox? That is, this construction works incorrectly
public void textBox1_KeyDown(object sender, KeyEventArgs e)
{
try
{
char s = Convert.ToChar(textBox1.Text);
if ((s <= '0') || (s >= '9'))
MessageBox.Show("You have entered a symbol! Please enter a number");
}
catch (System.FormatException)
{
MessageBox.Show("You have entered a symbol! Please enter a number");
}
}
You need to either check the key being entered in the KeyDown event (e.Key property) as the key value is added to the Text field after the event or use the TextChanged event - this would catch cut & paste operations as well.
public void textBox1_TextChanged(object sender, TextChangedEventArgs e)
{
if (!ValidNumericString(textBox1.Text))
{
MessageBox.Show("You have entered invalid characters! Please enter a number");
Dispatcher.BeginInvoke(new Action(() => textBox1.Undo()));
e.Handled = true;
}
}
public bool ValidNumericString(string IPString)
{
return IPString.All(char.IsDigit);
// OR make this check for thousands & decimals if required
}
You can use the OnKeyPress event which allows you to cancel the key event manually if you want to.
void textBox1_OnKeyPress(KeyPressEventArgs e)
{
e.Handled = true; // this won't send the key event to the textbox
}
If you want to accept only numbers and related chars (negative sign, decimal separators, ...), you can test the entered char :
void textBox1_OnKeyPress(KeyPressEventArgs e)
{
NumberFormatInfo numberFormatInfo = CultureInfo.CurrentCulture.NumberFormat;
string decimalSeparator = numberFormatInfo.NumberDecimalSeparator;
string groupSeparator = numberFormatInfo.NumberGroupSeparator;
string negativeSign = numberFormatInfo.NegativeSign;
string keyInput = e.KeyChar.ToString();
e.Handled = !(Char.IsDigit(e.KeyChar) || keyInput.Equals(negativeSign) || keyInput.Equals(decimalSeparator) || keyInput.Equals(groupSeparator));
}
This is untested code because I'm at work, but you get the idea.
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (Control.ModifierKeys == Keys.Control) return; // Check if ctrl is pressed
var key = (char) e.KeyValue; // ASCII to char
if (char.IsDigit(key) || char.IsControl(key) || char.IsWhiteSpace(key)) return; // Check if "key" is a number
MessageBox.Show("You have entered a symbol! Please enter a number");
textBox1.Text = textBox1.Text.Substring(0, textBox1.Text.Length - 1); // Remove last element
textBox1.SelectionStart = textBox1.Text.Length; // Return to initial position
}
I am trying to read Current value of Text Box in PreviewKeyDown Event but unable to get current value.
Here is my code ,
private void txtDoscountValue_PreviewKeyDown(object sender, KeyEventArgs e)
{
try
{
if (txtDoscountValue.Text == string.Empty)
discountPercentage = 0;
else
discountPercentage = float.Parse(txtDoscountValue.Text);
CalculateCart(cartItems, discountPercentage, 0);
}
catch
{ }
}
Maybe your problem is that you are asking at PreviewKeyDown, so when it gets called, there is still no values in the box. If you want to get called when the box actually changes you need to hook to KeyDown or even better TextChanged.
PreviewKeyDown is for checking the content of the change before actually applying it, which is kind of validation.
The value of the modification is stored in the keyEventArgs, not in the textbox.
It is possible to read value of TextBox at any time with Text property of TextBox control:
var currentValue=textBox.Text;
To read inputted keys of keyboard, you can use e.Key of KeyEventArgs:
private void txtDoscountValue_PreviewKeyDown(object sender, KeyEventArgs e)
{
try
{
string input=e.Key;
var ee = txtDoscountValue.Text;
}
catch { }
}
Update:
It is possible to use KeyConverter class to convert Keys to string. You should add reference to assembly System.Windows.Forms to your WPF project to use KeyConverter class:
private void textBox1_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
try
{
char c = '\0';
System.Windows.Input.Key key = e.Key;
if ((key >= Key.A) && (key <= Key.Z))
{
c = (char)((int)'a' + (int)(key - Key.A));
}
else if ((key >= Key.D0) && (key <= Key.D9))
{
c = (char)((int)'0' + (int)(key - Key.D0));
}
else if ((key >= Key.NumPad0) && (key <= Key.NumPad9))
{
c = (char)((int)'0' + (int)(key - Key.NumPad0));
}
//here your logic
}
catch { }
}
}
I want to make a TextBox which does not allow to enter a value above 100. Only numbers allowed, And a Numeric TextBox is not an option. This is my code for now:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar)) { e.Handled = true; } // only numbers
}
Any ideas?
You should use int.TryParse to see if the parsing is successful and then compare the value to see if it is below 100.
int number;
if(int.TryParse(textBox1.Text, out number))
{
if(number <= 100)
{
//in range
}
else
{
// not in range
}
}
else
{
//invalid number
}
You can also use double.TryParse or other TryParse method depending on the type, they are safe to use, since they will return a false if the parsing fails, instead of raising an exception.
Hello, here is my solution.
private void textBox_KeyPress(object sender, KeyPressEventArgs e)
{
char c = e.KeyChar;
if ((!char.IsDigit(c) ||
Convert.ToInt32(textBox.Text + e.KeyChar) >= 101 ||
textBox.Text == "0") && c != '\b')
e.Handled = true;
}
Finally. I found a solution:
int box_int = 0; Int32.TryParse(textBox1.Text, out box_int);
if (box_int > 1050 && textBox1.Text != "") { textBox1.Text = "1050"; }
You can enter only numbers and use arrows keys and backspace. If you enter a number > than 100 or less than 1, when you press enter it will be cancelled. Copy and Past with button key down is disabled and also mouse right click to prevent the user to paste in the text box is disabled/handled. This should solve your problem in full.
First of all set:
ShortcutsEnabled property of your text box to False
this will not allow mouse right click and ctrl+V for paste in your text box.
Then add the following code:
//prevent letters, special chars, punctuation, symbols, white spaces
private void txtType1_KeyPress(object sender, KeyPressEventArgs e)
{
{
if (char.IsLetter(e.KeyChar) ||
char.IsSymbol(e.KeyChar) ||
char.IsWhiteSpace(e.KeyChar) ||
char.IsPunctuation(e.KeyChar))
e.Handled = true;
}
{
//allows only numbers between 1 and 100
string value = txtType1.Text;
if (txtType1.Text !="")
{
if (Int16.Parse(value) < 1 )
{
txtType1.Text = "";
}
else if (Int16.Parse(value) > 100)
{
txtType1.Text = "";
}
}
}
}
I created a textbox dynamically with a TextChangedEventArgs to restrict the textbox to enter only numbers and decimal point.
Following is the code in c#
const char Delete = (char)8;
if (Char.IsDigit(e.KeyChar))
{
e.Handled = false;
}
else if (e.KeyChar == Delete)
{
e.Handled = false;
}
else if (e.KeyChar == '.')
{
if (!(amt.Text.Contains(".")))
e.Handled = false;
else
{
e.Handled = true;
}
}
else
{
e.Handled = true;
}
But I can't use this in wpf.
I tried to change the code with e.key or e.Text. But both these are not available. It is showing the following error Are u missing an assembly or directive.
Please anyone help me.
// one solution for filtering characters in a textbox.
// this is the PreviewKeyDown handler for a textbox named tbNumerical
// Need to add logic for cancelling repeated decimal point and minus sign
// or possible notation like 1.23e2 == 123
private void tbNumerical_PreviewKeyDown(object sender, KeyEventArgs e)
{
System.Windows.Input.Key k = e.Key;
// to see the key enums displayed, use a textbox or label
// someTextBox.Text = k.ToString();
// filter out control keys, not all are used, add more as needed
bool controlKeyIsDown = Keyboard.IsKeyDown(Key.LeftShift);
if (!controlKeyIsDown &&
Key.D0 <= k && k <= Key.D9 ||
Key.NumPad0 <= k && k <= Key.NumPad9 ||
k == Key.OemMinus || k == Key.Subtract ||
k == Key.Decimal || k == Key.OemPeriod) // or OemComma for european decimal point
else
{
e.Handled = true;
// just a little sound effect for wrong key pressed
System.Media.SystemSound ss = System.Media.SystemSounds.Beep;
ss.Play();
}
}