Làm cách nào để tạo một hộp văn bản chỉ chấp nhận số?


583

Tôi có một ứng dụng biểu mẫu windows với điều khiển hộp văn bản mà tôi muốn chỉ chấp nhận các giá trị nguyên. Trước đây, tôi đã thực hiện loại xác thực này bằng cách quá tải sự kiện KeyPress và chỉ xóa các ký tự không phù hợp với đặc điểm kỹ thuật. Tôi đã xem xét điều khiển MaskedTextBox nhưng tôi muốn một giải pháp tổng quát hơn có thể hoạt động với một biểu thức thông thường hoặc phụ thuộc vào các giá trị của các điều khiển khác.

Lý tưởng là điều này sẽ hành xử sao cho việc nhấn một ký tự không phải là số sẽ không tạo ra kết quả hoặc ngay lập tức cung cấp cho người dùng phản hồi về ký tự không hợp lệ.


11
số hay chữ số? sự khác biệt lớn: thậm chí số nguyên có thể trở nên tiêu cực
Joel Coehoorn

8
Câu hỏi được dành cho các số bao gồm toàn bộ các số hữu tỷ.
Mykroft

Câu trả lời:


797

Hai lựa chọn:

  1. Sử dụng NumericUpDownthay thế. NumericUpDown thực hiện việc lọc cho bạn, điều này thật tuyệt. Tất nhiên nó cũng cung cấp cho người dùng của bạn khả năng nhấn các mũi tên lên và xuống trên bàn phím để tăng và giảm giá trị hiện tại.

  2. Xử lý các sự kiện bàn phím thích hợp để ngăn chặn mọi thứ trừ đầu vào số. Tôi đã thành công với hai trình xử lý sự kiện này trên TextBox tiêu chuẩn:

    private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) &&
            (e.KeyChar != '.'))
        {
                e.Handled = true;
        }
    
        // only allow one decimal point
        if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1))
        {
            e.Handled = true;
        }
    }

Bạn có thể xóa kiểm tra cho '.'(và kiểm tra tiếp theo cho nhiều hơn một '.') nếu TextBox của bạn không cho phép vị trí thập phân. Bạn cũng có thể thêm một kiểm tra cho'-' TextBox của bạn có cho phép các giá trị âm hay không.

Nếu bạn muốn giới hạn người dùng về số chữ số, hãy sử dụng: textBox1.MaxLength = 2; // this will allow the user to enter only 2 digits


5
Hạn chế duy nhất với NumericUpDown là nó không cung cấp phản hồi khi bạn nhập một giá trị bên ngoài các giá trị Tối đa hoặc Tối thiểu được phép - nó chỉ thay đổi những gì bạn đã nhập. Một TextBox ít nhất có thể cho phép các giá trị không hợp lệ để bạn có thể cảnh báo người dùng khi họ gửi biểu mẫu.
Matt Hamilton

7
Điều đó đúng - người dùng luôn có thể dán vào một số ký tự không phải là số. Tuy nhiên, bạn sẽ hy vọng rằng việc xác thực mẫu sẽ nắm bắt được điều đó, vì tại một số điểm bạn sẽ muốn thực hiện Int32.TryPude hoặc một cái gì đó.
Matt Hamilton

52
Bạn sẽ cần một số nỗ lực bổ sung để toàn cầu hóa điều này bằng cách thay thế kiểm tra cho '.' với các kiểm tra trên CultureInfo.CiverseCARM.NumberFormat.NumberDecimalSpayator.
Jeff Yates

6
@ HamishGrubijan, IsControl không liên quan gì đến phím Control; nó trả về dù char có phải là char điều khiển hay không. Bằng cách cho phép ký tự điều khiển, bạn không phá vỡ những thứ như backspace, xóa hoặc các phím mũi tên
Thomas Levesque

13
Điều này vẫn chấp nhận đầu vào ctrl + v bất hợp pháp; một lỗi thậm chí tồn tại trong điều khiển NumericUpDown chính thức.
Nyerguds

149

Và chỉ vì sẽ vui hơn khi làm mọi thứ trong một dòng ...

 private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar);
    }

LƯU Ý: Điều này KHÔNG ngăn người dùng Sao chép / Dán vào hộp văn bản này. Đây không phải là một cách an toàn để vệ sinh dữ liệu của bạn.


đây không phải là một giải pháp chung vì nó chỉ hoạt động cho các intergers. Tôi đã phải thực hiện điều đó gần đây và tôi đã kết thúc với chuỗi kết quả phân tích thử thành số và chỉ cho phép nhập nếu phân tích thành công
grzegorz_p

1
Điều này có thể không hoạt động khi nhiều phương thức xử lý KeyPresscác sự kiện từ cùng một hộp văn bản. Một sự kiện có thể được đặt e.Handledthành đúng và sau đó một sự kiện khác có thể đặt lại thành sai. Nói chung, tốt hơn là sử dụngif (...) e.Handled = true;
Nathaniel Jones

2
Bạn có thể vô hiệu hóa thuộc tính Phím tắt để ngăn chặn sao chép bằng bàn phím hoặc menu
Ahmad

3
HAHA! Đúng! Một lót!
Jamie L.

3
Hở. Một TextChangedsự kiện vượt qua nó với biểu thức chính quy có thể khắc phục sao chép-dán;)
Nyerguds

51

Tôi giả sử từ ngữ cảnh và các thẻ bạn đã sử dụng rằng bạn đang viết ứng dụng .NET C #. Trong trường hợp này, bạn có thể đăng ký sự kiện thay đổi văn bản và xác thực từng hành trình phím.

private void textBox1_TextChanged(object sender, EventArgs e)
{
    if (System.Text.RegularExpressions.Regex.IsMatch(textBox1.Text, "[^0-9]"))
    {
        MessageBox.Show("Please enter only numbers.");
        textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);
    }
}

22
Chẳng phải điều đó sẽ mang lại hiệu ứng rất kỳ lạ nếu bạn gõ vào giữa một con số sao?
Colin Pickard

5
và cũng nên là:textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);
Pieniadz

3
Điều gì xảy ra nếu bản thân ký tự đầu tiên không phải là một chữ số ... sẽ không trừ đi 1 trong trường hợp đó gây ra lỗi ....
manu_dilip_shah

6
Ngoài ra, việc sử dụng TextChanged thay vì KeyPress sẽ tạo ra một chút đệ quy trong đó mã sẽ nhảy vào một sự kiện TextChanged thứ hai sau phương thức Remove.
WEFX

2
Bạn đã chuyển các tham số đầu vào và mẫu cho chức năng IsMatch của mình. Đầu vào nên là đầu tiên, sau đó là mẫu. msdn.microsoft.com/en-us/l
Library / sdx2bds0 (v = vs.110) .aspx

36

Dưới đây là một điều khiển tùy chỉnh Winforms độc lập đơn giản, xuất phát từ TextBox tiêu chuẩn, chỉ cho phép nhập liệu System.Int32 (có thể dễ dàng điều chỉnh cho các loại khác như System.Int64, v.v.). Nó hỗ trợ các hoạt động sao chép / dán và số âm:

public class Int32TextBox : TextBox
{
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        base.OnKeyPress(e);

        NumberFormatInfo fi = CultureInfo.CurrentCulture.NumberFormat;

        string c = e.KeyChar.ToString();
        if (char.IsDigit(c, 0))
            return;

        if ((SelectionStart == 0) && (c.Equals(fi.NegativeSign)))
            return;

        // copy/paste
        if ((((int)e.KeyChar == 22) || ((int)e.KeyChar == 3))
            && ((ModifierKeys & Keys.Control) == Keys.Control))
            return;

        if (e.KeyChar == '\b')
            return;

        e.Handled = true;
    }

    protected override void WndProc(ref System.Windows.Forms.Message m)
    {
        const int WM_PASTE = 0x0302;
        if (m.Msg == WM_PASTE)
        {
            string text = Clipboard.GetText();
            if (string.IsNullOrEmpty(text))
                return;

            if ((text.IndexOf('+') >= 0) && (SelectionStart != 0))
                return;

            int i;
            if (!int.TryParse(text, out i)) // change this for other integer types
                return;

            if ((i < 0) && (SelectionStart != 0))
                return;
        }
        base.WndProc(ref m);
    }

Cập nhật 2017 : Câu trả lời đầu tiên của tôi có một số vấn đề:

  • bạn có thể nhập nội dung nào đó dài hơn số nguyên của một loại nhất định (ví dụ: 2147483648 lớn hơn Int32.MaxValue);
  • tổng quát hơn, không có xác nhận thực sự về kết quả của những gì đã được gõ;
  • nó chỉ xử lý int32, bạn sẽ phải viết điều khiển dẫn xuất TextBox cụ thể cho từng loại (Int64, v.v.)

Vì vậy, tôi đã đưa ra một phiên bản khác chung chung hơn, vẫn hỗ trợ sao chép / dán, + và - ký, v.v.

public class ValidatingTextBox : TextBox
{
    private string _validText;
    private int _selectionStart;
    private int _selectionEnd;
    private bool _dontProcessMessages;

    public event EventHandler<TextValidatingEventArgs> TextValidating;

    protected virtual void OnTextValidating(object sender, TextValidatingEventArgs e) => TextValidating?.Invoke(sender, e);

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (_dontProcessMessages)
            return;

        const int WM_KEYDOWN = 0x100;
        const int WM_ENTERIDLE = 0x121;
        const int VK_DELETE = 0x2e;

        bool delete = m.Msg == WM_KEYDOWN && (int)m.WParam == VK_DELETE;
        if ((m.Msg == WM_KEYDOWN && !delete) || m.Msg == WM_ENTERIDLE)
        {
            DontProcessMessage(() =>
            {
                _validText = Text;
                _selectionStart = SelectionStart;
                _selectionEnd = SelectionLength;
            });
        }

        const int WM_CHAR = 0x102;
        const int WM_PASTE = 0x302;
        if (m.Msg == WM_CHAR || m.Msg == WM_PASTE || delete)
        {
            string newText = null;
            DontProcessMessage(() =>
            {
                newText = Text;
            });

            var e = new TextValidatingEventArgs(newText);
            OnTextValidating(this, e);
            if (e.Cancel)
            {
                DontProcessMessage(() =>
                {
                    Text = _validText;
                    SelectionStart = _selectionStart;
                    SelectionLength = _selectionEnd;
                });
            }
        }
    }

    private void DontProcessMessage(Action action)
    {
        _dontProcessMessages = true;
        try
        {
            action();
        }
        finally
        {
            _dontProcessMessages = false;
        }
    }
}

public class TextValidatingEventArgs : CancelEventArgs
{
    public TextValidatingEventArgs(string newText) => NewText = newText;
    public string NewText { get; }
}

Đối với Int32, bạn có thể xuất phát từ nó, như thế này:

public class Int32TextBox : ValidatingTextBox
{
    protected override void OnTextValidating(object sender, TextValidatingEventArgs e)
    {
        e.Cancel = !int.TryParse(e.NewText, out int i);
    }
}

hoặc dẫn xuất w / o, sử dụng sự kiện TextValidating mới như thế này:

var vtb = new ValidatingTextBox();
...
vtb.TextValidating += (sender, e) => e.Cancel = !int.TryParse(e.NewText, out int i);

nhưng điều tuyệt vời là nó hoạt động với bất kỳ chuỗi nào và bất kỳ thói quen xác nhận nào.


Điều này là tuyệt vời, tốt đẹp và đơn giản, dễ sử dụng và xử lý các nỗ lực đầu vào bất thường. Cảm ơn!
WiredEarp

1
Lưu ý trên phiên bản 2017, khi có một giá trị, ví dụ 1 và bạn nhấn backspace, nó sẽ bị bỏ qua trong khi nếu bạn nói 120 và nhấn backspace ba lần thì chúng ta còn lại 1.
Karen Payne

1
Hộp thư xác thực của bạn cho đến nay là cách triển khai tốt nhất tôi từng thấy trong một thời gian. Đơn giản và hiệu quả. Cảm ơn!
Samuel

19

Đây chính xác là những gì các sự kiện Xác thực / Xác thực được thiết kế cho.

Đây là bài viết MSDN về chủ đề: http://msdn.microsoft.com/en-us/l Library / system.windows.forms.control.validating.aspx

Phiên bản TL; DR: kiểm tra thuộc tính .Text trong sự kiện Xác thực và đặt e.Cancel=Truekhi dữ liệu không hợp lệ.

Khi bạn đặt e.Cattery = True, người dùng không thể rời khỏi trường, nhưng bạn sẽ cần cung cấp cho họ một số loại phản hồi rằng có gì đó không đúng. Tôi thay đổi màu nền của hộp thành màu đỏ nhạt để biểu thị một vấn đề. Đảm bảo đặt lại thành SystemColors.Windowkhi Xác thực được gọi với giá trị tốt.


1
+1 để đề cập đến một cách tiếp cận rất thành ngữ API. Tôi còn khá mới đối với Windows Forms và nó khá là phức tạp về chức năng & tài liệu MSDN, vì vậy cũng cảm ơn con trỏ tài liệu cụ thể Validating. <nitpick>OP đề cập rằng ngay lập tức không cho phép / chỉ ra một ký tự không hợp lệ là lý tưởng, nhưng Validatingdường như yêu cầu sự tập trung đó phải được chuyển sang một hình thức / điều khiển khác trước khi nó có hiệu lực. </nitpick>Tuy nhiên, đây là một cách tiếp cận tuyệt vời và luôn luôn đáng xem xét trong trường hợp tổng quát hơn.
William

13

Hãy thử một MaskedTextBox . Nó có một định dạng mặt nạ đơn giản để bạn có thể giới hạn đầu vào thành số hoặc ngày hoặc bất cứ điều gì.


2
Tôi đặc biệt không muốn sử dụng MaskedTextBox. Các định dạng họ cho phép có thể rất hạn chế. Họ làm việc cho trường hợp này nhưng tôi muốn làm một cái gì đó chung chung hơn.
Mykroft

12

Bạn có thể sử dụng TextChangedsự kiện

private void textBox_BiggerThan_TextChanged(object sender, EventArgs e)
{
    long a;
    if (! long.TryParse(textBox_BiggerThan.Text, out a))
    {
        // If not int clear textbox text or Undo() last operation
        textBox_LessThan.Clear();
    }
}

Có vẻ như nó sẽ hoạt động tốt nếu bạn sử dụng Undo(), nhưng nó dẫn đến một StackOverflowException.
vẽ Chapin

Có vẻ như sự phù hợp của TextChanged là một phần của thói quen mà bạn muốn hoàn tác (). Tôi có biến cho toàn bộ cửa sổ và tôi đang sử dụng public int txtBoxValue, và nếu tryPude không hoạt động, tôi hoàn nguyên văn bản trong txtBox bởitxtBox.Text = txtBoxValue.ToString();
L. Zeda

8

Điều này có thể hữu ích. Nó cho phép các giá trị số "thực", bao gồm các dấu thập phân thích hợp và các dấu cộng hoặc dấu trừ trước. Gọi nó từ trong sự kiện KeyPress liên quan.

       private bool IsOKForDecimalTextBox(char theCharacter, TextBox theTextBox)
    {
        // Only allow control characters, digits, plus and minus signs.
        // Only allow ONE plus sign.
        // Only allow ONE minus sign.
        // Only allow the plus or minus sign as the FIRST character.
        // Only allow ONE decimal point.
        // Do NOT allow decimal point or digits BEFORE any plus or minus sign.

        if (
            !char.IsControl(theCharacter)
            && !char.IsDigit(theCharacter)
            && (theCharacter != '.')
            && (theCharacter != '-')
            && (theCharacter != '+')
        )
        {
            // Then it is NOT a character we want allowed in the text box.
            return false;
        }



        // Only allow one decimal point.
        if (theCharacter == '.'
            && theTextBox.Text.IndexOf('.') > -1)
        {
            // Then there is already a decimal point in the text box.
            return false;
        }

        // Only allow one minus sign.
        if (theCharacter == '-'
            && theTextBox.Text.IndexOf('-') > -1)
        {
            // Then there is already a minus sign in the text box.
            return false;
        }

        // Only allow one plus sign.
        if (theCharacter == '+'
            && theTextBox.Text.IndexOf('+') > -1)
        {
            // Then there is already a plus sign in the text box.
            return false;
        }

        // Only allow one plus sign OR minus sign, but not both.
        if (
            (
                (theCharacter == '-')
                || (theCharacter == '+')
            )
            && 
            (
                (theTextBox.Text.IndexOf('-') > -1)
                ||
                (theTextBox.Text.IndexOf('+') > -1)
            )
            )
        {
            // Then the user is trying to enter a plus or minus sign and
            // there is ALREADY a plus or minus sign in the text box.
            return false;
        }

        // Only allow a minus or plus sign at the first character position.
        if (
            (
                (theCharacter == '-')
                || (theCharacter == '+')
            )
            && theTextBox.SelectionStart != 0
            )
        {
            // Then the user is trying to enter a minus or plus sign at some position 
            // OTHER than the first character position in the text box.
            return false;
        }

        // Only allow digits and decimal point AFTER any existing plus or minus sign
        if  (
                (
                    // Is digit or decimal point
                    char.IsDigit(theCharacter)
                    ||
                    (theCharacter == '.')
                )
                &&
                (
                    // A plus or minus sign EXISTS
                    (theTextBox.Text.IndexOf('-') > -1)
                    ||
                    (theTextBox.Text.IndexOf('+') > -1)
                )
                &&
                    // Attempting to put the character at the beginning of the field.
                    theTextBox.SelectionStart == 0
            )
        {
            // Then the user is trying to enter a digit or decimal point in front of a minus or plus sign.
            return false;
        }

        // Otherwise the character is perfectly fine for a decimal value and the character
        // may indeed be placed at the current insertion position.
        return true;
    }

6

Tôi đã làm việc trên một bộ sưu tập các thành phần để hoàn thành những thứ còn thiếu trong WinForms, đây là: Các hình thức nâng cao

Đặc biệt, đây là lớp dành cho Regex TextBox

/// <summary>Represents a Windows text box control that only allows input that matches a regular expression.</summary>
public class RegexTextBox : TextBox
{
    [NonSerialized]
    string lastText;

    /// <summary>A regular expression governing the input allowed in this text field.</summary>
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public virtual Regex Regex { get; set; }

    /// <summary>A regular expression governing the input allowed in this text field.</summary>
    [DefaultValue(null)]
    [Category("Behavior")]
    [Description("Sets the regular expression governing the input allowed for this control.")]
    public virtual string RegexString {
        get {
            return Regex == null ? string.Empty : Regex.ToString();
        }
        set {
            if (string.IsNullOrEmpty(value))
                Regex = null;
            else
                Regex = new Regex(value);
        }
    }

    protected override void OnTextChanged(EventArgs e) {
        if (Regex != null && !Regex.IsMatch(Text)) {
            int pos = SelectionStart - Text.Length + (lastText ?? string.Empty).Length;
            Text = lastText;
            SelectionStart = Math.Max(0, pos);
        }

        lastText = Text;

        base.OnTextChanged(e);
    }
}

Đơn giản chỉ cần thêm một cái gì đó như là myNumbericTextBox.RegexString = "^(\\d+|)$";đủ.


5

Chỉ cần sử dụng một NumericUpDownđiều khiển và thiết lập khả năng hiển thị các nút xấu xí xuống false.

numericUpDown1.Controls[0].Visible = false;

NumericUpDown thực sự là một tập hợp các điều khiển chứa 'hộp quay' (nút lên xuống), hộp văn bản và một số mã để xác thực và kết hợp tất cả lại với nhau.

Đánh dấu:

YourNumericUpDown.Controls[0].visible = false 

sẽ ẩn các nút trong khi giữ mã bên dưới hoạt động.

Mặc dù không phải là một giải pháp rõ ràng, nó đơn giản và hiệu quả. .Controls[1]sẽ ẩn phần hộp văn bản nếu bạn muốn làm điều đó thay vào đó.


Câu trả lời được chấp nhận không bao gồm bất kỳ thông tin nào về cách loại bỏ các nút lên xuống, làm thế nào để làm điều đó là không rõ ràng vì không có giao diện có thể đọc được của con người để kích hoạt hoặc vô hiệu hóa chúng. NumericUpDown thực sự là một tập hợp các điều khiển chứa hộp văn bản và "hộp quay" (nút lên xuống) và một số mã xác thực nhập xác thực.
dùng2163234

4

Tôi đã làm một cái gì đó cho điều này trên CodePlex .

Nó hoạt động bằng cách chặn sự kiện TextChanged. Nếu kết quả là một số tốt, nó sẽ được lưu trữ. Nếu đó là một cái gì đó sai, giá trị tốt cuối cùng sẽ được khôi phục. Nguồn hơi quá lớn để xuất bản ở đây, nhưng đây là một liên kết đến lớp xử lý cốt lõi của logic này.


4

chỉ cần sử dụng mã này trong hộp văn bản:

private void textBox1_TextChanged(object sender, EventArgs e)
{

    double parsedValue;

    if (!double.TryParse(textBox1.Text, out parsedValue))
    {
        textBox1.Text = "";
    }
}

4

Trong trang web của chúng tôi với định nghĩa của hộp văn bản, chúng tôi có thể thêm một onkeypresssự kiện để chỉ chấp nhận số. Nó sẽ không hiển thị bất kỳ thông báo nào nhưng nó sẽ ngăn bạn nhập sai. Nó làm việc cho tôi, người dùng không thể nhập bất cứ thứ gì ngoại trừ số.

<asp:TextBox runat="server" ID="txtFrom"
     onkeypress="if(isNaN(String.fromCharCode(event.keyCode))) return false;">

2

bạn có thể sử dụng sự kiện TextChanged / Keypress, sử dụng biểu thức chính quy để lọc số và thực hiện một số hành động.


2

Tôi sẽ xử lý nó trong sự kiện KeyDown.

void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            char c = Convert.ToChar(e.PlatformKeyCode);
            if (!char.IsDigit(c))
            {
                e.Handled = true;
            }
        }

2
Còn các khóa như "Backspace", "Xóa", "Mũi tên-Khóa trái", "Mũi tên-Khóa-Phải", Sao chép và Dán, Chữ số được nhập bởi Numpad (chúng được giao dịch dưới dạng!
Chữ

Chỉ cần thêm một vài bài kiểm tra như thế này: if (! Char.IsDigit (c) && c! = (Char) Keys.Back)
dnennis

2
private void txt3_KeyPress(object sender, KeyPressEventArgs e)
{
    for (int h = 58; h <= 127; h++)
    {
        if (e.KeyChar == h)             //58 to 127 is alphabets tat will be         blocked
        {
            e.Handled = true;
        }
    }
    for(int k=32;k<=47;k++)
    {
        if (e.KeyChar == k)              //32 to 47 are special characters tat will 
        {                                  be blocked
            e.Handled = true;
        }
    }
}

thử cái này rất đơn giản


2

Hãy xem xử lý đầu vào trong WinForm

Tôi đã đăng giải pháp sử dụng các sự kiện ProcessCmdKey và OnKeyPress trên hộp văn bản. Các ý kiến ​​chỉ cho bạn cách sử dụng Regex để xác minh phím bấm và chặn / cho phép một cách thích hợp.


2

Xin chào, bạn có thể làm một cái gì đó như thế này trong sự kiện trao đổi văn bản của hộp văn bản.

đây là bản demo

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        string actualdata = string.Empty;
        char[] entereddata = textBox1.Text.ToCharArray();
        foreach (char aChar in entereddata.AsEnumerable())
        {
            if (Char.IsDigit(aChar))
            {
                actualdata = actualdata + aChar;
                // MessageBox.Show(aChar.ToString());
            }
            else
            {
                MessageBox.Show(aChar + " is not numeric");
                actualdata.Replace(aChar, ' ');
                actualdata.Trim();
            }
        }
        textBox1.Text = actualdata;
    }

Cảm ơn, nó rất hữu ích.
Kiran RS

2

Có vẻ như nhiều câu trả lời hiện tại cho câu hỏi này đang phân tích thủ công văn bản đầu vào. Nếu bạn đang tìm kiếm một loại số tích hợp cụ thể (ví dụ inthoặc double), tại sao không chỉ ủy thác công việc cho TryParsephương thức của loại đó ? Ví dụ:

public class IntTextBox : TextBox
{
    string PreviousText = "";
    int BackingResult;

    public IntTextBox()
    {
        TextChanged += IntTextBox_TextChanged;
    }

    public bool HasResult { get; private set; }

    public int Result
    {
        get
        {
            return HasResult ? BackingResult : default(int);
        }
    }

    void IntTextBox_TextChanged(object sender, EventArgs e)
    {
        HasResult = int.TryParse(Text, out BackingResult);

        if (HasResult || string.IsNullOrEmpty(Text))
        {
            // Commit
            PreviousText = Text;
        }
        else
        {
            // Revert
            var changeOffset = Text.Length - PreviousText.Length;
            var previousSelectionStart =
                Math.Max(0, SelectionStart - changeOffset);

            Text = PreviousText;
            SelectionStart = previousSelectionStart;
        }
    }
}

Nếu bạn muốn một cái gì đó chung chung hơn nhưng vẫn tương thích với Trình thiết kế của Visual Studio:

public class ParsableTextBox : TextBox
{
    TryParser BackingTryParse;
    string PreviousText = "";
    object BackingResult;

    public ParsableTextBox()
        : this(null)
    {
    }

    public ParsableTextBox(TryParser tryParse)
    {
        TryParse = tryParse;

        TextChanged += ParsableTextBox_TextChanged;
    }

    public delegate bool TryParser(string text, out object result);

    public TryParser TryParse
    {
        set
        {
            Enabled = !(ReadOnly = value == null);

            BackingTryParse = value;
        }
    }

    public bool HasResult { get; private set; }

    public object Result
    {
        get
        {
            return GetResult<object>();
        }
    }

    public T GetResult<T>()
    {
        return HasResult ? (T)BackingResult : default(T);
    }

    void ParsableTextBox_TextChanged(object sender, EventArgs e)
    {
        if (BackingTryParse != null)
        {
            HasResult = BackingTryParse(Text, out BackingResult);
        }

        if (HasResult || string.IsNullOrEmpty(Text))
        {
            // Commit
            PreviousText = Text;
        }
        else
        {
            // Revert
            var changeOffset = Text.Length - PreviousText.Length;
            var previousSelectionStart =
                Math.Max(0, SelectionStart - changeOffset);

            Text = PreviousText;
            SelectionStart = previousSelectionStart;
        }
    }
}

Và cuối cùng, nếu bạn muốn một cái gì đó hoàn toàn chung chung và không quan tâm đến hỗ trợ của Nhà thiết kế:

public class ParsableTextBox<T> : TextBox
{
    TryParser BackingTryParse;
    string PreviousText;
    T BackingResult;

    public ParsableTextBox()
        : this(null)
    {
    }

    public ParsableTextBox(TryParser tryParse)
    {
        TryParse = tryParse;

        TextChanged += ParsableTextBox_TextChanged;
    }

    public delegate bool TryParser(string text, out T result);

    public TryParser TryParse
    {
        set
        {
            Enabled = !(ReadOnly = value == null);

            BackingTryParse = value;
        }
    }

    public bool HasResult { get; private set; }

    public T Result
    {
        get
        {
            return HasResult ? BackingResult : default(T);
        }
    }

    void ParsableTextBox_TextChanged(object sender, EventArgs e)
    {
        if (BackingTryParse != null)
        {
            HasResult = BackingTryParse(Text, out BackingResult);
        }

        if (HasResult || string.IsNullOrEmpty(Text))
        {
            // Commit
            PreviousText = Text;
        }
        else
        {
            // Revert
            var changeOffset = Text.Length - PreviousText.Length;
            var previousSelectionStart =
                Math.Max(0, SelectionStart - changeOffset);

            Text = PreviousText;
            SelectionStart = previousSelectionStart;
        }
    }
}

2

Cả số nguyên và số float đều cần được chấp nhận, bao gồm cả số âm.

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    // Text
    string text = ((Control) sender).Text;

    // Is Negative Number?
    if (e.KeyChar == '-' && text.Length == 0)
    {
        e.Handled = false;
        return;
    }

    // Is Float Number?
    if (e.KeyChar == '.' && text.Length > 0 && !text.Contains("."))
    {
        e.Handled = false;
        return;
    }

    // Is Digit?
    e.Handled = (!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar));
}

2

Đây là lời xin lỗi của tôi:

  1. sử dụng linq (dễ dàng sửa đổi bộ lọc)
  2. sao chép / dán mã bằng chứng
  3. giữ vị trí caret khi bạn nhấn một ký tự bị cấm
  4. chấp nhận số không còn lại
  5. và bất kỳ số kích thước

    private void numeroCuenta_TextChanged(object sender, EventArgs e)
    {
        string org = numeroCuenta.Text;
        string formated = string.Concat(org.Where(c => (c >= '0' && c <= '9')));
        if (formated != org)
        {
            int s = numeroCuenta.SelectionStart;
            if (s > 0 && formated.Length > s && org[s - 1] != formated[s - 1]) s--;
            numeroCuenta.Text = formated;
            numeroCuenta.SelectionStart = s;
        }
    }

2

Sử dụng cách tiếp cận được mô tả trong câu trả lời của Fabio Iotti, tôi đã tạo ra một giải pháp chung chung hơn:

public abstract class ValidatedTextBox : TextBox {
    private string m_lastText = string.Empty;
    protected abstract bool IsValid(string text);
    protected sealed override void OnTextChanged(EventArgs e) {
        if (!IsValid(Text)) {
            var pos = SelectionStart - Text.Length + m_lastText.Length;
            Text = m_lastText;
            SelectionStart = Math.Max(0, pos);
        }
        m_lastText = Text;
        base.OnTextChanged(e);
    }
}

"ValidatedTextBox", chứa tất cả các hành vi xác thực không cần thiết. Tất cả những gì còn lại phải làm là kế thừa từ lớp này và ghi đè phương thức "IsValid" với bất kỳ logic xác thực nào được yêu cầu. Ví dụ: bằng cách sử dụng lớp này, có thể tạo "RegexedTextBox" sẽ chỉ chấp nhận các chuỗi khớp với biểu thức chính quy cụ thể:

public abstract class RegexedTextBox : ValidatedTextBox {
    private readonly Regex m_regex;
    protected RegexedTextBox(string regExpString) {
        m_regex = new Regex(regExpString);
    }
    protected override bool IsValid(string text) {
        return m_regex.IsMatch(Text);
    }
}

Sau đó, kế thừa từ lớp "RegexedTextBox", chúng ta có thể dễ dàng tạo các điều khiển "positiveNumberTextBox" và "positiveFloatingPointNumberTextBox":

public sealed class PositiveNumberTextBox : RegexedTextBox {
    public PositiveNumberTextBox() : base(@"^\d*$") { }
}

public sealed class PositiveFloatingPointNumberTextBox : RegexedTextBox {
    public PositiveFloatingPointNumberTextBox()
        : base(@"^(\d+\" + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + @")?\d*$") { }
}

1

Xin lỗi để đánh thức người chết, nhưng tôi nghĩ ai đó có thể thấy điều này hữu ích để tham khảo trong tương lai.

Đây là cách tôi xử lý nó. Nó xử lý số dấu phẩy động, nhưng có thể dễ dàng sửa đổi cho số nguyên.

Về cơ bản, bạn chỉ có thể nhấn 0 - 9.

Bạn chỉ có thể có một 0 trước .

Tất cả các ký tự khác được bỏ qua và vị trí con trỏ được duy trì.

    private bool _myTextBoxChanging = false;

    private void myTextBox_TextChanged(object sender, EventArgs e)
    {
        validateText(myTextBox);
    }

    private void validateText(TextBox box)
    {
        // stop multiple changes;
        if (_myTextBoxChanging)
            return;
        _myTextBoxChanging = true;

        string text = box.Text;
        if (text == "")
            return;
        string validText = "";
        bool hasPeriod = false;
        int pos = box.SelectionStart;
        for (int i = 0; i < text.Length; i++ )
        {
            bool badChar = false;
            char s = text[i];
            if (s == '.')
            {
                if (hasPeriod)
                    badChar = true;
                else
                    hasPeriod = true;
            }
            else if (s < '0' || s > '9')
                badChar = true;

            if (!badChar)
                validText += s;
            else
            {
                if (i <= pos)
                    pos--;
            }
        }

        // trim starting 00s
        while (validText.Length >= 2 && validText[0] == '0')
        {
            if (validText[1] != '.')
            {
                validText = validText.Substring(1);
                if (pos < 2)
                    pos--;
            }
            else
                break;
        }

        if (pos > validText.Length)
            pos = validText.Length;
        box.Text = validText;
        box.SelectionStart = pos;
        _myTextBoxChanging = false;
    }

Đây là một phiên bản int được sửa đổi nhanh chóng:

    private void validateText(TextBox box)
    {
        // stop multiple changes;
        if (_myTextBoxChanging)
            return;
        _myTextBoxChanging = true;

        string text = box.Text;
        if (text == "")
            return;
        string validText = "";
        int pos = box.SelectionStart;
        for (int i = 0; i < text.Length; i++ )
        {
            char s = text[i];
            if (s < '0' || s > '9')
            {
                if (i <= pos)
                    pos--;
            }
            else
                validText += s;
        }

        // trim starting 00s 
        while (validText.Length >= 2 && validText.StartsWith("00")) 
        { 
            validText = validText.Substring(1); 
            if (pos < 2) 
                pos--; 
        } 

        if (pos > validText.Length)
            pos = validText.Length;
        box.Text = validText;
        box.SelectionStart = pos;
        _myTextBoxChanging = false;
    }

2
Giải pháp này là phát minh lại bánh xe với sự cẩn thận. Nội địa hóa chẳng hạn.
Julien Guertault

1

Công cụ này hoạt động với sao chép và dán, kéo và thả, phím xuống, ngăn tràn và khá đơn giản

public partial class IntegerBox : TextBox 
{
    public IntegerBox()
    {
        InitializeComponent();
        this.Text = 0.ToString();
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
    }

    private String originalValue = 0.ToString();

    private void Integerbox_KeyPress(object sender, KeyPressEventArgs e)
    {
        originalValue = this.Text;
    }

    private void Integerbox_TextChanged(object sender, EventArgs e)
    {
        try
        {
            if(String.IsNullOrWhiteSpace(this.Text))
            {
                this.Text = 0.ToString();
            }
            this.Text = Convert.ToInt64(this.Text.Trim()).ToString();
        }
        catch (System.OverflowException)
        {
            MessageBox.Show("Value entered is to large max value: " + Int64.MaxValue.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            this.Text = originalValue;
        }
        catch (System.FormatException)
        {                
            this.Text = originalValue;
        }
        catch (System.Exception ex)
        {
            this.Text = originalValue;
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK , MessageBoxIcon.Error);
        }
    }       
}

1

Đừng quên rằng người dùng có thể dán một văn bản không hợp lệ vào một TextBox.

Nếu bạn muốn hạn chế điều đó, hãy làm theo đoạn mã dưới đây:

private void ultraTextEditor1_TextChanged(object sender, EventArgs e)
{
    string append="";
    foreach (char c in ultraTextEditor1.Text)
    {
        if ((!Char.IsNumber(c)) && (c != Convert.ToChar(Keys.Back)))
        {

        }
        else
        {
            append += c;
        }
    }

    ultraTextEditor1.Text = append;
}   

1

Tôi cũng đang tìm cách tốt nhất để chỉ kiểm tra các số trong hộp văn bản và vấn đề với phím nhấn là nó không hỗ trợ sao chép dán bằng cách nhấp chuột phải hoặc bảng tạm để tìm ra mã này để xác thực khi con trỏ rời khỏi trường văn bản và nó cũng kiểm tra cánh đồng trống. (phiên bản thích nghi của newguy)

private void txtFirstValue_MouseLeave(object sender, EventArgs e)
{
    int num;
    bool isNum = int.TryParse(txtFirstValue.Text.Trim(), out num);

    if (!isNum && txtFirstValue.Text != String.Empty)
    {
        MessageBox.Show("The First Value You Entered Is Not a Number, Please Try Again", "Invalid Value Detected", MessageBoxButtons.OK, MessageBoxIcon.Error);
        txtFirstValue.Clear();
    }
}

MouseLeave có vẻ như là một lựa chọn thực sự tồi cho một sự kiện sử dụng.
LarsTech

@LarsTech những gì tôi nghĩ đã được chuyển đổi văn bản thậm chí có thể gây ra hộp thông báo lỗi ngay cả khi người dùng nhận ra lỗi và cố gắng sửa nó để tôi nghĩ rằng tôi sẽ làm việc tốt hơn. Bạn nghĩ gì là sự kiện tốt nhất cho trường hợp này?
Alston Antony

@AlstonAntony bình luận muộn, tôi biết. Nhưng một sự kiện nhấp chuột đơn giản kích hoạt trên rightclick sẽ đủ phải không?
Takarii

0
int Number;
bool isNumber;
isNumber = int32.TryPase(textbox1.text, out Number);

if (!isNumber)
{ 
    (code if not an integer);
}
else
{
    (code if an integer);
}

0

3 giải pháp

1)

//Add to the textbox's KeyPress event
//using Regex for number only textBox

private void txtBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (!System.Text.RegularExpressions.Regex.IsMatch(e.KeyChar.ToString(), "\\d+"))
e.Handled = true;
}

2) một giải pháp khác từ msd

// Boolean flag used to determine when a character other than a number is entered.
private bool nonNumberEntered = false;
// Handle the KeyDown event to determine the type of character entered into the     control.
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
// Initialize the flag to false.
nonNumberEntered = false;
// Determine whether the keystroke is a number from the top of the keyboard.
if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)
{
    // Determine whether the keystroke is a number from the keypad.
    if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)
    {
        // Determine whether the keystroke is a backspace.
        if (e.KeyCode != Keys.Back)
        {
            // A non-numerical keystroke was pressed.
            // Set the flag to true and evaluate in KeyPress event.
            nonNumberEntered = true;
        }
    }
}

}

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (nonNumberEntered == true)
    {
       MessageBox.Show("Please enter number only..."); 
       e.Handled = true;
    }
}

nguồn http://msdn.microsoft.com/en-us/l Library / system.windows.forms.control.keypress (v = VS.90) .aspx

3) bằng cách sử dụng MaskedTextBox: http://msdn.microsoft.com/en-us/l Library / system.windows.forms.maskedtextbox.aspx


0

Trong nút bấm, bạn có thể kiểm tra văn bản của hộp văn bản theo vòng lặp:

char[] c = txtGetCustomerId.Text.ToCharArray();
bool IsDigi = true;

for (int i = 0; i < c.Length; i++)
     {
       if (c[i] < '0' || c[i] > '9')
      { IsDigi = false; }
     }
 if (IsDigi)
    { 
     // do something
    }

0

Câu trả lời đơn giản hơn:

_textBox.TextChanged += delegate(System.Object o, System.EventArgs e)
{
    TextBox _tbox = o as TextBox;
    _tbox.Text = new string(_tbox.Text.Where(c => (char.IsDigit(c)) || (c == '.')).ToArray());
};
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.