Allow only alphanumeric in textbox - c#

I have a textbox that should disallow entering any special characters.
The user can enter :
A-Z
a-z
0-9
Space
How can I make the KeyDown event to do this?

Handling the KeyDown or KeyPress events is one way to do this, but programmers usually forget that a user can still copy-and-paste invalid text into the textbox.
A somewhat better way is to handle the TextChanged event, and strip out any offending characters there. This is a bit more complicated, as you have to keep track of the caret position and re-set it to the appropriate spot after changing the box's Text property.
Depending on your application's needs, I would just let the user type in whatever they want, and then flag the textbox (turn the text red or something) when the user tries to submit.

Just wanted to add some code for those ending up here by search:
private void Filter_TextChanged(object sender, EventArgs e)
{
var textboxSender = (TextBox)sender;
var cursorPosition = textboxSender.SelectionStart;
textboxSender.Text = Regex.Replace(textboxSender.Text, "[^0-9a-zA-Z ]", "");
textboxSender.SelectionStart = cursorPosition;
}
This is a change filter, so handles copy and paste, and preserves cursor position so that changing text in the middle works properly.
Note it uses the 'sender' to get the control name, allowing this one function to be linked to multiple textbox boxes, assuming they need the same filter. You can link multiple controls by going to the event section of a control and manually picking the function for the TextChanged event.

Use a regex to filter out the other characters. Or use Char.IsDigit, IsXXX methods to filter out unwanted characters. Lots of ways to do this.
Update: If you must use KeyDown then it seems that you need to also handle KeyPressed and set obEventArgs.Handled = true to disallow the characters. See the example on the KeyDown MSDN Page
Update: Now that you specify it's WPF. The below code will allow only a-z and A-Z characters to be entered into the textbox. Extend as needed...
private void _txtPath_KeyDown(object sender, KeyEventArgs e)
{
if ((e.Key < Key.A) || (e.Key > Key.Z))
e.Handled = true;
}
This will break if you copy-paste stuff into the text-box. Validate the entire text once the user leaves the control or when he clicks OK/Submit as MusicGenesis says.

private void _txtPath_KeyDown(object sender, KeyEventArgs e)
{
if ((e.Key < Key.A) || (e.Key > Key.Z))
e.Handled = true;
}

I think it's worth considering doing the filtering on the TextBox's TextChanged event. You can create an operation that gets rid of any non-valid characters from your text string. This is a bit more messy than blocking the KeyDown event.
But, I think this is the way to go because you are not blocking WPF's built-in KeyDown/Up event handling mechanisms, so copy/paste still works. You would be working at a higher level of abstractions so I think it will be easier to figure out what is going on.

I ran into this in silverlight and wrote something like this.
private string _filterRegexPattern = "[^a-zA-Z0-9]"; // This would be "[^a-z0-9 ]" for this question.
private int _stringMaxLength = 24;
private void _inputTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (!string.IsNullOrEmpty(_filterRegexPattern))
{
var text = _inputTextBox.Text;
var newText = Regex.Replace(_inputTextBox.Text, _filterRegexPattern, "");
if (newText.Length > _stringMaxLength)
{
newText = newText.Substring(0, _stringMaxLength);
}
if (text.Length != newText.Length)
{
var selectionStart = _inputTextBox.SelectionStart - (text.Length - newText.Length);
_inputTextBox.Text = newText;
_inputTextBox.SelectionStart = selectionStart;
}
}
}

I accomplish this with a custom Dependency Property. It's reusable for any TextBox control, is much faster and more efficient to use than building key events, and makes my code files much cleaner.
In addition, it can handle other input methods which does not trigger key events, such as pasting a value into the TextBox using the mouse.
The code for the custom DP looks like this:
// When set to a Regex, the TextBox will only accept characters that match the RegEx
/// <summary>
/// Lets you enter a RegexPattern of what characters are allowed as input in a TextBox
/// </summary>
public static readonly DependencyProperty AllowedCharactersRegexProperty =
DependencyProperty.RegisterAttached("AllowedCharactersRegex",
typeof(string), typeof(TextBoxProperties),
new UIPropertyMetadata(null, AllowedCharactersRegexChanged));
// Get
public static string GetAllowedCharactersRegex(DependencyObject obj)
{
return (string)obj.GetValue(AllowedCharactersRegexProperty);
}
// Set
public static void SetAllowedCharactersRegex(DependencyObject obj, string value)
{
obj.SetValue(AllowedCharactersRegexProperty, value);
}
// Events
public static void AllowedCharactersRegexChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var tb = obj as TextBox;
if (tb != null)
{
if (e.NewValue != null)
{
tb.PreviewTextInput += Textbox_PreviewTextChanged;
DataObject.AddPastingHandler(tb, TextBox_OnPaste);
}
else
{
tb.PreviewTextInput -= Textbox_PreviewTextChanged;
DataObject.RemovePastingHandler(tb, TextBox_OnPaste);
}
}
}
public static void TextBox_OnPaste(object sender, DataObjectPastingEventArgs e)
{
var tb = sender as TextBox;
bool isText = e.SourceDataObject.GetDataPresent(DataFormats.Text, true);
if (!isText) return;
var newText = e.SourceDataObject.GetData(DataFormats.Text) as string;
string re = GetAllowedCharactersRegex(tb);
re = string.Format("[^{0}]", re);
if (Regex.IsMatch(newText.Trim(), re, RegexOptions.IgnoreCase))
{
e.CancelCommand();
}
}
public static void Textbox_PreviewTextChanged(object sender, TextCompositionEventArgs e)
{
var tb = sender as TextBox;
if (tb != null)
{
string re = GetAllowedCharactersRegex(tb);
re = string.Format("[^{0}]", re);
if (Regex.IsMatch(e.Text, re, RegexOptions.IgnoreCase))
{
e.Handled = true;
}
}
}
And it's used like this:
<TextBox Text="{Binding SomeValue, UpdateSourceTrigger=PropertyChanged}"
local:TextBoxHelpers.AllowedCharactersRegex="a-zA-Z0-9\s" />

I know that winForms have available a MaskedTextBox control, which lets you specify exactly this sort of thing. I don't know WPF, so I dunno if that's available there, but if it is, do that. Its MUCH easier than all this stuff with keypresses and events, and more robust too.

The easiest way to do this would be to included the Extended WPF Toolkit which has a control for doing exactly what you are asking for by specifying a mask.
http://wpftoolkit.codeplex.com/wikipage?title=MaskedTextBox&referringTitle=Home
It will also display the mask in the text box as you are inputting if required.
(It also has many other useful controls)

and your regExp could look like [0-9a-zA-Z]* to allow only English alphanumeric chracters

only alphanumeric TextBox WPF C#,
sorry for my english.. but with this code for WPF, c#, I only permit alphanumeric
private void txtTraslado_TextChanged(object sender, KeyEventArgs e)
{
if (((e.Key < Key.NumPad0)||(e.Key > Key.NumPad9))&&((e.Key < Key.A)||(e.Key > Key.Z)))
{
e.Handled = true;
}
}

Use Asp.NET AJAX Control Toolkit
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>
And Use FilteredTextBoxExtender
<asp:TextBox ID="txt_gpf_no" runat="server" CssClass="textbox"
MaxLength="10"></asp:TextBox>
<asp:FilteredTextBoxExtender ID="FilteredTextBoxExtender_gpf_no" runat="server" Enabled="True"
TargetControlID="txt_gpf_no" FilterType="UppercaseLetters,LowercaseLetters,Custom" ValidChars="1234567890 ">
</asp:FilteredTextBoxExtender>

in my.Net Framework 4.5 C# application
private void txtRF_Register_Val_KeyDown(object sender, KeyEventArgs e)
{
//only enable alphanumeric
if (!(((e.KeyCode < Keys.NumPad0) || (e.KeyCode > Keys.NumPad9)) && ((e.KeyCode < Keys.A) || (e.KeyCode > Keys.E))))
{
e.SuppressKeyPress = false;
}
else
{
e.SuppressKeyPress = true;
}
}

Related

How can I make a TextBox accepts only numeric values in WinUI 3?

I have a TextBox which I use in Settings page of my app. Now, this textbox should only accept/display digits. There are several examples and solutions for this problem however, none of them work for WinUI 3 as they are mostly from 5-10 years ago.
KeyPress event does not exists in WinUI 3 TextBox. While looking for alternatives I saw KeyDown event however this event arguments are different and KeyRoutedEventArgs do not contain any property like KeyChar.
The example code I found that's applicable for WPF applications:
private void txtbox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
}
}
How can I achieve this behaviour in WinUI 3 TextBox?
You can use InputScope!
You can find a reference from the Microsoft docs.
Here's an example from Microsoft:
<TextBox Header="Telephone Number" InputScope="TelephoneNumber"/>
You can also do further verifications in the code-behind by listening to the TextChanged event:
<TextBox TextChanged="OnTextChanged" />
<!-- In your code-behind file -->
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
// Get the current text of the TextBox
var text = ((TextBox)sender).Text;
// Use a regular expression to only allow numeric values
var regex = new Regex("^[0-9]*$");
// If the text does not match the regular expression, undo the change
if (!regex.IsMatch(text))
{
((TextBox)sender).Undo();
}
}
Edit:
In WinUI 3, you can use KeyDown event too.
It's very similar to the way you did in WPF:
<TextBox KeyDown="OnKeyDown" />
private void OnKeyDown(object sender, KeyRoutedEventArgs e)
{
// Check if the key pressed is a numeric key
if (!((e.Key >= VirtualKey.Number0 && e.Key <= VirtualKey.Number9) || (e.Key >= VirtualKey.NumberPad0 && e.Key <= VirtualKey.NumberPad9)))
{
// If the key is not numeric, cancel the event and prevent the key from being entered
e.Handled = true;
}
}
#Link Hylia's answer was somehow correct in achieving the behaviour requested. I expanded on that answered by:
Changed the event used. The KeyDown or TextChanged events were asynchronous events and would not block the entered input to appear on the screen. I changed this to TextChanging event which is run synchronously and before the TextBox.Text is rendered. Using this method, I can control the text before its rendered and improve UX.
Instead of undoing, I now do just remove the char entered from the text and pass it back to the TextBox.
I put the cursor back to where it was before so that the user can continue typing from where they left.
The code can be found below:
private void textBox1_TextChanging(TextBox sender, TextBoxTextChangingEventArgs args)
{
var currentPosition = textBox1.SelectionStart - 1;
var text = ((TextBox)sender).Text;
var regex = new Regex("^[0-9]*$");
if(!regex.IsMatch(text))
{
var foundChar = Regex.Match(textBox1.Text, #"[^0-9]");
if(foundChar.Success)
{
textBox1.Text = textBox1.Text.Remove(foundChar.Index, 1);
}
textBox1.Select(currentPosition, 0);
}
}

How can I remove a character from a C#.net WPF textbox before it's shown?

I have a project in C#.net using a WPF textbox that validates a character like * as the first character entered. If this character is entered, the rest of the text is good but I cannot show nor use the character. How can I remove the character from the string early enough to not show it? I've attempted using the KeyDown event but while the event is active, there is no data to remove. And if I use the KeyUp event the data is shown for a second. I've previously used a KeyPress event in VB6 to achieve this which worked because the value was simultaneously in the code but not in the textbox. As far as I can tell a WPF textbox does not have this event. What can I do?
Code:
private void UserInput_KeyUp(object sender, KeyEventArgs e)
{
//get ascii value from keyboard input
int Ascii = (int)e.Key;
//get char value to know what to remove as a string
char CharAscii = (char)Ascii;
If(Ascii == InputPrefix)
{
PrefixValidated = true;
UserInput.Text = UserInput.Text.Replace(CharAscii.ToString(), string.Empty);
}
}
The same code is in the KeyDown event and I've tried it using one or the other and both.
it may be a bit of a rough solution but you could use a PreviewTextInupt event I belive.
private bool PrefixValidated = false;
private string CheckUserInput;
private void TextBox1_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
CheckUserInput = CheckUserInput + e.Text;
if (CheckUserInput.ElementAt(0).ToString() == "*" && e.Text != "*")
{
e.Handled = false;
}
else if (CheckUserInput.ElementAt(0).ToString() == "*")
{
PrefixValidated = true;
e.Handled = true;
}
else
{
e.Handled = true;
}
}
Thanks to Dark Templar for helping with the discovery of this solution. Using PreviewTextInput and validating the character only if there are no other characters in the textbox seems to give the correct result.
Setting e.Handled = true stops the character from actually entering the textbox even for a second so the user is never aware of the prefix.
Code:
private void UserInput_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
//if this is the first character entered, the textbox is not yet populated
//only perform validation if the character is a prefix
if (UserInput.Text != "")
return;
char CharAscii = (char)ScannerPrefix;
if (e.Text == CharAscii.ToString())
{
PrefixValidated = true;
e.Handled = true;
}
}

Format textbox with numbers only

I have a textbox that accepts only numbers, no other characters. And I created the following function in the keypress method for that:
private void txtRGIE_KeyPress(object sender, KeyPressEventArgs e)
{
if (!Char.IsDigit(e.KeyChar) && e.KeyChar != (char)8)
{
e.Handled = true;
}
}
Validation is working when I type, I can't type special characters or letters like I wanted. However, if I copy a numeric string that contains dots or other characters and paste it into the field, it accepts normally. For example, if you copy: 323.323 / 323 and paste into the field, it will accept. How do I validate the characters I paste, allowing only numbers?
I have a textbox that accepts only numbers
And that's the flaw; saying "I have a knife here that i'm trying to use as a screwdriver, but i keep cutting myself with it, so i filed it smooth, but it's too big to get into the screw hole, so I filed it small, but it doesn't turn a + shaped screw very well, and the tip isn't hardened so it keeps breaking.."
The answer is to use a + shaped screwdriver, rather than keep repeatedly trying to kludge something not made for the job, into something that will do the job
A NumericUpDown control is the right tool for this job; it accepts only numbers, has configurable decimal places, and upper and lower limits, cannot have alphameric text typed or pasted into it and, bonus, the user can use the Up and Down cursor keys to change the value
NUD is a drop in replacement for your textbox, it's free and it's part of the standard lib so there isn't anything to install - just remember to get the .Value, not the .Text, and that it's a decimal, so you might want to cast it to something else to use it (double? int?) depending on what your app expects
If you don't like the little up down buttons, see here
you can use :
private void txtRGIE_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) &&
(e.KeyChar != '.'))
{
e.Handled = true;
}
// only allow one decimal point
if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1))
{
e.Handled = true;
}
}
or you can use a NumericUpDown instead
refer to this answers so you understand more.
You could use a MaskedTextBox instead of a regular one.
As already mentioned a NumericUpDown control is a good choice and to make it appear like a TextBox you can hide the up/down arrows e.g.
amountNumericUpDown1.Controls[0].Hide();
Or create a custom version with no up/down arrows and in this case no beep when pressing enter key.
public class SpecialNumericUpDown : NumericUpDown
{
public SpecialNumericUpDown()
{
Controls[0].Hide();
TextAlign = HorizontalAlignment.Right;
}
protected override void OnTextBoxResize(object source, EventArgs e)
{
Controls[1].Width = Width - 4;
}
public delegate void TriggerDelegate();
public event TriggerDelegate TriggerEvent;
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == (Keys.Return))
{
e.Handled = true;
e.SuppressKeyPress = true;
TriggerEvent?.Invoke();
return;
}
base.OnKeyDown(e);
}
}

how to add dots automatically while writing in TextBox

I have one TextBox with binding on DateTime type. I need to get a dot after first 2 chars and second 2 chars, for example: 12.12.1990.
I'm using behavior in TextChanged event, that code:
void tb_TextChanged(object sender, TextChangedEventArgs e)
{
int i = tb.SelectionStart;
if (i == 2 || i == 5)
{
tb.Text += ".";
tb.SelectionStart = i + 1;
}
}
That is working, but if I want to delete text by backspace, obviously I can't delete dots, because event is called again.
What is better way to solve it?
Solved
It works
But if you can, you may fix my algorithm.
public string oldText = "";
public string currText = "";
private void TextBox1_TextChanged(object sender, TextChangedEventArgs e)
{
oldText = currText;
currText = TextBox1.Text;
if (oldText.Length > currText.Length)
{
oldText = currText;
return;
}
if (TextBox1.Text.Length == currText.Length)
{
if (TextBox1.SelectionStart == 2 || TextBox1.SelectionStart == 5)
{
TextBox1.Text += ".";
TextBox1.SelectionStart = TextBox1.Text.Length;
}
}
}
I would do it in the KeyPress event, so you can filter by what kind of key it was (using the KeyChar argument with Char.IsLetter() and similar functions).
Also, add the dot when the next key is pressed. If the user has typed "12", don't add a dot yet. When the user presses 1 to add the second "12", add it then (before the new character).
Use String Format in the xaml control like so
StringFormat='{}{0:dd.MM.yyyy}'
I just tested it and this will even convert slashes to the dots.
For example
<TextBox.Text>
<Binding Path="Person.DateOfBirth" UpdateSourceTrigger="LostFocus" StringFormat='{}{0:dd.MM.yyyy}'></Binding>
</TextBox.Text>
If you are using a datepicker then you will need to override its textbox template as in the link below with the String Format above.
This link may help if if you are trying to apply it to a datepicker.
I recommend you to use a DateTimePicker and change its Format property to Short. Another option is to change your TextBox to a MaskedTextBox and changing its Mask property to ShortDate (00/00/0000) .DateTimePicker allows you not to do much about validating datetime values. But if you use a MaskedTextBox you should validate it. Sample link shows how to do validation.
I have modified above code
private void txt_in1_TextChanged(object sender, TextChangedEventArgs e)
{
int i = txt_in1.SelectionStart;
if (bsp1 != 1)
{
if (i == 2)
{
txt_in1.Text += ":";
txt_in1.SelectionStart = i + 1;
}
}
}
private void txt_in1_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Back)
{
bsp1 = 1;
}
else
{
bsp1 = 0;
}
}
I have taken another event which is keyup (equivalent keypress event), In that whenever backspace is detected it will flag bsp1 variable, which intern stop the text change event to put ":". here "bsp1" is define as global variable. (Code is for wpf, c#).

How to validate array of text boxes

I am using c# winform.
I have 2dimensional array of text boxes I want them to accept only Letters from A-I I've created the method but that works for only one text box.
Here is my code:
textbox[i,j].Validated+=new EventHandler(TextBox_KeyPress);
private void TextBox_KeyPress(object sender, EventArgs e)
{
bool bTest = txtRegExStringIsValid(textbox[1,1].Text.ToString());
ToolTip tip = new ToolTip();
if (bTest == false)
{
tip.Show("Only A-I", textbox[1,1], 2000);
textbox[1,1].Text = " ";
}
}
private bool txtRegExStringIsValid(string textToValidate)
{
Regex TheRegExpression;
string TheTextToValidate;
string TheRegExTest = #"^[A-I ]+$";
TheTextToValidate = textToValidate;
TheRegExpression = new Regex(TheRegExTest);
if (TheRegExpression.IsMatch(TheTextToValidate))
{
return true;
}
else
{
return false;
}
}
Can anyone please guide what should I do make this code work for all text boxes?
if this works for textbox[1,1] you could register your private void TextBox_KeyPress(object sender, EventArgs e) as eventhandler for all your textboxes and instead of textbox[1,1] you could use ((TextBox)sender)
i want text boxes to accept only letters from a-i actually i am trying to make sudoku
There's a much simpler solution than regular expressions, and you don't even need to handle the Validated event to implement it.
In a situation like this, where there are only certain characters that you want to prevent the user from entering, handling the KeyDown event is a much better solution. The user gets immediate feedback that the letter they tried to enter was not accepted. The alternative (the Validating and Validated events) actually wait until the user tries to leave the textbox to rudely alert them that their input was invalid. Especially for a game, this tends to break concentration and isn't particularly user-friendly.
Doing it this way also makes it irrelevant which individual textbox raised the event. Instead, you will handle it the same way for all of the textboxes—by completely ignoring all invalid input.
Here's what I'd do:
First, attach a handler method to your textbox's KeyDown event. You can do this from the Properties window in the designer, or you can do it through code, as you have in the question:
textbox[i,j].KeyDown += TextBox_KeyDown;
Then, you need to put the logic into your event handler method that determines if the key that the user just pressed is in the allowed range (A through I), or outside of it:
private void TextBox_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
// Determine if the keystroke was a letter between A and I
if (e.KeyCode < Keys.A || e.KeyCode > Keys.I)
{
// But allow through the backspace key,
// so they can correct their mistakes!
if (e.KeyCode != Keys.Back)
{
// Now we've caught them! An invalid key was pressed.
// Handle it by beeping at the user, and ignoring the key event.
System.Media.SystemSounds.Beep.Play();
e.SuppressKeyPress = true;
}
}
}
If you want to restrict the user to typing in only one letter, you can add code to handle that in the above method, or you can take an even simpler route and let the textbox control handle it for you automatically. To do that, set the MaxLength property of the textbox to true, either in the designer or through code:
textbox[i,j].MaxLength = true;
Check the text of the sender instead of whatever textbox[1,1] is.
Use the sender parameter of the event handler to identify the textbox responsible for the event.
The first thing that will help you is casting the sender of your event to a TextBox like this:
(Also, as Cody Gray said, this is a TextBox_Validated event, not a KeyPress event so I've renamed it appropriately)
private void TextBox_Validated(object sender, EventArgs e)
{
TextBox tb = sender as TextBox()
if (sender == null)
return;
bool bTest = txtRegExStringIsValid(tb.Text.ToString());
ToolTip tip = new ToolTip();
if (bTest == false) {
tip.Show("Only A-I", tb, 2000);
tb .ext = " ";
}
Next you need to actually get into that code for every textbox. There are two obvious approaches to that, you can either assign the eventhandler to each textbox in the array or you can use a custom textbox which always does this validation and then add that to your array.
Assign eventhandler to textboxes
foreach(var tb in textbox)
{
tb.Validated += new EventHandler(TextBox_KeyPress);
}
Create custom textbox control
Create the custom text box control (Add a user control to the project) and then just use it exactly as you would a normal textbox.
public partial class ValidatingTextBox: TextBox
{
public ValidatingTextBox()
{
InitializeComponent();
}
protected override void OnValidating(CancelEventArgs e)
{
bool bTest = txtRegExStringIsValid(this.Text.ToString());
ToolTip tip = new ToolTip();
if (bTest == false)
{
tip.Show("Only A-I", this, 2000);
this.Text = " ";
}
}
private bool txtRegExStringIsValid(string textToValidate)
{
// Exactly the same validation logic as in the same method on the form
}
}

Categories

Resources