ฉันจะสร้างกล่องข้อความที่รับเฉพาะตัวเลขได้อย่างไร


582

ฉันมีแอพพลิเคชั่น windows windows พร้อมกล่องข้อความที่ฉันต้องการรับเฉพาะค่าจำนวนเต็ม ในอดีตที่ผ่านมาฉันได้ทำการตรวจสอบประเภทนี้โดยการโหลดเหตุการณ์ KeyPress มากเกินไปและเพิ่งลบอักขระที่ไม่ตรงกับข้อกำหนด ฉันดูที่ตัวควบคุม MaskedTextBox แต่ฉันต้องการโซลูชันทั่วไปที่สามารถใช้งานได้กับนิพจน์ทั่วไปหรือขึ้นอยู่กับค่าของตัวควบคุมอื่น ๆ

เป็นการดีที่สิ่งนี้จะทำงานเช่นการกดอักขระที่ไม่ใช่ตัวเลขจะไม่สร้างผลลัพธ์หรือให้ข้อเสนอแนะแก่ผู้ใช้เกี่ยวกับอักขระที่ไม่ถูกต้องทันที


11
ตัวเลขหรือตัวเลข? ความแตกต่างใหญ่: แม้จำนวนเต็มสามารถลบได้
Joel Coehoorn

8
คำถามมีไว้สำหรับตัวเลขรวมทั้งชุดของจำนวนตรรกยะ
Mykroft

คำตอบ:


797

สองตัวเลือก:

  1. ใช้NumericUpDownแทน NumericUpDown ทำการกรองสำหรับคุณซึ่งดีมาก แน่นอนว่ามันยังช่วยให้ผู้ใช้ของคุณสามารถกดลูกศรขึ้นและลงบนคีย์บอร์ดเพื่อเพิ่มและลดค่าปัจจุบัน

  2. จัดการเหตุการณ์แป้นพิมพ์ที่เหมาะสมเพื่อป้องกันอะไรก็ได้ยกเว้นการป้อนตัวเลข ฉันประสบความสำเร็จกับตัวจัดการเหตุการณ์สองตัวนี้ใน TextBox มาตรฐาน:

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

คุณสามารถลบการตรวจสอบ'.'(และการตรวจสอบที่ตามมามากกว่าหนึ่ง'.') ถ้ากล่องข้อความของคุณไม่ควรอนุญาตให้มีตำแหน่งทศนิยม คุณสามารถเพิ่มการตรวจสอบ'-'ว่ากล่องข้อความของคุณควรอนุญาตค่าลบหรือไม่

หากคุณต้องการ จำกัด จำนวนผู้ใช้งานให้ใช้: textBox1.MaxLength = 2; // this will allow the user to enter only 2 digits


5
ข้อเสียเปรียบเพียงอย่างเดียวกับ NumericUpDown คือมันไม่ได้ให้ข้อเสนอแนะเมื่อคุณป้อนค่านอกค่าสูงสุดหรือต่ำสุดที่อนุญาต - เพียงแค่เปลี่ยนสิ่งที่คุณพิมพ์ กล่องข้อความอย่างน้อยสามารถอนุญาตค่าที่ไม่ถูกต้องเพื่อให้คุณสามารถเตือนผู้ใช้เมื่อพวกเขาส่งแบบฟอร์ม
Matt Hamilton

7
นั่นเป็นความจริง - ผู้ใช้สามารถวางในอักขระที่ไม่ใช่ตัวเลขได้เสมอ คุณหวังว่าการตรวจสอบแบบฟอร์มจะเป็นเช่นนั้นเนื่องจากในบางจุดคุณจะต้องทำการ Int32.TryParse หรืออะไรบางอย่าง
Matt Hamilton

52
คุณจะต้องใช้ความพยายามเพิ่มเติมเพื่อทำให้โลกนี้เป็นจริงโดยแทนที่เช็คสำหรับ '.' ด้วยการตรวจสอบ CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator
Jeff Yates

6
@HamishGrubijan, IsControl ไม่มีส่วนเกี่ยวข้องกับคีย์ควบคุม มันจะส่งกลับว่าถ่านเป็นถ่านควบคุมหรือไม่ ด้วยการอนุญาตให้ใช้ตัวควบคุมคุณจะไม่ทำลายสิ่งต่าง ๆ เช่น backspace ลบหรือปุ่มลูกศร
Thomas Levesque

13
วิธีนี้ยังคงยอมรับอินพุต ctrl + v ที่ผิดกฎหมาย บั๊กที่มีอยู่ในตัวควบคุม NumericUpDown อย่างเป็นทางการ
Nyerguds

149

และเพียงเพราะมันสนุกมากกว่าที่จะทำสิ่งต่าง ๆ ในบรรทัดเดียว ...

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

หมายเหตุ: นี่ไม่ได้ป้องกันผู้ใช้จากการคัดลอก / วางลงในกล่องข้อความนี้ ไม่ใช่วิธีที่ปลอดภัยที่จะทำให้ข้อมูลของคุณปลอดภัย


นี่ไม่ใช่วิธีแก้ไขปัญหาทั่วไปเนื่องจากทำงานได้เฉพาะกับผู้แทรกแซง ฉันต้องใช้สิ่งนี้เมื่อเร็ว ๆ นี้และฉันจบลงด้วยการลองแยกสตริงผลลัพธ์เป็นตัวเลขและอนุญาตให้ป้อนข้อมูลก็ต่อเมื่อการแยกวิเคราะห์สำเร็จ
grzegorz_p

1
สิ่งนี้อาจไม่ทำงานเมื่อหลายวิธีจัดการกับKeyPressเหตุการณ์จากกล่องข้อความเดียวกัน เหตุการณ์หนึ่งอาจตั้งค่าe.Handledเป็นจริงจากนั้นเหตุการณ์อีกเหตุการณ์หนึ่งอาจตั้งค่าเป็นเท็จ โดยทั่วไปจะดีกว่าที่จะใช้if (...) e.Handled = true;
นาธาเนียลโจนส์

2
คุณสามารถปิดการใช้งานคุณสมบัติทางลัดเปิดใช้งานเพื่อป้องกันการคัดลอกวางโดยแป้นพิมพ์หรือเมนู
Ahmad

3
ฮ่า ๆ ! ใช่ หนึ่งสมุทร!
Jamie L.

3
เอ๊ะ TextChangedเหตุการณ์ที่จะไปมากกว่านั้นกับ regex สามารถแก้ไข copy-paste;)
Nyerguds

51

ฉันกำลังสมมติว่าจากบริบทและแท็กที่คุณใช้ว่าคุณกำลังเขียนแอป. NET C # ในกรณีนี้คุณสามารถสมัครสมาชิกข้อความเหตุการณ์เปลี่ยนแปลงและตรวจสอบแต่ละจังหวะที่สำคัญ

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
นั่นจะไม่ส่งผลที่แปลกมากหากคุณพิมพ์ลงไปในจำนวนกลางหรือไม่?
Colin Pickard

5
และควรเป็น:textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);
Pieniadz

3
เกิดอะไรขึ้นถ้าตัวละครตัวแรกไม่ใช่ตัวเลข ... จะไม่ลบ 1 ในกรณีนั้นจะเกิดข้อผิดพลาด ....
manu_dilip_shah

6
นอกจากนี้การใช้ TextChanged แทน KeyPress จะสร้างการสอบถามซ้ำเล็กน้อยซึ่งรหัสจะข้ามไปยังเหตุการณ์ TextChanged ที่สองหลังจากวิธีการลบ
WEFX

2
คุณสลับพารามิเตอร์อินพุตและรูปแบบสำหรับฟังก์ชัน IsMatch ของคุณ อินพุตควรเป็นอันดับแรกจากนั้นจึงจัดรูปแบบ msdn.microsoft.com/en-us/library/sdx2bds0(v=vs.110).aspx
Mibou

36

นี่คือการควบคุมแบบกำหนดเอง Winforms แบบสแตนด์อโลนที่เรียบง่ายซึ่งได้มาจากกล่องข้อความมาตรฐานที่อนุญาตเฉพาะอินพุต System.Int32 (สามารถปรับให้เข้ากับประเภทอื่นเช่น System.Int64 และอื่น ๆ ได้อย่างง่ายดาย) รองรับการคัดลอก / วางและจำนวนลบ:

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

อัปเดต 2017 : คำตอบแรกของฉันมีปัญหา:

  • คุณสามารถพิมพ์สิ่งที่ยาวกว่าจำนวนเต็มของประเภทที่กำหนด (ตัวอย่างเช่น 2147483648 มากกว่า Int32.MaxValue);
  • โดยทั่วไปแล้วไม่มีการตรวจสอบความถูกต้องของผลลัพธ์ของสิ่งที่พิมพ์
  • จัดการกับ int32 เท่านั้นคุณจะต้องเขียนกล่องข้อความที่ควบคุมมาสำหรับแต่ละประเภท (Int64 และอื่น ๆ )

ดังนั้นฉันจึงพบกับรุ่นอื่นที่เป็นแบบทั่วไปมากกว่าซึ่งยังคงรองรับการคัดลอก / วาง + และ - เซ็น ฯลฯ

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

สำหรับ Int32 คุณสามารถหาได้จากมันเช่นนี้

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

หรือไม่มีการสืบทอดให้ใช้เหตุการณ์ TextValidating ใหม่เช่นนี้:

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

แต่สิ่งที่ดีคือมันใช้ได้กับสตริงใด ๆ และรูทีนการตรวจสอบความถูกต้องใด ๆ


นี่ยอดเยี่ยมดีและเรียบง่ายใช้งานง่ายและจัดการกับการป้อนข้อมูลที่ผิดปกติ ขอบคุณ!
WiredEarp

1
หมายเหตุในเวอร์ชั่น 2017 เมื่อมีค่าเดียวเช่น 1 และคุณกดแบ็คสเปซมันจะไม่สนใจในขณะที่ถ้าคุณพูด 120 และกดแบ็คสเปซสามครั้งเราจะเหลือ 1
Karen Payne

1
ValidatingTextbox ของคุณเป็นการใช้งานที่ดีที่สุดที่ฉันเคยเห็นมาระยะหนึ่งแล้ว ง่ายและมีประสิทธิภาพ ขอบคุณ!
ซามูเอล

19

นี่คือสิ่งที่กิจกรรมการตรวจสอบ / รับรองความถูกต้องได้รับการออกแบบมาสำหรับ

นี่คือบทความ MSDN ในหัวข้อ: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.validating.aspx

รุ่น TL; DR: ตรวจสอบคุณสมบัติ. Text ในเหตุการณ์การตรวจสอบและตั้งค่าe.Cancel=Trueเมื่อข้อมูลไม่ถูกต้อง

เมื่อคุณตั้งค่า e.Cancel = True ผู้ใช้ไม่สามารถออกจากฟิลด์ได้ แต่คุณจะต้องให้ข้อเสนอแนะบางอย่างกับพวกเขาว่ามีบางอย่างผิดปกติ ฉันเปลี่ยนสีพื้นหลังของกล่องเป็นสีแดงอ่อนเพื่อระบุปัญหา ตรวจสอบให้แน่ใจว่าได้ตั้งค่ากลับเป็นSystemColors.Windowเมื่อมีการเรียกใช้การตรวจสอบความถูกต้องด้วยค่าที่ดี


1
+1 สำหรับการกล่าวถึงวิธีใช้ API- สำนวนมาก ฉันค่อนข้างใหม่สำหรับ Windows Forms และมันค่อนข้างเป็นเรื่องของการใช้งาน & เอกสาร MSDN ดังนั้นขอบคุณสำหรับตัวชี้ doc ที่เฉพาะเจาะจงValidatingด้วย <nitpick>OP ระบุว่าไม่อนุญาต / ระบุอักขระที่ทำให้ใช้งานไม่ได้ในทันที แต่Validatingดูเหมือนว่าต้องการย้ายโฟกัสไปยังรูปแบบ / การควบคุมอื่นก่อนจึงจะมีผล </nitpick>แต่ถึงกระนั้นนี่ก็เป็นวิธีการที่ยอดเยี่ยมและควรพิจารณาในกรณีทั่วไปมากกว่า
วิลเลียม

13

ลองMaskedTextBox มันใช้รูปแบบหน้ากากที่เรียบง่ายเพื่อให้คุณสามารถ จำกัด อินพุตให้เป็นตัวเลขหรือวันที่หรืออะไรก็ตาม


2
ฉันไม่ต้องการใช้ MaskedTextBox โดยเฉพาะ รูปแบบที่อนุญาตอาจมีข้อ จำกัด มาก พวกเขาใช้งานได้ในกรณีนี้ แต่ฉันต้องการทำอะไรที่ธรรมดากว่านี้
Mykroft

12

คุณสามารถใช้TextChangedเหตุการณ์

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

ดูเหมือนว่ามันจะทำงานได้ดีถ้าคุณใช้แต่ผลในUndo() StackOverflowException
Drew Chapin

ดูเหมือนว่าความเหมาะสมของ TextChanged เป็นส่วนหนึ่งของกิจวัตรที่คุณต้องการเลิกทำ () ฉันมีตัวแปรสำหรับทั้งหน้าต่างและฉันใช้public int txtBoxValueและถ้า tryParse ไม่ทำงานฉันจะแปลงข้อความเป็น txtBox โดยtxtBox.Text = txtBoxValue.ToString();
L. Zeda

8

สิ่งนี้อาจมีประโยชน์ อนุญาตให้ใช้ค่าตัวเลข "ของจริง" รวมถึงจุดทศนิยมที่เหมาะสมและเครื่องหมายบวกหรือลบก่อนหน้า โทรจากภายในเหตุการณ์ KeyPress ที่เกี่ยวข้อง

       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

ฉันได้ทำงานกับคอลเลกชันของส่วนประกอบเพื่อทำสิ่งที่ขาดหายไปใน WinForms นี่คือ: Advanced Forms

โดยเฉพาะนี่คือคลาสสำหรับกล่องข้อความ Regex

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

เพียงเพิ่มบางสิ่งเช่นmyNumbericTextBox.RegexString = "^(\\d+|)$";ควรจะพอเพียง


5

เพียงแค่ใช้การNumericUpDownควบคุมและตั้งค่าการมองเห็นปุ่มที่น่าเกลียดเหล่านั้นให้falseเป็น

numericUpDown1.Controls[0].Visible = false;

NumericUpDown จริงๆแล้วเป็นคอลเลกชันของตัวควบคุมที่มี 'กล่องหมุน' (ปุ่มขึ้นลง), กล่องข้อความและรหัสบางอย่างเพื่อตรวจสอบและรวมกันทั้งหมดเข้าด้วยกัน

ทำเครื่องหมาย:

YourNumericUpDown.Controls[0].visible = false 

จะซ่อนปุ่มในขณะที่ยังคงรหัสที่ใช้งานอยู่

ในขณะที่ไม่ได้เป็นทางออกที่ชัดเจนมันง่ายและมีประสิทธิภาพ .Controls[1]จะซ่อนส่วนของกล่องข้อความหากคุณต้องการทำเช่นนั้นแทน


คำตอบที่ได้รับการยอมรับไม่ได้รวมข้อมูลใด ๆ เกี่ยวกับวิธีการลบปุ่มขึ้นลงวิธีการทำเช่นนั้นไม่ชัดเจนเนื่องจากไม่มีอินเทอร์เฟซที่มนุษย์สามารถอ่านได้เพื่อเปิดใช้งานหรือปิดใช้งาน NumericUpDown เป็นชุดควบคุมที่มีกล่องข้อความและ "สปินบ็อกซ์" (ปุ่มขึ้นลง) และการตรวจสอบการป้อนรหัสบางอย่าง
user2163234

4

ผมได้ทำบางสิ่งบางอย่างเกี่ยวกับเรื่องนี้CodePlex

มันทำงานได้โดยการดักเหตุการณ์ TextChanged หากผลลัพธ์เป็นตัวเลขที่ดีจะถูกเก็บไว้ หากมีสิ่งผิดปกติมูลค่าสุดท้ายจะถูกคืนค่า แหล่งข้อมูลมีขนาดใหญ่เกินไปที่จะเผยแพร่ที่นี่ แต่นี่เป็นลิงก์ไปยังคลาสที่จัดการกับแกนหลักของตรรกะนี้


4

เพียงใช้รหัสนี้ในกล่องข้อความ:

private void textBox1_TextChanged(object sender, EventArgs e)
{

    double parsedValue;

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

4

ในหน้าเว็บของเราพร้อมคำจำกัดความของกล่องข้อความเราสามารถเพิ่มonkeypressเหตุการณ์สำหรับการรับเฉพาะตัวเลข จะไม่แสดงข้อความใด ๆ แต่จะป้องกันไม่ให้คุณป้อนผิด มันใช้งานได้สำหรับฉันผู้ใช้ไม่สามารถป้อนอะไรก็ได้ยกเว้นหมายเลข

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


2

ฉันจะจัดการกับมันในเหตุการณ์ KeyDown

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

2
สิ่งที่เกี่ยวกับคีย์เช่น "Backspace", "ลบ", "Arrow-Key-Left", "Arrow-Key-Right", คัดลอกและวาง, ตัวเลขที่ป้อนโดย Numpad (พวกเขาซื้อขายกัน!! หลัก)
user799821

เพียงเพิ่มการทดสอบอีกสองสามอย่างดังนี้: 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;
        }
    }
}

ลองนี่ง่ายมาก


2

ดูการจัดการอินพุตใน WinForm

ฉันโพสต์โซลูชันของฉันซึ่งใช้เหตุการณ์ ProcessCmdKey และ OnKeyPress บนกล่องข้อความ ความคิดเห็นแสดงวิธีการใช้ Regex เพื่อตรวจสอบ keypress และ block / อนุญาตอย่างเหมาะสม


2

สวัสดีคุณสามารถทำสิ่งนี้ในเหตุการณ์ textchanged ของกล่องข้อความ

นี่คือตัวอย่าง

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

ขอบคุณมันมีประโยชน์มาก
Kiran RS

2

ดูเหมือนว่าคำตอบปัจจุบันจำนวนมากสำหรับคำถามนี้จะแยกวิเคราะห์ข้อความอินพุตด้วยตนเอง หากคุณกำลังมองหาประเภทตัวเลขในตัว (เช่นintหรือdouble) ทำไมไม่เพียงมอบหมายงานให้กับTryParseวิธีการประเภทนั้น ตัวอย่างเช่น:

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

ถ้าคุณต้องการบางสิ่งที่ธรรมดากว่า แต่ก็ยังเข้ากันได้กับนักออกแบบของ 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;
        }
    }
}

และในที่สุดถ้าคุณต้องการบางสิ่งที่สมบูรณ์แบบและไม่สนใจการสนับสนุนจากผู้ออกแบบ:

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

ต้องยอมรับทั้งจำนวนเต็มและจำนวนลอยรวมถึงจำนวนลบ

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

นี่คือ aproach ของฉัน:

  1. ใช้ linq (ง่ายต่อการปรับเปลี่ยนตัวกรอง)
  2. คัดลอก / วางรหัสหลักฐาน
  3. คงคาเร็ตเมื่อคุณกดตัวอักษรต้องห้าม
  4. ยอมรับค่าศูนย์ซ้าย
  5. และตัวเลขขนาดใด ๆ

    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

การใช้วิธีการที่อธิบายไว้ในคำตอบของ Fabio Iottiฉันได้สร้างวิธีแก้ปัญหาทั่วไปเพิ่มเติม:

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" ซึ่งมีพฤติกรรมการตรวจสอบความถูกต้องทั้งหมด สิ่งที่เหลืออยู่ที่ต้องทำคือการสืบทอดจากคลาสนี้และแทนที่เมธอด "IsValid" ด้วยตรรกะการตรวจสอบใด ๆ ก็ตามที่จำเป็น ตัวอย่างเช่นการใช้คลาสนี้สามารถสร้าง "RegexedTextBox" ซึ่งจะยอมรับเฉพาะสตริงที่ตรงกับนิพจน์ทั่วไปที่ระบุเท่านั้น:

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

หลังจากนั้นการสืบทอดจากคลาส "RegexedTextBox" เราสามารถสร้างตัวควบคุม "PositiveNumberTextBox" และ "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

ขออภัยที่ปลุกคนตาย แต่ฉันคิดว่าบางคนอาจพบว่ามีประโยชน์สำหรับการอ้างอิงในอนาคต

นี่คือวิธีที่ฉันจัดการกับมัน มันจัดการกับตัวเลขจุดลอย แต่สามารถแก้ไขได้อย่างง่ายดายสำหรับจำนวนเต็ม

โดยทั่วไปคุณสามารถกด0 - 9 และ

คุณสามารถมีได้เพียงหนึ่ง0 ก่อน

อักขระอื่น ๆ ทั้งหมดจะถูกละเว้นและรักษาตำแหน่งเคอร์เซอร์ไว้

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

นี่คือเวอร์ชั่น int ที่ถูกแก้ไขอย่างรวดเร็ว:

    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
วิธีแก้ปัญหานี้เป็นการสร้างล้อใหม่ด้วยคำเตือน ยกตัวอย่างเช่น
Julien Guertault

1

อันนี้ใช้ได้กับการคัดลอกและวาง, ลากและวาง, กดลง, ป้องกันการโอเวอร์โฟลว์และค่อนข้างง่าย

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

อย่าลืมว่าผู้ใช้สามารถวางข้อความที่ไม่ถูกต้องใน TextBoxอย่าลืมว่าผู้ใช้สามารถวางข้อความที่ไม่ถูกต้องใน

หากคุณต้องการ จำกัด ให้ทำตามรหัสด้านล่าง:

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

ฉันกำลังมองหาวิธีที่ดีที่สุดในการตรวจสอบตัวเลขในกล่องข้อความและปัญหาเกี่ยวกับปุ่มกดเท่านั้นเพราะมันไม่รองรับการคัดลอกวางโดยคลิกขวาหรือคลิปบอร์ดดังนั้นจึงเกิดรหัสนี้ขึ้นซึ่งจะตรวจสอบเมื่อเคอร์เซอร์ออกจากช่องข้อความและตรวจสอบ ช่องว่าง (เวอร์ชั่นดัดแปลงของ 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 ดูเหมือนจะเป็นตัวเลือกที่ไม่ดีจริงๆสำหรับกิจกรรมที่จะใช้
LarsTech

@ LarsTech สิ่งที่ฉันคิดว่าเป็น textchanged แม้อาจทำให้เกิดกล่องข้อความแสดงข้อผิดพลาดก่อนแม้ว่าผู้ใช้จะรับรู้ถึงข้อผิดพลาดและพยายามแก้ไขมันดังนั้นฉันจึงคิดว่าฉันจะทำงานได้ดีขึ้น คุณคิดว่าเหตุการณ์ที่ดีที่สุดสำหรับคดีนี้คืออะไร?
Alston Antony

@AlstonAntony ความเห็นปลายฉันรู้ แต่เหตุการณ์คลิกง่าย ๆ ที่เปิดใช้งานบนคลิกขวาจะไม่เพียงพอหรือไม่
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 ทางออก

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) โซลูชันอื่นจาก msdn

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

แหล่ง http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keypress(v=VS.90).aspx

3) ใช้ MaskedTextBox: http://msdn.microsoft.com/en-us/library/system.windows.forms.maskedtextbox.aspx


0

ในการคลิกปุ่มคุณสามารถตรวจสอบข้อความของกล่องข้อความโดยสำหรับวง:

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

คำตอบที่ง่ายกว่า:

_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());
};
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.