How to define what character is generated using KeyRoutedEventArgs? - c#

I want to validate the information entered in a text box - I am going to allow only Cyrillic characters. To do that, I am using the following regular expression:
#"[\u0400-\u04FF]{1}"
and binding a function to the KeyDown event of the text box. Note, that the expressions is working perfectly.
Here is the code:
private void txtBoxName_KeyDown(object sender, KeyRoutedEventArgs e)
{
Debug.WriteLine(e.Key.ToString());
Debug.WriteLine(Regex.IsMatch(e.Key.ToString(), #"[\u0400-\u04FF]{1}"));
if (e.Key == Windows.System.VirtualKey.Back || Regex.IsMatch(e.Key.ToString(), #"[\u0400-\u04FF]{1}"))
{
//return true;
}
else
{
e.Handled = true;
}
}
The issue is I am not able to correctly identify what is the real character generated. For example:
Gives me(this is the code generated by the debug statements) and not Я:
Shift 'MST_61462004_E1T04.exe' (CoreCLR: .): Loaded
'C:\windows\system32\System.Runtime.WindowsRuntime.NI.DLL'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
False
S
False
And I believe this is why the validation is not working.

Accoring to MSDN KeyRoutedEventArgs.Key does not necessarily represent mapped Unicode character of the pressed key:
Depending on the input device, this can be a mapped value. For raw,
unmapped event data, see the OriginalKey property.
In your case (Keyboard Device), it just represents virtual keys and there is a mapping process that TextBox does internally to convert the virtual key to zero or more unicode characters. In Win32, it could be done by MapVirtualKey function but there is nothing similar to it in WinRT.
You have a few choices:
Validating on TextChanged event of the TextBox instead (I prefer this one)
Using a very simple mapping tightly coupled to the expected keyboard layout as described here
Implementing a full version of MapVirtualKey (It takes lots of effort)

The Key property of the KeyRoutedEventArgs returns the mapped event value. Use KeyRoutedEventArgs.OriginalKey to get unmapped value.
Depending on the input device, the input button might be mapped to a different key value.
Also, you do not have to use the {1} quantifier, it is redundant, as the character class [\u0400-\u04FF] is capturing exactly 1 character. Or, to shorten it, you can use a Unicode category class \p{IsCyrillic}.
So, use
if (e.Key == Windows.System.VirtualKey.Back ||
Regex.IsMatch(e.OriginalKey.ToString(), #"[\u0400-\u04FF]"))
{
//return true;
}

Related

Convert Text to Uppercase while typing in Text box

I am new in Visual Studio and using visual Studio 2008.
In a project I want to make all text in uppercase while typed by the user without pressing shift key or caps lock on.
I have used this code
TextBox1.Text = TextBox1.Text.ToUpper();
but it capitalize characters after pressing Enter key.
I just want that characters appear in uppercase while typing by the user without pressing shift key or without caps lock on.
Total page code is as...
public partial class Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void TextBox1_TextChanged(object sender, EventArgs e)
{
TextBox1.Text = TextBox1.Text.ToUpper();
}
}
Have any one any solution, please guide me.
There is a specific property for this. It is called CharacterCasing and you could set it to Upper
TextBox1.CharacterCasing = CharacterCasing.Upper;
In ASP.NET you could try to add this to your textbox style
style="text-transform:uppercase;"
You could find an example here: http://www.w3schools.com/cssref/pr_text_text-transform.asp
Edit (for ASP.NET)
After you edited your question it's cler you're using ASP.NET. Things are pretty different there (because in that case a roundtrip to server is pretty discouraged). You can do same things with JavaScript (but to handle globalization with toUpperCase() may be a pain) or you can use CSS classes (relying on browsers implementation). Simply declare this CSS rule:
.upper-case
{
text-transform: uppercase
}
And add upper-case class to your text-box:
<asp:TextBox ID="TextBox1" CssClass="upper-case" runat="server"/>
General (Old) Answer
but it capitalize characters after pressing Enter key.
It depends where you put that code. If you put it in, for example, TextChanged event it'll make upper case as you type.
You have a property that do exactly what you need: CharacterCasing:
TextBox1.CharacterCasing = CharacterCasing.Upper;
It works more or less but it doesn't handle locales very well. For example in German language ß is SS when converted in upper case (Institut für Deutsche Sprache) and this property doesn't handle that.
You may mimic CharacterCasing property adding this code in KeyPress event handler:
e.KeyChar = Char.ToUpper(e.KeyChar);
Unfortunately .NET framework doesn't handle this properly and upper case of sharp s character is returned unchanged. An upper case version of ß exists and it's ẞ and it may create some confusion, for example a word containing "ss" and another word containing "ß" can't be distinguished if you convert in upper case using "SS"). Don't forget that:
However, in 2010 the use of the capital sharp s became mandatory in official documentation when writing geographical names in all-caps.
There isn't much you can do unless you add proper code for support this (and others) subtle bugs in .NET localization. Best advice I can give you is to use a custom dictionary per each culture you need to support.
Finally don't forget that this transformation may be confusing for your users: in Turkey, for example, there are two different versions of i upper case letter.
If text processing is important in your application you can solve many issues using specialized DLLs for each locale you support like Word Processors do.
What I usually do is to do not use standard .NET functions for strings when I have to deal with culture specific issues (I keep them only for text in invariant culture). I create a Unicode class with static methods for everything I need (character counting, conversions, comparison) and many specialized derived classes for each supported language. At run-time that static methods will user current thread culture name to pick proper implementation from a dictionary and to delegate work to that. A skeleton may be something like this:
abstract class Unicode
{
public static string ToUpper(string text)
{
return GetConcreteClass().ToUpperCore(text);
}
protected virtual string ToUpperCore(string text)
{
// Default implementation, overridden in derived classes if needed
return text.ToUpper();
}
private Dictionary<string, Unicode> _implementations;
private Unicode GetConcreteClass()
{
string cultureName = Thread.Current.CurrentCulture.Name;
// Check if concrete class has been loaded and put in dictionary
...
return _implementations[cultureName];
}
}
I'll then have an implementation specific for German language:
sealed class German : Unicode
{
protected override string ToUpperCore(string text)
{
// Very naive implementation, just to provide an example
return text.ToUpper().Replace("ß", "ẞ");
}
}
True implementation may be pretty more complicate (not all OSes supports upper case ẞ) but take as a proof of concept. See also this post for other details about Unicode issues on .NET.
if you can use LinqToObjects in your Project
private YourTextBox_TextChanged ( object sender, EventArgs e)
{
return YourTextBox.Text.Where(c=> c.ToUpper());
}
An if you can't use LINQ (e.g. your project's target FW is .NET Framework 2.0) then
private YourTextBox_TextChanged ( object sender, EventArgs e)
{
YourTextBox.Text = YourTextBox.Text.ToUpper();
}
Why Text_Changed Event ?
There are few user input events in framework..
1-) OnKeyPressed fires (starts to work) when user presses to a key from keyboard after the key pressed and released
2-) OnKeyDown fires when user presses to a key from keyboard during key presses
3-) OnKeyUp fires when user presses to a key from keyboard and key start to release (user take up his finger from key)
As you see, All three are about keyboard event..So what about if the user copy and paste some data to the textbox?
if you use one of these keyboard events then your code work when and only user uses keyboard..in example if user uses a screen keyboard with mouse click or copy paste the data your code which implemented in keyboard events never fires (never start to work)
so, and Fortunately there is another option to work around : The Text Changed event..
Text Changed event don't care where the data comes from..Even can be a copy-paste, a touchscreen tap (like phones or tablets), a virtual keyboard, a screen keyboard with mouse-clicks (some bank operations use this to much more security, or may be your user would be a disabled person who can't press to a standard keyboard) or a code-injection ;) ..
No Matter !
Text Changed event just care about is there any changes with it's responsibility component area ( here, Your TextBox's Text area) or not..
If there is any change occurs, then your code which implemented under Text changed event works..
**/*Css Class*/**
.upCase
{
text-transform: uppercase;
}
<asp:TextBox ID="TextBox1" runat="server" Text="abc" Cssclass="upCase"></asp:TextBox>
I use to do this thing (Code Behind) ASP.NET using VB.NET:
1) Turn AutoPostBack = True in properties of said Textbox
2) Code for Textbox (Event : TextChanged)
Me.TextBox1.Text = Me.TextBox1.Text.ToUpper
3) Observation
After entering the string variables in TextBox1, when user leaves TextBox1,
AutoPostBack fires the code when Text was changed during "TextChanged" event.
I had the same problem with Visual Studio 2008 and solved adding the following event handler to the textbox:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if ((e.KeyChar >= 'a') && (e.KeyChar <= 'z'))
{
int iPos = textBox1.SelectionStart;
int iLen = textBox1.SelectionLength;
textBox1.Text = textBox1.Text.Remove(iPos, iLen).Insert(iPos, Char.ToUpper(e.KeyChar).ToString());
textBox1.SelectionStart = iPos + 1;
e.Handled = true;
}
}
It works even if you type a lowercase character in a textbox where some characters are selected.
I don't know if the code works with a Multiline textbox.
set your CssClass property in textbox1 to "cupper", then in page content create new css class :
<style type="text/css">.cupper {text-transform:uppercase;}</style>
Then, enjoy it ...

Trap NULL key in WPF application

I am using a barcode scanner and we were looking for a way to determine if input was from a keyboard or the scanner. The input will be used in a WPF POS application. We thought we had come up with a good method by using the scanners ability to prefix reads with custom characters. The first character ideally would be non printable so we chose NULL or '\0'. We used the following code to register an event handler
EventManager.RegisterClassHandler(typeof(System.Windows.Controls.Control), System.Windows.Controls.Control.KeyUpEvent, new RoutedEventHandler(KeyUpEvent));
internal static void KeyUpEvent (object sender, RoutedEventArgs e)
{
KeyEventArgs keyEvent = e as KeyEventArgs;
if (keyEvent != null)
{
keyEvent.Key.ToString();
}
}
This however seems to not get the first NULL character and instead moves to the next char which is the length of the data.
I have also tested with a console app and just done a Console.ReadKey(). This returns me the null char as the first thing read so I know the scanner is definitely sending the correct data.
So is there any way in WPF to obtain all the data read?
Edit:
I tried using TextCompositionEventHandler but to no avail, i still only get the printable characters coming through.
KeyEventArgs.Key is not a character, it's an enum indicating which key was pressed. There is no NULL keyboard key so there is no point trying to check for the ASCII NULL (0x00) character. Moreover, most non-printable characters have no equivalent key and require the user to use a combination of keys to type them.
If you want to detect scanner codes using prefixes, try chekcing the UIElement.TextInput TextBoxBase.TextChanged events.
A better idea may be to use the scanner's SDK (if available) to send data directly to your application. More expensive models usually have an SDK to communicate with applications directly instead of emulating the keyboard.
I might be wrong, but I don't think NULL and \0 is the same in this context. Have a look at this post. They suggest using TextInput instead of KeyUp.
How to get KeyChar in WPF application

Windows Forms - customizing MaskedTextBox

I need to use basic functionality of the MaskedTextBox. I can get use of the 5 digit mask but there are few things that I want to change. Right now the box is looking like this:
and there are two thing I don't like. First - the Prompt char which is undersoce _. I deleted the field value in order to leave it empty (as I would like it to appear) but this gives an error - The property value is invalid. So is there a way to get rid of these underscores? And second - I use this value for one of my entity properties which is of integer type so I make a convertion :
if (txtNumOfAreas.Text != "")
{
string temp = txtNumOfAreas.Text;
bool result = Int32.TryParse(temp, out convertValue);
if (result)
{
entity.AreasCnt = convertValue;
}
else
{
MessageBox.Show(Resources.ERROR_SAVE, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
else
{
entity.AreasCnt = null;
}
which works fine unless someone decides to make experiments and insert something like _1__5_ then the conversion fails, but at first place I would like to make possible to write the digits only one after another. So is this possible too?
It looks like your MaskedEdit is more trouble than it's worth to deal with your particular range of issues. A better control to use might be the NumericUpDown.
The upside to NumericUpDown:
There are no underscore prompts to try and get rid of
It will only accept numeric input
So there is no need to try and convert the value. You will always have an integer
Setting Minimum and Maximum value properties gives you automatic data entry validation
Provides multiple modes of data entry:
Typing
Clicking up/down buttons with a mouse
Up/down with keyboard
If you like, you could hide the up/down buttons altogether: C# WinForms numericUpDown control (removing the spin box)
So to get the _ to be a space you just need to set the mask character to a single space. And to resolve the conversion error, just set the AllowPromptAsInput property to false so that the user can't actually end up with something like your example.

Text box only digits

I know this question is asked but I have another problem in my code:
(e.Key >= Windows.System.VirtualKey.Number0) &&
(e.Key <= Windows.System.VirtualKey.Number9)
It works but when I type Shift+6 it types & the code wont work when shift press but after 6 is pressed it works and types as &.
How can I disable this? I am thinking a global variable that keeps the previous key and if it's shift don't type but it also keeps shift neither shift is pressed with a number key at the same time or shift is preesed before number key.
Why don't you TryParse the incomming text and see if it's int rather then verifying the key.
If you wish to keep the current implementation then also check for Modifier keys to avoid cases like Shift+6.
You may as well check for special keys like Shift: Keyboard.Modifiers == ModifierKeys.Shift.
http://msdn.microsoft.com/en-us/library/system.windows.input.modifierkeys.aspx
better use a Regex to check if user inputed a number, as user also can paste a value which also can be valid.
Use "^\d+$" if you need to match more than one digit.
Note that "\d" will match [0-9] and other digit characters like the Eastern Arabic numerals ٠١٢٣٤٥٦٧٨٩. Use "^[0-9]+$" to restrict matches to just the Arabic numerals 0 - 9.
You should check keep in private member your valid value from textbox and every time text box value is changed, you must check if value is valid, if valid, then private member = textbox.value, else textbox.value = private member, in that case you user won't be able to input not valid value
You shoud use PreviewTextInput.it raises before any other textchanged or any other key event, if you set
e.Handled to True that means that all upcoming events have been handeled including (Textchanged,...), so they'll be canceled.
if
e.Handeled false so everything continues Normaly
Next you try to parse the e.text (which is the new textbox value) to an int if its true (the text is an int) e.handeled=False so the textchanged,.. continue, otherwise e.Handeled=True sothing happens
NOTE
on the preview event the textbox didn't changed yet, so you retrieve its value from e.Text
TextBox mytextblock= new TextBox();
mytextblock.PreviewTextInput += mytextblock_PreviewTextInput;
inside
void mytextblock_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
int val;
e.Handled = !int.TryParse(e.Text, out val);
};

When data is entered into a cell of a DataGridView can I modify their entry before cell validation?

Consider a data entry form where the user needs to enter times in military format. They wish to key from a keypad to speed up their work but don't want to key the colon (:) between the hours/minutes.
The column is formatted to allow time and will automatically convert the time to the standard AM/PM formats. Unfortunately, it requires the colon. Therefore a conversion method should be run on this input to attempt to convert it to a time value.
The method to do this is not part of the answer I'm looking for. It could represent any reason why someone would want to change a value keyed by a user into some other value. The key is that it needs to happen before validation so the DataError event is not raised.
I assumed that CellValidating would be the right place for this so I wrote what I expected to work:
private void sampleDataGridView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
// Ensure we're looking at the column that requires our attention
if (sampleDataGridView.Columns[e.ColumnIndex].Name == "timeCol")
sampleDataGridView[e.ColumnIndex, e.RowIndex].Value = convertMilitary(e.FormattedValue);
}
When stepping into this code after the cell is written to, the event args tell me that the formatted value is indeed what was keyed, but attempting to set this to the current value of the cell doesn't help validation. On closer inspection I learned that the value is still what it was prior to user entry.
This leaves me at an impasse because I don't see where else I would put this. I feel that I'm in the right spot but I'm missing something. Where do I put this conversion so the DataError event isn't raised from a failed validation?
Its possible that there is a different property I need to set? Its like I should be changing what the user keyed, not the cell value directly like I am attempting to do...
Have you looked at using the CellParsing event? I seem to recall using this when I needed to do something similar.

Categories

Resources