Yalnızca sayıları kabul eden bir metin kutusunu nasıl oluştururum?


582

Yalnızca tamsayı değerlerini kabul etmek istediğim bir metin kutusu denetimi olan bir windows form uygulaması var. Geçmişte, KeyPress olayını aşırı yükleyerek ve yalnızca spesifikasyona uymayan karakterleri kaldırarak bu tür bir doğrulama yaptım. MaskedTextBox denetimine baktım ama belki de düzenli bir ifade ile çalışabilir veya diğer denetimlerin değerlerine bağlı olabilir daha genel bir çözüm istiyorum.

İdeal olarak bu, sayısal olmayan bir karaktere basmanın sonuç vermeyeceği veya kullanıcıya geçersiz karakter hakkında hemen geri bildirim sağlayacağı şekilde davranır.


11
rakamlar veya rakamlar? büyük fark: tamsayılar bile negatif olabilir
Joel Coehoorn

8
Soru, tüm rasyonel sayılar kümesini içeren sayılar için tasarlandı.
Mykroft

Yanıtlar:


797

İki seçenek:

  1. NumericUpDownBunun yerine bir kullanın. NumericUpDown filtrelemeyi sizin için yapar, bu da güzeldir. Tabii ki kullanıcılarınıza geçerli değeri artırmak ve azaltmak için klavyedeki yukarı ve aşağı oklara basma yeteneği verir.

  2. Sayısal giriş dışında herhangi bir şeyi önlemek için uygun klavye olaylarını kullanın. Standart bir TextBox'ta bu iki olay işleyicisiyle başarılı oldum:

    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'ınızın ondalık basamaklara izin vermemesi gerekiyorsa , denetimi '.'(ve daha sonra gelen birden fazla denetimi) kaldırabilirsiniz '.'. Ayrıca '-'TextBox'ınızın negatif değerlere izin verip vermeyeceğini kontrol edebilirsiniz.

Kullanıcıyı basamak sayısı ile sınırlamak istiyorsanız, şunu kullanın: textBox1.MaxLength = 2; // this will allow the user to enter only 2 digits


5
NumericUpDown'ın tek dezavantajı, izin verilen Maksimum veya Minimum değerlerin dışında bir değer girdiğinizde geri bildirim sağlamamasıdır - yalnızca yazdıklarınızı değiştirir. Bir TextBox en azından geçersiz değerlere izin verebilir, böylece formu gönderirken kullanıcıyı uyarabilirsiniz.
Matt Hamilton

7
Bu doğru - kullanıcı her zaman sayısal olmayan bazı karakterleri yapıştırabilir. Form doğrulamanın bunu yakalayacağını umuyorsunuz, çünkü bir noktada bir Int32 yapmak isteyeceksiniz.
Matt Hamilton

52
"." Denetimlerini değiştirerek bunu küreselleştirmek için biraz çaba harcamanız gerekir. CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator üzerinde denetimler.
Jeff Yates

6
@HamishGrubijan, IsControl'ün Control tuşuyla ilgisi yoktur; bir karakterin bir kontrol karakteri olup olmadığını döndürür. Kontrol karakterlerine izin vererek, geri silme, silme veya ok tuşları gibi şeyleri kırmazsınız
Thomas Levesque

13
Bu arada, hala yasadışı ctrl + v girişi kabul edilmektedir; Resmi NumericUpDown kontrolünde bile var olan bir hata.
Nyerguds

149

Ve bir satırda bir şeyler yapmak her zaman daha eğlenceli olduğu için ...

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

NOT: Bu, bir kullanıcının bu metin kutusuna Kopyala / Yapıştır uygulamasını engellemez. Verilerinizi temizlemenin güvenli bir yolu değildir.


Bu sadece genel bir çözüm değildir, çünkü sadece interger'lar için çalışır. Son zamanlarda böyle bir şey uygulamak zorunda kaldı ve ben sayıya sonuçlanan dize ayrıştırma denemek ve sadece ayrıştırma başarılı olursa giriş izin ile sona erdi
grzegorz_p

1
Birden çok yöntem KeyPressaynı metin kutusundaki olayları işlediğinde bu çalışmayabilir . Bir olay e.Handledtrue değerine, diğeri de false değerine geri dönebilir. Genel olarak, kullanmak daha iyidirif (...) e.Handled = true;
Nathaniel Jones

2
Klavye veya menü ile kopya yapışmasını önlemek için ShortcutsEnabled özelliğini devre dışı bırakabilirsiniz
Ahmad

3
HAHA! Evet! Bir gömlek!
Jamie L.

3
Eh. Bir TextChangednormal ifade ile üzerinden geçen bir olay kopyala-macunu düzeltebilir;)
Nyerguds

51

Bağlam ve .NET C # uygulaması yazarken kullandığınız etiketleri varsayıyorum. Bu durumda, metin değiştirilmiş olaya abone olabilir ve her tuş vuruşunu doğrulayabilirsiniz.

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
Bir sayının ortasına yazarsanız bu çok garip bir etki yaratmaz mı?
Colin Pickard

5
ve ayrıca şöyle olmalıdır:textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);
Pieniadz

3
ilk karakterin kendisi bir rakam değilse ... bu durumda 1 çıkartılmazsa hata verir ....
manu_dilip_shah

6
Ayrıca, KeyPress yerine TextChanged kullanımı, kodun Remove yönteminden sonra ikinci bir TextChanged olayına atlaması nedeniyle biraz özyineleme oluşturur.
WEFX

2
IsMatch işleviniz için giriş ve desen parametrelerini değiştirdiniz. Giriş önce, sonra desen olmalıdır. msdn.microsoft.com/en-us/library/sdx2bds0(v=vs.110).aspx
Mibou

36

Burada, standart TextBox'tan türetilmiş, yalnızca System.Int32 girişine izin veren basit bir bağımsız Winforms özel denetimi bulunmaktadır (System.Int64, vb. Gibi diğer türler için kolayca uyarlanabilir). Kopyalama / yapıştırma işlemlerini ve negatif sayıları destekler:

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 Güncellemesi : İlk cevabımın bazı sorunları var:

  • belirli bir türde bir tam sayıdan daha uzun bir şey yazabilirsiniz (örneğin, 2147483648, Int32.MaxValue'dan daha büyüktür);
  • daha genel olarak, sonucun gerçek bir doğrulaması yoktur yazılanların ;
  • yalnızca int32'yi işliyorsa, her tür (Int64 vb.) için özel TextBox türetilmiş denetim yazmanız gerekir

Bu yüzden, daha genel, kopyala / yapıştır, + ve - işaretini vb. Destekleyen başka bir sürüm buldum.

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 için, ya şu şekilde türetebilirsiniz:

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

veya türetme olmadan, aşağıdaki gibi yeni TextValidating olayını kullanın:

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

ancak güzel olan şey, herhangi bir dizeyle ve herhangi bir doğrulama yordamıyla çalışmasıdır.


Bu harika, hoş ve basit, kolay kullanılır ve alışılmadık giriş denemeleriyle ilgilenir. Teşekkürler!
WiredEarp

1
2017 sürümünde, örneğin 1 gibi bir değer olduğunda ve geri tuşuna bastığınızda, 120 dediyseniz ve geri üç kez vurursanız, 1 ile kaldığımızda yok sayılır.
Karen Payne

1
ValidatingTextbox'ınız bir süredir gördüğüm en iyi uygulama. Basit ve etkili. Teşekkürler!
Samuel

19

Validated / Validating olayları tam olarak bunun için tasarlanmıştır.

İşte konu hakkındaki MSDN makalesi: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.validating.aspx

TL; DR sürümü: Validating olayında .Text özelliğini kontrol edin e.Cancel=Trueve veri geçersiz olduğunda ayarlayın .

E.Cancel = True ayarladığınızda, kullanıcı alandan ayrılamaz, ancak bir şeylerin yanlış olduğuna dair bir tür geri bildirimde bulunmanız gerekir. Bir sorunu belirtmek için kutunun arka plan rengini açık kırmızı olarak değiştiririm. SystemColors.WindowDoğrulama iyi bir değerle çağrıldığında tekrar ayarlandığından emin olun .


1
Çok API-deyimsel bir yaklaşımdan bahsettiği için +1. Windows Forms için nispeten yeniyim ve oldukça işlevsel ve MSDN belgelerinin bir ormanı, bu yüzden de belirli bir doc pointer için teşekkürler Validating. <nitpick>OP, geçersiz kılınan bir karakterin hemen reddedilmesinin / gösterilmesinin ideal olduğunu belirtiyor, ancak Validatingbu odaklanmanın yürürlüğe girmeden önce başka bir forma / kontrole taşınmasını gerektiriyor gibi görünüyor. </nitpick>Yine de, bu harika bir yaklaşımdır ve daha genel bir durumda her zaman dikkate değer.
William

13

Bir MaskedTextBox'ı deneyin . Basit bir maske formatı gerektirir, böylece girişi sayılarla, tarihlerle veya herhangi bir şeyle sınırlayabilirsiniz.


2
Özellikle MaskedTextBox kullanmak istemiyorum. İzin verdikleri biçimler çok sınırlayıcı olabilir. Bu dava için çalışıyorlar ama daha genel bir şey yapmak istiyorum.
Mykroft

12

TextChangedEtkinliği kullanabilirsiniz

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

Kullanırsanız iyi çalışması gerektiği anlaşılıyor Undo(), ancak bir StackOverflowException.
Drew Chapin

TextChanged özelliğinin geri almak istediğiniz rutinin bir parçası olduğu anlaşılıyor (). Tüm pencere için değişken var ve kullanıyorum public int txtBoxValueve tryParse işe yaramazsa, bentxtBox.Text = txtBoxValue.ToString();
L Zeda

8

Bu yararlı olabilir. Uygun ondalık noktaları ve önceki artı veya eksi işaretlerini içeren "gerçek" sayısal değerlere izin verir. İlgili KeyPress etkinliği içinden arayın.

       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

Ben WinForms eksik şeyler tamamlamak için bileşenlerin bir koleksiyon üzerinde çalışıyorum, işte burada: Gelişmiş Formlar

Özellikle bu bir Regex TextBox sınıfıdır

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

Sadece bir şey eklemek myNumbericTextBox.RegexString = "^(\\d+|)$";yeterlidir.


5

Sadece bir NumericUpDownkontrol kullanın ve bu çirkin yukarı aşağı düğmelerin görünürlüğünü ayarlayın false.

numericUpDown1.Controls[0].Visible = false;

NumericUpDown aslında bir 'döndürme kutusu' (yukarı aşağı düğmeler), bir metin kutusu ve hepsini doğrulamak ve kandırmak için bazı kodlar içeren bir kontroller topluluğudur.

İşaretleme:

YourNumericUpDown.Controls[0].visible = false 

alttaki kodu etkin tutarken düğmeleri gizler.

Açık bir çözüm olmasa da basit ve etkilidir. .Controls[1]bunu yapmak isterseniz metin kutusu bölümünü gizler.


Kabul edilen cevap, yukarı aşağı düğmelerinin nasıl kaldırılacağı hakkında herhangi bir bilgi içermiyordu, nasıl etkinleştirileceği veya devre dışı bırakılacağı insan tarafından okunabilir arabirimler olmadığından nasıl yapılacağı açık değildir. NumericUpDown aslında bir metin kutusu ve bir "döndürme kutusu" (yukarı aşağı düğmeleri) ve bazı kod işleme giriş doğrulaması içeren bir kontrol koleksiyonudur.
user2163234

4

CodePlex üzerinde bunun için bir şey yaptım .

TextChanged olayını keserek çalışır. Sonuç iyi bir sayı ise saklanır. Yanlış bir şey varsa, son iyi değer geri yüklenir. Kaynak burada yayınlamak için biraz fazla, ama burada bu mantığın çekirdeğini işleyen sınıfa bir bağlantı var .


4

bu kodu metin kutusunda kullanmanız yeterlidir:

private void textBox1_TextChanged(object sender, EventArgs e)
{

    double parsedValue;

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

4

Metin kutusu tanımına sahip web sayfamıza onkeypressyalnızca sayı kabul etmek için bir etkinlik ekleyebiliriz . Herhangi bir mesaj göstermez, ancak yanlış giriş yapmanızı önler. Benim için çalıştı, kullanıcı sayı dışında bir şey giremedi.

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


2

KeyDown olayında hallederdim.

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

2
"Backspace", "Delete", "Arrow-Key-Left", "Arrow-Key-Right", Kopyala ve Yapıştır, Numpad tarafından girilen basamaklar (!
Digit

Sadece bunun gibi birkaç test daha ekleyin: 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;
        }
    }
}

dene bu çok basit


2

WinForm'da Giriş işlemeye göz atın

Ben TextC ProcessCmdKey ve OnKeyPress olayları kullanan benim çözüm gönderdi. Yorumlar, tuş basışını doğrulamak ve uygun şekilde engellemek / izin vermek için Regex'in nasıl kullanılacağını gösterir.


2

Merhaba, metin kutusunun textchanged olayında böyle bir şey yapabilirsiniz.

işte bir 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;
    }

Teşekkürler, çok faydalı.
Kiran RS

2

Bu soruya verilen mevcut cevapların çoğu giriş metnini manuel olarak ayrıştırıyor gibi görünüyor. Belirli bir yerleşik sayısal tür (örneğin intveya double) arıyorsanız , neden işi yalnızca bu türün TryParseyöntemine devretmiyoruz ? Örneğin:

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

Daha genel ancak yine de Visual Studio Tasarımcısı ile uyumlu bir şey istiyorsanız:

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

Ve son olarak, tamamen genel bir şey istiyorsanız ve Tasarımcı desteği ile ilgilenmiyorsanız:

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

Negatif sayılar da dahil olmak üzere hem tamsayıların hem de kayan sayıların kabul edilmesi gerekir.

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

Bu benim yaklaşımım:

  1. linq kullanarak (filtreyi değiştirmek kolaydır)
  2. kanıt kodunu kopyala / yapıştır
  3. yasaklanmış bir karaktere bastığınızda şapka pozisyonunu korur
  4. sol sıfırları kabul eder
  5. ve herhangi bir boyut numarası

    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'nin cevabında açıklanan yaklaşımı kullanarak daha genel bir çözüm yarattım:

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

Tüm önemsiz doğrulama davranışlarını içeren "ValidatedTextBox". Yapılması gereken tek şey bu sınıftan miras almak ve "IsValid" yöntemini gereken doğrulama mantığıyla geçersiz kılmaktır. Örneğin, bu sınıfı kullanarak, yalnızca belirli normal ifadeyle eşleşen dizeleri kabul edecek "RegexedTextBox" oluşturmak mümkündür:

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

Bundan sonra, "RegexedTextBox" sınıfından devralma ile kolayca "PositiveNumberTextBox" ve "PositiveFloatingPointNumberTextBox" kontrolleri oluşturabiliriz:

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

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

1

Ölüleri uyandırdığım için üzgünüm, ama birisinin bunu ileride başvurmak için yararlı bulabileceğini düşündüm.

İşte böyle idare ediyorum. Kayan nokta sayılarını işler, ancak tamsayılar için kolayca değiştirilebilir.

Temel olarak yalnızca 0 - 9 ve tuşlarına basabilirsiniz .

Tarihinden önce yalnızca bir 0 olabilir .

Diğer tüm karakterler yok sayılır ve imleç konumu korunur.

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

İşte hızlı değiştirilmiş int sürümü:

    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
Bu çözüm tekerleği uyarılarla yeniden keşfediyor. Örneğin yerelleştirme.
Julien Guertault

1

Bu kopyalama ve yapıştırma, sürükle ve bırak, tuş aşağı, taşma önler ve oldukça basit ile çalışır

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

Bir kullanıcının geçersiz bir metni a TextBox.

Bunu kısıtlamak istiyorsanız, aşağıdaki kodu izleyin:

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

Ayrıca metin kutusunda sadece sayıları kontrol etmek için en iyi yolu arıyordum ve keypress ile sorun sağ tıklama veya pano tarafından kopyala yapıştırmayı desteklemiyordu, bu yüzden imleç metin alanını terk ettiğinde doğrulayan bu kodla geldi ve ayrıca kontrol etti boş alan. (newguy'un uyarlanmış versiyonu)

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 bir etkinliğin kullanması için gerçekten kötü bir seçim gibi görünüyor.
LarsTech

@LarsTech metin değiştiğini bile düşündüm bile kullanıcı hata fark ve düzeltmeye çalışın daha iyi çalışacağını düşündüm bile önce hata mesaj kutusu neden olabilir. Sizce bu dava için en iyi olay nedir?
Alston Antony

@AlstonAntony geç yorum, biliyorum. Ancak sağ tıklamayla etkinleşen basit bir tıklama etkinliği yeterli olmaz mı?
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 çözüm

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'den başka bir çözüm

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

kaynak http://msdn.microsoft.com/tr-tr/library/system.windows.forms.control.keypress(v=VS.90).aspx

3) MaskedTextBox'ı kullanarak: http://msdn.microsoft.com/en-us/library/system.windows.forms.maskedtextbox.aspx


0

Düğme tıklatmasında metin kutusunun metnini döngü için kontrol edebilirsiniz:

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

Daha basit cevap:

_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());
};
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.