限制c#中文本框十进制输入的最佳方法

如何创建一个文本框,其中只能输入类似12.00或1231231.00或123123的数字

我已经做了很长的事情,我正在寻找最好,最快的方式。

小数分隔符也必须是特定于文化的:

Application.CurrentCulture.NumberFormat.NumberDecimalSeparator 

这是一个相当简单的操作。 您需要过滤掉您不想要的密钥,然后执行一些额外的检查。

将以下代码添加到文本框的KeyDown事件:

 private void TextBox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) { switch (e.KeyCode) { case Keys.D0: case Keys.D1: case Keys.D2: case Keys.D3: case Keys.D4: case Keys.D5: case Keys.D6: case Keys.D7: case Keys.D8: case Keys.D9: case Keys.NumPad0: case Keys.NumPad1: case Keys.NumPad2: case Keys.NumPad3: case Keys.NumPad4: case Keys.NumPad5: case Keys.NumPad6: case Keys.NumPad7: case Keys.NumPad8: case Keys.NumPad9: //allow numbers only when no modifiers are active if (e.Control || e.Alt || e.Shift) { //suppress numbers with modifiers e.SuppressKeyPress = true; e.Handled = true; Interaction.Beep(); } break; case (Keys)110: case Keys.OemPeriod: if (!((TextBox)sender).Text.Contains(".")) { //allow period key if there is no '.' //in the text and no modifiers are active if (e.Control || e.Alt || e.Shift) { //suppress numbers with modifiers e.SuppressKeyPress = true; e.Handled = true; Interaction.Beep(); } } else { e.SuppressKeyPress = true; e.Handled = true; Interaction.Beep(); } break; case Keys.Subtract: case Keys.OemMinus: if (((TextBox)sender).SelectionStart == 0 && !((TextBox)sender).Text.Contains("-")) { //allow the negative key only when the cursor //is at the start of the textbox //and there are no minuses in the textbox //and no modifiers are active if (e.Control || e.Alt || e.Shift) { //suppress numbers with modifiers e.SuppressKeyPress = true; e.Handled = true; Interaction.Beep(); } } else { e.SuppressKeyPress = true; e.Handled = true; Interaction.Beep(); } break; case Keys.C: case Keys.X: case Keys.V: case Keys.Z: //allow copy, cut, paste & undo by checking for //the CTRL state. if (e.Control == false) { e.SuppressKeyPress = true; e.Handled = true; Interaction.Beep(); } break; case Keys.Control: case Keys.ControlKey: case Keys.Alt: case Keys.Shift: case Keys.ShiftKey: //allow control, alt & shift break; case Keys.Left: case Keys.Right: case Keys.Up: case Keys.Down: case Keys.PageUp: case Keys.PageDown: case Keys.Home: case Keys.End: //allow navigation keys break; case Keys.Back: case Keys.Delete: //allow backspace & delete break; default: //suppress any other key e.SuppressKeyPress = true; e.Handled = true; Interaction.Beep(); break; } } 

然后,由于用户可以将值粘贴到文本框中,因此将以下内容添加到TextBox的Validate事件中

 private void TextBox1_Validating(object sender, System.ComponentModel.CancelEventArgs e) { //just in case a value was pasted, //we'll need to validate the value if (!Information.IsNumeric(((TextBox)sender).Text)) { e.Cancel = true; } } 

我写了一个类来处理各种filter[显然包括特定于文化的小数符号]。

将此类添加到项目中

 using Microsoft.VisualBasic; using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; public class TextBoxFilter { [Flags()] public enum Filters { None = 0, Text = 1, Numbers = 2, AlphaNumeric = Filters.Text | Filters.Numbers, Currency = 4, All = Filters.Text | Filters.Numbers | Filters.Currency } Dictionary _keyFilter; Dictionary _allowedKeys; Dictionary _invalidKeys; Dictionary keyEventArgs; private static string DecimalMark = Application.CurrentCulture.NumberFormat.NumberDecimalSeparator; private static string NegativeMark = Application.CurrentCulture.NumberFormat.NegativeSign; private static string CurrencySymb = Application.CurrentCulture.NumberFormat.CurrencySymbol; private static string CurrencyDecimal = Application.CurrentCulture.NumberFormat.CurrencyDecimalSeparator; public TextBoxFilter() { _keyFilter = new Dictionary(); _allowedKeys = new Dictionary(); _invalidKeys = new Dictionary(); keyEventArgs = new Dictionary(); } //set & remove filter public void SetTextBoxFilter(TextBox textBox, Filters filter) { SetTextBoxFilter(textBox, filter, AllowedKeys(textBox), InvalidKeys(textBox)); } public void SetTextBoxFilter(TextBox textBox, string allowedKeys) { SetTextBoxFilter(textBox, Strings.Filter(textBox), allowedKeys, InvalidKeys(textBox)); } public void SetTextBoxFilter(TextBox textBox, string allowedKeys, string invalidKeys) { SetTextBoxFilter(textBox, Strings.Filter(textBox), allowedKeys, invalidKeys); } public void SetTextBoxFilter(TextBox textBox, Filters filter, string allowedKeys, string invalidKeys) { if (!_keyFilter.ContainsKey(textBox)) { //add the textbox and its filter if it does not exist in //the collection of registered textboxes _keyFilter.Add(textBox, filter); _allowedKeys.Add(textBox, allowedKeys); _invalidKeys.Add(textBox, invalidKeys); keyEventArgs.Add(textBox, new System.Windows.Forms.KeyEventArgs(Keys.None)); //add the event handlers textBox.KeyDown += KeyDownUp; textBox.KeyUp += KeyDownUp; textBox.KeyPress += KeyPress; textBox.Validating += Validating; textBox.Disposed += Disposed; } else { //change the filter of the textbox if it exists in //the collection of registered textboxes _keyFilter(textBox) = filter; _allowedKeys(textBox) = allowedKeys; _invalidKeys(textBox) = invalidKeys; } } public void RemoveTextBoxFilter(TextBox textBox) { if (_keyFilter.ContainsKey(textBox)) { _keyFilter.Remove(textBox); _allowedKeys.Remove(textBox); _invalidKeys.Remove(textBox); keyEventArgs.Remove(textBox); textBox.KeyDown -= KeyDownUp; textBox.KeyUp -= KeyDownUp; textBox.KeyPress -= KeyPress; textBox.Validating -= Validating; textBox.Disposed -= Disposed; } } public bool ContainsTextBox(TextBox textBox) { return _keyFilter.ContainsKey(textBox); } //properties public Filters Filter { get { if (ContainsTextBox(textBox)) { return _keyFilter.Item[textBox]; } else { return Filters.None; } } set { SetTextBoxFilter(textBox, value); } } public string AllowedKeys { get { if (ContainsTextBox(textBox)) { return _allowedKeys(textBox); } else { return ""; } } set { SetTextBoxFilter(textBox, this.Filter(textBox), value, this.InvalidKeys(textBox)); } } public string InvalidKeys { get { if (ContainsTextBox(textBox)) { return _invalidKeys(textBox); } else { return ""; } } set { SetTextBoxFilter(textBox, this.Filter(textBox), this.AllowedKeys(textBox), value); } } //event handlers private void Disposed(object sender, System.EventArgs e) { RemoveTextBoxFilter((TextBox)sender); } private void KeyDownUp(object sender, System.Windows.Forms.KeyEventArgs e) { //assign the modifiers keyEventArgs((TextBox)sender) = e; } private void KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { //ensure key pressed is in the allowed keys object txt = (TextBox)sender; object c = e.KeyChar; bool allowKey = IsValidChar(txt, c, txt.SelectionStart); //check for backspace & Ctrl combinations if the allowKey is still false if (allowKey == false) { if (keyEventArgs(txt).Control) { //control modifier goes with A, X, C, V and Z for //Select All, Cut, Copy, Paste and Undo respectively object key = keyEventArgs(txt).KeyCode; allowKey = (key == Keys.A || key == Keys.X || key == Keys.C || key == Keys.V || key == Keys.Z); } else if (keyEventArgs(txt).KeyCode == Keys.Back) { //allow the backspace key allowKey = true; } } //disable the key if it was not valid if (!allowKey) { e.Handled = true; Interaction.Beep(); } } private void Validating(object sender, System.ComponentModel.CancelEventArgs e) { object box = (TextBox)sender; object boxFlags = _keyFilter(box); //skip validation if the textbox allows all entries or there is no text if (boxFlags == Filters.All | string.IsNullOrEmpty(box.Text)) return; //otherwise check the characters entered object txtChars = box.Text.ToCharArray; bool isValidEntry = false; //check each caracter for an invalid entry for (i = 0; i <= txtChars.Length - 1; i++) { object c = txtChars(i); isValidEntry = IsValidChar(box, txtChars(i), i); if (!isValidEntry) { box.Select(i, 1); break; // TODO: might not be correct. Was : Exit For } } if (!isValidEntry) e.Cancel = true; if (!isValidEntry) { Interaction.MsgBox("The text entered is invalid for the format " + boxFlags.ToString + "." + !string.IsNullOrEmpty(_allowedKeys(box)) ? Constants.vbCrLf + "Additional Allowed Keys: " + _allowedKeys(box) : "" + !string.IsNullOrEmpty(_invalidKeys(box)) ? Constants.vbCrLf + "Additional Invalid Keys: " + _invalidKeys(box) : "", MsgBoxStyle.Critical, "Invalid Entry"); } } private bool IsValidChar(TextBox textBox, char c, int charIndex) { //ensure key pressed is in the allowed keys object pF = _keyFilter(textBox); object aK = _allowedKeys(textBox); object iK = _invalidKeys(textBox); bool shouldAllow = false; //if filter is set to all, return true unconditionally if (pF == Filters.All) return true; //check preset filters //check for text if (EnumHasFlag(pF, Filters.Text)) { if (!char.IsDigit(c)) { shouldAllow = true; } else { //if the character is a digit, check for the number flag (AlphaNumerics) if (EnumHasFlag(pF, Filters.Numbers)) { shouldAllow = true; } } } //check for nubers if (shouldAllow == false && EnumHasFlag(pF, Filters.Numbers)) { if (char.IsDigit(c)) { shouldAllow = true; } else if (DecimalMark.Contains(c)) { //allow the decimal if there is no decimal in the textbox's //text or the selected text contains the mark if (!textBox.Text.Substring(0, charIndex).Contains(c) || textBox.SelectedText.Contains(c)) { shouldAllow = true; } } else if (NegativeMark.Contains(c) && (charIndex <= NegativeMark.IndexOf(c))) { //allow the negative mark if we are at the start of the //textbox shouldAllow = true; } } //check for currency if (shouldAllow == false && EnumHasFlag(pF, Filters.Currency)) { if (char.IsDigit(c)) { shouldAllow = true; } else if (CurrencyDecimal.Contains(c)) { //allow the currency decimal mark if it does not exist in the //textbox's text or the selected text contains the mark if (!textBox.Text.Substring(0, charIndex).Contains(c) || textBox.SelectedText.Contains(c)) { shouldAllow = true; } } else if (CurrencySymb.Contains(c) && (charIndex <= CurrencySymb.IndexOf(c))) { //allow the currency symbol if we are in a valid position shouldAllow = true; } } //now check for extra allowed keys if (!shouldAllow) { shouldAllow = aK.Contains(c); } //and then check for extra invalid keys if (shouldAllow && iK.Contains(c)) { shouldAllow = false; } return shouldAllow; } [System.Diagnostics.DebuggerStepThrough()] private bool EnumHasFlag(Enum value, Enum flag) { return (Convert.ToInt64(value) & Convert.ToInt64(flag)) == Convert.ToInt64(flag); } } 

然后在表单中使用它,如下所示

 public class Form1 { TextBoxFilter filter = new TextBoxFilter(); private void Form1_Load(object sender, System.EventArgs e) { filter.SetTextBoxFilter(TextBox1, TextBoxFilter.Filters.Numbers); } public Form1() { Load += Form1_Load; } } 

validation事件是为了做到这一点。 删除表单上的ErrorProvider控件,以便巧妙地提醒用户她做错了什么。 该事件还允许您以有意义的方式格式化文本框文本。 像这样:

  private void textBox1_Validating(object sender, CancelEventArgs e) { // Empty strings okay? Up to you. if (textBox1.Text.Length > 0) { decimal value; if (decimal.TryParse(textBox1.Text, out value)) { textBox1.Text = value.ToString("N2"); errorProvider1.SetError(textBox1, ""); } else { e.Cancel = true; textBox1.SelectAll(); errorProvider1.SetError(textBox1, "Please enter a number"); } } } 

尝试使用MaskedTextBox控件。

  private void textBox1_KeyPress(object sender, KeyPressEventArgs e) { if (!Char.IsNumber(e.KeyChar)) { e.Handled = !(((TextBox)sender).SelectionStart != 0 && (e.KeyChar.ToString() == Application.CurrentCulture.NumberFormat.NumberDecimalSeparator && ((TextBox)sender).Text.IndexOf(Application.CurrentCulture.NumberFormat.NumberDecimalSeparator) == -1)); } } 

你应该检查leave for Length == 0我认为……