IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Mezi 13:00 až cca 16:00 proběhne odstávka sítě z důvodu aktualizace. Web bude po celou dobu nedostupný.
Avatar
Michaal.K
Člen
Avatar
Michaal.K:22.2.2017 9:54

Ahoj,

mám problém s testováním čísla vloženého přes textBox. Zatím jsem to udělal tak, že odchytím událost TextBoxKeyPress a vní testuji co zadá uživatel. Povolil jsem jen vkládání čísel, desetinné čárky a backspace:

void TextBoxLimitABKeyPress(object sender, KeyPressEventArgs e)
{
        char insertedChar = e.KeyChar;
        if ((insertedChar == 44) && (textBoxLimitAB.Text.IndexOf(',') != -1))
        {
                e.Handled = true;
                return;
        }
        if ((!Char.IsDigit(insertedChar)) && (insertedChar != 8) && (insertedChar != 44))
        {
                e.Handled = true;
        }
}

Ale teď bych ještě potřeboval testovat vložené číslo, které je maximálně: 999,99.
Napadlo mě udělat to přes regex a přidat do události podmínku:

if (Char.IsNumber(e.KeyChar) || e.KeyChar==',')
 {
        if (Regex.IsMatch(textBoxLimitAB.Text, "^\\d*\\,\\d{2}$"))
                e.Handled=true;
 }

bohužel se mi nedaří vytvořit správný regulární výraz.... Nyní jak to mám tak mi to dovolí maximálně dvě desetinná místa, ale pokud zadám např. 1,25 tak pak už mi to nedovolí zadat nic, např 12,25 abych mohl upravit číslo musím ho celé smazat.
Díky za pomoc a rady.

Editováno 22.2.2017 9:56
 
Odpovědět
22.2.2017 9:54
Avatar
Odpovídá na Michaal.K
Michal Štěpánek:22.2.2017 11:13

Trošku postrádám smysl tvého počínání. Kdybys použil NumericUpDown, nemusel bys nic testovat...

Nahoru Odpovědět
22.2.2017 11:13
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Michaal.K
Člen
Avatar
Odpovídá na Michal Štěpánek
Michaal.K:22.2.2017 12:26

U numericUpDown jsou postraně šipky a ty já tam nechci. A nevím jestli jdou nějak zřušit. A hlavně u numericUpDown mohu zadat jakékoliv číslo a až když stisknu enter (tab...) tak to teprve vyhodnotí a vloží maximální číslo. Já jsem to chtěl udělat testování již při zadávání proto událost keypress a textbox.
Pokud by to šlo lépe udělat přes numericUpDown napiš mi prosím jak.
Díky

Edit: tak skrývání šipek u numericUpDown jsem už pořešil:

numericUpDown1.Controls[0].Hide();
Editováno 22.2.2017 12:28
 
Nahoru Odpovědět
22.2.2017 12:26
Avatar
Odpovídá na Michaal.K
Michal Štěpánek:22.2.2017 13:10

Vzhledem k tomu, že NumUpDown v podstatě nedovolí napsat nic jiného, než číslo, tak není co testovat...

Nahoru Odpovědět
22.2.2017 13:10
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Odpovídá na Michaal.K
Michal Štěpánek:22.2.2017 13:12

Já jsem to chtěl udělat testování již při zadávání proto událost keypress a textbox.

Pokud bys to přeci jen chtěl testovat při zadávání, měla by tam být nějaká událost "textchanged", nebo tak něco a v ní bych kontroloval, jestli je to číslo nebo ne...

Nahoru Odpovědět
22.2.2017 13:12
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
ostrozan
Tvůrce
Avatar
ostrozan:22.2.2017 18:24

tohle ti ošetří že do textBoxu se ti nezapíše nic jiného, než požadované znaky - nemusíš mazat a opravovat

private void textBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
        string characters="0123456789,";
    if (!characters.Contains(e.Text)) e.Handled = true;
}

a tímhle ošetříš max hodnotu

if(float.Parse(TextBox.Text)>999.99) VyhodChybu();
 
Nahoru Odpovědět
22.2.2017 18:24
Avatar
ostrozan
Tvůrce
Avatar
Odpovídá na Michaal.K
ostrozan:22.2.2017 18:32

omlouvám se - přehlédl jsem "form" v titulku - ten PrewiewTextInput je samozřejmě jen ve WPF, ale to druhé platí

 
Nahoru Odpovědět
22.2.2017 18:32
Avatar
HONZ4
Člen
Avatar
Odpovídá na Michaal.K
HONZ4:22.2.2017 23:20
const string supportedchars = "0123456789,\b";
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (0 > supportedchars.IndexOf(e.KeyChar)) e.KeyChar = '\0';
}

private void NecoProved(float f)
{
    Text = f.ToString();
}

private void textBox1_TextChanged(object sender, EventArgs e)
{
    float f;
    if (float.TryParse(textBox1.Text, out f) && f < 1000) NecoProved(f);
    else NecoProved(0);
}
 
Nahoru Odpovědět
22.2.2017 23:20
Avatar
termostat
Člen
Avatar
termostat:27.2.2017 11:19

Se správným regulárním výrazem to jde provést i takto :)
Neřeším validaci při opuštění pole, kdy může na konci zůstat oddělovací čárka, je to jen nástřel :)

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
        if(e.KeyChar != (char)Keys.Back)
        {
                var textBox = (sender as TextBox);
                var newText = textBox.Text.Remove(textBox.SelectionStart, textBox.SelectionLength).Insert(textBox.SelectionStart, e.KeyChar.ToString());
                e.Handled = !Regex.IsMatch(newText, @"^\d*(\,(\d{0,2})?)?$");
        }
}
 
Nahoru Odpovědět
27.2.2017 11:19
Avatar
Michaal.K
Člen
Avatar
Michaal.K:1.3.2017 11:25

Ahoj,
tak jsem se k tomu konečně dostal. Nakonec jsem to vyřešil takto a vypadá, že to funguje tak jak jsem chtěl:

private void textBox3_KeyPress(object sender, KeyPressEventArgs e)
        {
            char insertedChar = e.KeyChar;
            if ((insertedChar == 44) && (textBox3.Text.IndexOf(',') != -1))
            {
                e.Handled = true;
                return;
            }
            if ((!Char.IsDigit(insertedChar)) && (insertedChar != 8) && (insertedChar != 44))
            {
                e.Handled = true;
            }

            if (Char.IsNumber(e.KeyChar))
            {
                float f;
                int positionCursor = textBox3.SelectionStart;
                string newNum = textBox3.Text.Insert(positionCursor, e.KeyChar.ToString());
                if ((float.TryParse(newNum, out f)) && (f > 999.99) || (Regex.IsMatch(newNum, "^\\d*\\,\\d{3}$")))
                {
                    e.Handled = true;
                }

            }

        }

Uživatel nemůže vložit větší číslo než 999,99 a pouze jednu desetinnou čárku a jen čísla. A vše testuji hned při zadávání, takže v textBoxu se větší nebo jiné znaky nezobrazují.
Děkuji všem za pomoc a hlavně inspiraci. Akorát teď nevím komu přiřknout "Akceptované řešení", protože jsem čerpal od všech :-)

 
Nahoru Odpovědět
1.3.2017 11:25
Avatar
HONZ4
Člen
Avatar
Odpovídá na Michaal.K
HONZ4:1.3.2017 17:22

ale takto nemáš ošetřeno vložení textu ze schránky. Doporučuji kombinovat KeyPress s TextChanged, nebo i filtrovat schránku

Editováno 1.3.2017 17:24
 
Nahoru Odpovědět
1.3.2017 17:22
Avatar
HONZ4
Člen
Avatar
HONZ4:1.3.2017 19:02

Ještě navíc, doporučuji zjistit si aktuální NumberDecimal­Separator (taky jsem se na to ve svém příkladu vykašlal).

 
Nahoru Odpovědět
1.3.2017 19:02
Avatar
Michaal.K
Člen
Avatar
Odpovídá na HONZ4
Michaal.K:2.3.2017 10:59

Ahoj, díky za radu na vložení textu ze schránky jsem zapomněl. Zkusím to nějak napravit přes událost TextChanged. Jak filtrovat schránku??
Ještě jsem se tě chtěl zeptat jak si myslel NumberDecimal­Separator vůbec tuto metodu neznám.
Díky

 
Nahoru Odpovědět
2.3.2017 10:59
Avatar
Michaal.K
Člen
Avatar
Michaal.K:2.3.2017 16:22

Tak vkladaní přes ctrl+v nebo kontextové menu jsem vyřešil takto:

private void textBox3_KeyPress(object sender, KeyPressEventArgs e)
{
    char insertedChar = e.KeyChar;
    if ((insertedChar == 44) && (textBox3.Text.IndexOf(',') != -1))
    {
        e.Handled = true;
        return;
    }
    // Testuji zda neni vlozeny znak cislo a zda neni backspace a zda neni carka (',') a zda neni vlozeno ctrl+v, pokud neni ani jedno znak nezobrazuji v textBoxu
    if ((!Char.IsDigit(insertedChar)) && (insertedChar != 8) && (insertedChar != 44) && (insertedChar != 22))
    {
        e.Handled = true;
    }

    if (Char.IsNumber(e.KeyChar))                                                           // Testuji zda je vlozeny znak cislo
    {
        float f;
        int positionCursor = textBox3.SelectionStart;                                       // Zjistim pozici, kde byl vlozen posledni znak
        string newNum = textBox3.Text.Insert(positionCursor, e.KeyChar.ToString());         // Spojim jiz vlozene cislo v textBoxu s nove vlozenym znakem na pozici kurzoru

        if ((float.TryParse(newNum, out f)) && (f > 999.99) || (!Regex.IsMatch(newNum, @"^\d*(\,(\d{0,2})?)?$")))
        {
            e.Handled = true;
        }

    }
}

private void textBox3_TextChanged(object sender, EventArgs e)
{
    string insertedNum = textBox3.Text;
    float f;
    if ((float.TryParse(insertedNum, out f)) && (f > 999.99) || (!Regex.IsMatch(insertedNum, @"^\d*(\,(\d{0,2})?)?$")))
    {
        textBox3.Text = "";
        MessageBox.Show("Muzete vlozit pouze cislo od 0 do 999,99!!");
    }
}

V události KeyPress jsem povolil stisk ctrl+v a pak v události TextChanged znovu testuji vložené číslo.
Zatím to funguje jak má :-)

 
Nahoru Odpovědět
2.3.2017 16:22
Avatar
HONZ4
Člen
Avatar
Odpovídá na Michaal.K
HONZ4:2.3.2017 18:36

regex vůbec neovládám, takže pokud na tom trváš, tak si to budeš muset upravit:

using System;
using System.Windows.Forms;
using System.Globalization;

namespace WindowsFormsApplication17
{
    public partial class Form1 : Form
    {
        const string supportedchars = "0123456789\b";
        //nepřemýšlím nad tim, že by mohl být dec. separ. i řetězec
        readonly char dseparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator[0];

        public Form1()
        {
            InitializeComponent();
        }

        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == dseparator)
            {
                if (textBox1.Text.Length == 0 || textBox1.Text.IndexOf(dseparator) > -1) e.KeyChar = '\0';
            }
            else if (0 > supportedchars.IndexOf(e.KeyChar)) e.KeyChar = '\0';
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            if (textBox1.Text.Length > 0)
            {
                float f;
                if (float.TryParse(textBox1.Text, out f) && f >= 0 && f <= 999.99) NecoProved(f);
                else textBox1.Clear();
            }
        }
        //nějaká metoda, která zpracovává vyhodnocené číslo
        private void NecoProved(float f)
        {
            Text = f.ToString();
        }
    }
}

To filtrování schránky je asi zbytečné, stejně uživatel by uživatel mohl zadat velké číslo např. dodatečným umazáním desetinné čárky. Takže nejlépe bude ošetřit událost TextChanged.

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
 
Nahoru Odpovědět
2.3.2017 18:36
Avatar
Michaal.K
Člen
Avatar
Odpovídá na HONZ4
Michaal.K:8.3.2017 11:15

Díky... Už jsem to úspěšně dořešil.
Děkuji všem za pomoc a hlavně inspiraci.

 
Nahoru Odpovědět
8.3.2017 11:15
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 16 zpráv z 16.