需要一个仅限数字的 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 两者

WPF 怎么设置comboBox.text

仅限 MS Windows:需要一种在进程范围内创建私有文件系统的方法

text 仅限一个屏幕

如何以特殊格式输入 textfield.text

更改 SysLink 控件的颜色