【问题标题】:Best way to limit textbox decimal input in c#在c#中限制文本框十进制输入的最佳方法
【发布时间】:2011-03-08 17:11:09
【问题描述】:

如何制作一个只能输入 12.00 或 1231231.00 或 123123 等数字的文本框

我已经做了很长时间,我正在寻找最好和最快的方法。

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

Application.CurrentCulture.NumberFormat.NumberDecimalSeparator

【问题讨论】:

    标签: c# vb.net winforms c#-3.0 c#-4.0


    【解决方案1】:

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

    在文本框的 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;
        }
    }
    

    我编写了一个类来为您处理各种过滤器 [其中显然包括特定于文化的十进制符号]。

    将此类添加到您的项目中

    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;
        }
    }
    

    【讨论】:

    • 我还不知道任何处理特定文化的十进制运算符的方法。我会尽快为您找到一个。
    • 这里是:Application.CurrentCulture.NumberFormat.NumberDecimalSeparator
    • 最新添加处理特定文化的十进制符号、负数和货币。
    • 我忘了补充一点,我将此代码从 vb.net 移植到 c#,因此您可以随时请求原始 vb.net 源代码。
    【解决方案2】:
        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));
            }
        }
    

    你应该检查 onLeave 的 Length == 0 我认为...

    【讨论】:

    • 就我个人而言,我会在 TextChange、Leave 或 Validate 事件中删除所有非数字和额外的分隔符 - 取决于您何时需要。在框架内(据我所知)无法在粘贴事件发生之前捕获它。
    【解决方案3】:

    验证事件就是为了做到这一点。在您的表单上放置一个 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");
                }
            }
        }
    

    【讨论】:

      【解决方案4】:

      试试MaskedTextBox 控件。

      【讨论】:

      • 它没有帮助。因为它有一个固定宽度的输入。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-21
      相关资源
      最近更新 更多