2010-06-26 88 views
3

我怎樣才能使一個文本框,在其中可以只輸入了一個數字,如12.00或1231231.00或123123最佳方式

我在很遠的路這樣做,我尋找最好,最快的方式。

而且小數點分隔符必須是特定的文化:

Application.CurrentCulture.NumberFormat.NumberDecimalSeparator 

回答

2

這是一個相當簡單的操作。您需要過濾不想出來的密鑰,然後執行一些額外的檢查。

下面的代碼添加到文本框的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的驗證事件

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

我還不知道處理文化特定小數運算符的方法。我會盡力爲你找到一個。 – 2010-07-23 11:12:22

+0

它是這樣的:Application.CurrentCulture.NumberFormat.NumberDecimalSeparator – 2010-07-23 16:37:50

+0

最新的添加處理文化特定的小數符號,負數和貨幣。 – 2010-07-24 11:36:56

0

嘗試MaskedTextBox控制。

+0

它不會幫助使用它在您形式。由於它具有固定寬度的輸入。 – 2010-06-26 21:28:39

7

驗證事件是爲了做到這一點。在窗體上放置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"); 
      } 
     } 
    } 
0
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的長度== 0我想......

+0

右鍵單擊並粘貼怎麼辦? – 2010-07-22 18:13:22

+1

就我個人而言,我會去掉TextChange,Leave或Validate事件中的所有非數字和額外的分隔符 - 取決於您何時需要它。從框架內部(據我所知)沒有辦法在粘貼事件發生之前趕上粘貼事件。 – riffnl 2010-07-22 18:30:17