edit for upper case letter and numbers only

jassie

Well-known member
Joined
Nov 13, 2012
Messages
61
Programming Experience
1-3
In a C# 2010 desktop application, I want a textbox field to contain only letters in upper case. In addition, I want to allow for numbers. Any other values are not valid for this textbox field.

Thus can you show me code on how to setup the edit for uppercase letters and numbers only in the textbox?
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,196
Location
Sydney, Australia
Programming Experience
10+
The upper-case bit is easy. You simply set the CharacterCasing property of the TextBox to Upper. That way you can add text to the TextBox either in code or through the UI as upper- or lower-case and the control will convert it all to upper-case itself.

As for limiting the text to letters and numbers, this is the simplest implementation:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    var keyChar = e.KeyChar;

    e.Handled = !char.IsControl(e.KeyChar) && !char.IsLetterOrDigit(e.KeyChar);
}
That will test each character as the user types and reject all non-control characters that aren't either letters of digits. Control characters include backspace, delete and return, so it's a good ides to always allow them.

The issue with that code is it provides no barrier if the user doesn't type the text. That means that you can display invalid text via code and, more problematic still, is that the user can paste invalid text into the control unfettered. You could set ShortcutsEnabled to False and disallow pasting altogether, but that might also be undesirable.

The answer to the need for a more rigorous implementation is to create a custom control and encapsulate all the logic. For an example of how you might do that, check this out:

Numeric Text Box

That code is in VB but the principles are the same in C#. You could use the SimpleNumberBox as your starting point and adjust it to allow letters and disallow decimals and negatives. Here's the output when converting that code to C# using Instant C# from Tangible Software Solutions:
using System.Globalization;

public class SimpleNumberBox : System.Windows.Forms.TextBox
{
	private const int WM_PASTE = 0x302;

	protected override void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e)
	{
		var keyChar = e.KeyChar;
		var formatInfo = NumberFormatInfo.CurrentInfo;

		if (char.IsControl(keyChar) || char.IsDigit(keyChar) || ((keyChar.ToString() == formatInfo.NegativeSign || keyChar.ToString() == formatInfo.NumberDecimalSeparator) && this.ValidateText(keyChar.ToString())))
		{
			base.OnKeyPress(e);
		}
		else
		{
			e.Handled = true;
		}
	}

	protected override void OnValidated(System.EventArgs e)
	{
		if (!(decimal.TryParse(this.Text, out new decimal())))
		{
			this.Clear();
		}

		base.OnValidated(e);
	}

	protected override void WndProc(ref System.Windows.Forms.Message m)
	{
		if (m.Msg != WM_PASTE || !(Clipboard.ContainsText()) || this.ValidateText(Clipboard.GetText()))
		{
			base.WndProc(ref m);
		}
	}

	private bool ValidateText(string newText)
	{
		var isValid = true;
		var currentText = this.Text;
		var selectionStart = this.SelectionStart;
		var proposedText = currentText.Substring(0, selectionStart) + newText + currentText.Substring(selectionStart + this.SelectionLength);

		if (!(decimal.TryParse(proposedText, NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint, null, out new decimal())))
		{
			var formatInfo = NumberFormatInfo.CurrentInfo;
			var negativeSign = formatInfo.NegativeSign;
			var decimalSeparator = formatInfo.NumberDecimalSeparator;

			isValid = (proposedText == negativeSign) || (proposedText == decimalSeparator) || (proposedText == negativeSign + decimalSeparator);
		}

		return isValid;
	}

}
 
Top Bottom