需要一个仅限数字的 Windows 控件 TextBox [重复]
Posted
技术标签:
【中文标题】需要一个仅限数字的 Windows 控件 TextBox [重复]【英文标题】:Need a numeric only windows control TextBox [duplicate] 【发布时间】:2011-04-22 23:21:15 【问题描述】:我正在使用 System.Windows.Controls.TextBox 在 c# 中创建一个老式对话框。 有没有一种简单的方法可以将此框中的文本输入限制为仅限数字?
谢谢!
【问题讨论】:
谢谢大家。但我想强调的是,这不是一个 Windows 窗体控件。它是一个老式的 System.Windows.Controls 控件。所以,很多这些解决方案都行不通。 【参考方案1】:还要考虑您的设计是否需要在输入/粘贴时限制用户输入,或者当用户离开文本框时是否可以简单地将用户输入转换为数字。
通常限制性方法更难执行(处理逗号、句点、货币符号、空格等......可能会很痛苦)
然后这个方法就变得很简单了:
private void textBox1_Leave(object sender, EventArgs e)
textBox1.Text = VerifyNumeric(textBox1.Text);
private string VerifyNumeric(string text)
double value = 0;
double.TryParse(text, out value);
return value.ToString(); // could format here too.
【讨论】:
【参考方案2】:这是my answer to an earlier question的摘录。
将此类添加到您的项目中
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<TextBox, Filters> _keyFilter;
Dictionary<TextBox, string> _allowedKeys;
Dictionary<TextBox, string> _invalidKeys;
Dictionary<TextBox, Windows.Forms.KeyEventArgs> 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<TextBox, Filters>();
_allowedKeys = new Dictionary<TextBox, string>();
_invalidKeys = new Dictionary<TextBox, string>();
keyEventArgs = new Dictionary<TextBox, KeyEventArgs>();
//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;
【讨论】:
【参考方案3】:您可以考虑使用MaskedTextBox,相应地设置Mask 属性。
【讨论】:
【参考方案4】:只需实现 onkeyup 事件处理程序,如果按下的键不是 Character.IsDigit 则清除它。
http://msdn.microsoft.com/en-us/library/system.windows.controls.textbox.onkeyup(VS.95).aspx
【讨论】:
+1,考虑是否需要允许其他符号,如逗号/句点或破折号(负号) 不确定在这种情况下是否会过大,但您还需要停止粘贴非数字文本。以上是关于需要一个仅限数字的 Windows 控件 TextBox [重复]的主要内容,如果未能解决你的问题,请参考以下文章
输入数字验证 - 仅限输入数字或数字,int & float 两者