숫자 만 허용하는 텍스트 상자를 만들려면 어떻게합니까?


582

정수 값만 허용하려는 텍스트 상자 컨트롤이있는 Windows Forms 앱이 있습니다. 과거에는 KeyPress 이벤트를 오버로드하고 사양에 맞지 않는 문자를 제거하여 이러한 종류의 유효성 검사를 수행했습니다. MaskedTextBox 컨트롤을 살펴 보았지만 정규 표현식으로 작동하거나 다른 컨트롤의 값에 의존 할 수있는보다 일반적인 솔루션을 원합니다.

숫자가 아닌 문자를 누르면 결과가 생성되지 않거나 사용자에게 유효하지 않은 문자에 대한 피드백을 즉시 제공하는 것이 이상적입니다.


11
숫자 또는 숫자? 큰 차이 : 심지어 정수는 음수 갈 수
조엘 Coehoorn

8
이 문제는 전체 합리적 수를 포함한 숫자에 대한 것입니다.
Mykroft 2016 년

답변:


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

TextBox에서 소수점 이하 자릿수를 허용하지 않으면 확인을 제거하고 '.'이후에 둘 이상의 확인을 제거 할 수 있습니다 '.'. '-'TextBox에서 음수 값을 허용해야하는지 여부를 확인할 수도 있습니다 .

사용자를 자릿수로 제한하려면 다음을 사용하십시오. textBox1.MaxLength = 2; // this will allow the user to enter only 2 digits


5
NumericUpDown의 유일한 단점은 최대 또는 최소 허용 값 이외의 값을 입력 할 때 피드백을 제공하지 않으며 입력 한 내용 만 변경한다는 것입니다. TextBox는 적어도 유효하지 않은 값을 허용하므로 양식을 제출할 때 사용자에게 경고 할 수 있습니다.
매트 해밀턴

7
사실입니다. 사용자는 항상 숫자가 아닌 문자를 붙여 넣을 수 있습니다. 폼 유효성 검사가이를 포착 할 수 있기를 바랍니다. 언젠가는 Int32.TryParse 또는 무언가를 원할 것이기 때문입니다.
매트 해밀턴

52
'.'에 대한 점검을 대체하여이를 세계화하려면 추가 노력이 필요합니다. CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator를 점검합니다.
Jeff Yates

6
@HamishGrubijan, IsControl은 Control 키와 관련이 없습니다. 문자가 제어 문자인지 여부를 리턴합니다. 제어 문자를 허용하면 백 스페이스, 삭제 또는 화살표 키와 같은 항목을 깰 수 없습니다.
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);
    }

참고 : 이렇게하면 사용자가이 텍스트 상자에 복사 / 붙여 넣기를 할 수 없습니다. 데이터를 안전하게 처리하는 안전한 방법은 아닙니다.


이것은 interger들에게만 적용되기 때문에 일반적인 해결책은 아닙니다. 나는 최근에 그런 일을 구현했다 그리고 난 시도 구문 분석 구문 분석이 성공하는 경우에만 번호로 문자열을 결과 입력을 허용하여 결국
grzegorz_p

1
여러 메소드 KeyPress가 동일한 텍스트 상자의 이벤트를 처리하는 경우에는 작동하지 않을 수 있습니다 . 한 이벤트는 e.Handledtrue로 설정 되고 다른 이벤트는 다시 false로 설정 될 수 있습니다. 일반적으로 사용하는 것이 좋습니다if (...) e.Handled = true;
Nathaniel Jones

2
키보드 또는 메뉴로 복사 붙여 넣기를 방지하기 위해 ShortcutsEnabled 속성을 비활성화 할 수 있습니다
Ahmad

3
ㅋ! 예! 하나의 라이너!
Jamie L.

3
뭐라고. TextChanged정규식으로 진행 되는 이벤트는 복사-붙여 넣기를 수정할 수 있습니다.)
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
숫자 중간에 입력하면 매우 이상한 효과가 발생하지 않습니까?
콜린 피커드

5
– 또한 다음과 같아야합니다.textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);
Pieniadz

3
무엇을 첫 번째 문자 자체가 ... 오류가 발생하는 경우에 1을 뺀하지 않을 숫자가 아닌 경우 ....
manu_dilip_shah

6
또한 KeyPress 대신 TextChanged를 사용하면 Remove 메서드 다음에 코드가 두 번째 TextChanged 이벤트로 이동한다는 점에서 약간의 재귀가 발생합니다.
WEFX

2
IsMatch 기능에 대한 입력 및 패턴 매개 변수를 전환했습니다. 먼저 입력 한 다음 패턴을 입력해야합니다. msdn.microsoft.com/ko-kr/library/sdx2bds0(v=vs.110).aspx
Mibou

36

표준 TextBox에서 파생 된 간단한 독립 실행 형 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 등)에 대해 특정 TextBox 파생 컨트롤을 작성해야합니다.

그래서 복사 / 붙여 넣기, + 및-기호 등을 계속 지원하는 더 일반적인 다른 버전을 생각해 냈습니다.

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

바로 Validated / Validating 이벤트가 설계된 것입니다.

다음 주제에 대한 MSDN 기사입니다. http://msdn.microsoft.com/en-us/library/system.windows.forms.control.validating.aspx

TL; DR 버전 : Validating 이벤트에서 .Text 속성을 확인 e.Cancel=True하고 데이터가 유효하지 않을 때 설정 하십시오.

e.Cancel = True를 설정하면 사용자는 필드를 떠날 수 없지만 문제가있는 피드백을 제공해야합니다. 상자의 배경색을 밝은 빨간색으로 변경하여 문제를 나타냅니다. SystemColors.WindowValidating이 좋은 값으로 호출 될 때 다시 설정하십시오 .


1
API- 아이디 오마 틱 접근 방식을 언급 한 +1 저는 Windows Forms를 처음 접했고 상당히 많은 기능 및 MSDN 문서이므로 특정 문서 포인터에 대한 감사합니다 Validating. <nitpick>OP는 무효화 캐릭터를 즉시 금지 / 표시하는 것이 이상적이지만, Validating포커스를 적용하기 전에 다른 폼 / 컨트롤로 포커스를 이동해야한다고합니다. </nitpick>그러나 이것은 훌륭한 접근 방법이며 항상 일반적인 경우에 고려할 가치가 있습니다.
William

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 속성이 undo ()하려는 루틴의 일부인 것 같습니다. 전체 창에 변수 public int txtBoxValue가 있고을 사용 하고 있으며 tryParse가 작동하지 않으면 txtBox의 텍스트를txtBox.Text = txtBoxValue.ToString();
L. Zeda로 수정하십시오. 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에서 누락 된 항목을 완성하기 위해 구성 요소 모음을 작업하고 있습니다. 고급 양식

특히 이것은 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);
    }
}

다음과 같은 것을 추가 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
"백 스페이스", "삭제", "화살표 키-왼쪽", "화살표 키-오른쪽", 복사 및 붙여 넣기, 숫자 키패드로 입력 한 자릿수 (그들은! 숫자로 거래 됨)와 같은 키는
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 이벤트를 사용하는 솔루션을 게시했습니다. 주석은 정규식을 사용하여 키 누르기를 확인하고 적절하게 차단 / 허용하는 방법을 보여줍니다.


2

안녕하세요, 텍스트 상자의 텍스트 변경 이벤트에서 이와 같은 작업을 수행 할 수 있습니다.

여기 데모가 있습니다

    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의 Designer와 호환되는 것을 원할 경우 :

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. 왼쪽 0을 받아들입니다
  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 텍스트 변경이라고 생각한 경우에도 사용자가 오류를 인식하고 수정하려고해도 오류 메시지 상자가 발생하여 더 잘 작동한다고 생각했습니다. 이 사건에 가장 적합한 이벤트는 무엇이라고 생각하십니까?
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

버튼 클릭으로 for 루프로 텍스트 상자의 텍스트를 확인할 수 있습니다.

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.