Grafikus C# – Windows Forms tanfolyam › 13.5 lecke

Windows Forms · 13.5 lecke · bevitel-ellenőrzés

Üres, hibás és szélsőértékes bevitelek

A felhasználó mindent beírhat: üres mezőt, betűt szám helyett, negatív életkort, ezer karakteres nevet, vesszőt ott, ahol pontot vártál. A program akkor jó, ha ezekre is érthetően reagál: nem omlik össze, nem számol ostobaságot, és megmondja, mit javítson a felhasználó. A bevitel-ellenőrzés három kérdés: mit fogadok el (szabályok), mikor ellenőrzök (gépeléskor, mezőelhagyáskor, mentéskor) és hogyan jelzem a hibát (ErrorProvider, üzenet). Ebben a leckében megtanulod a bevitel-típusokat és a szélsőértékeket, a vezérlők beépített védelmét, a kultúra miatti tizedesvessző-csapdát, a Validating eseményt és a határérték-tesztelést.

  • kb. 100 perc
  • közepes szint
  • bevitel-ellenőrzés
Anime stílusú fiú és lány egy C# programozási feladatot beszél meg

A lecke végére

  • megkülönbözteted a bevitel hibafajtáit (üres, formátum, tartomány, szélsőérték);
  • a vezérlők beépített korlátozásait használod (NumericUpDown, MaxLength, DropDownList, DateTimePicker, MaskedTextBox);
  • helyesen olvasol számot (TryParse, kultúra, decimal pénznél, túlcsordulás);
  • használod a Validating eseményt, az ErrorProvidert és a ValidateChildren()-t;
  • az ellenőrzést központi, tesztelhető osztályba teszed;
  • határérték-teszteléssel ellenőrzöd a mezőket.

Mielőtt elkezded

Ehhez a leckéhez a 13.4 lecke (TryParse, kivételek), a 6. fejezet (vezérlők) és a 12.7 lecke (logika külön osztályban) szükséges.

13.4 try, catch, finally →

A bevitel hibafajtái és a szélsőértékek

FajtaPéldaEllenőrzés
Üres"", " " (csak szóköz)string.IsNullOrWhiteSpace(s)
Rossz formátum"abc" számnál, "12.5.3", hibás e-mailTryParse, szabály/Regex
Tartományon kívüliéletkor −5 vagy 400, 2 mp-es hatalmas dátumalsó és felső határ összehasonlítása
Szélsőérték0, −1, 1, legnagyobb és legkisebb megengedett, int.MaxValuehatárérték-tesztelés
Túl hosszú10 000 karakteres névMaxLength, Length ellenőrzés
Különleges karakterekékezetek, emoji, <, ", \, fájlnévben tiltott jelekkarakterhalmaz ellenőrzés, Path.GetInvalidFileNameChars()
Logikailag ellentmondókezdés után lévő befejezés, jelszó ≠ megerősítésmezők közti ellenőrzés
Soha ne bízz a bevitelbenMinden, amit a felhasználó ad (és fájlból, hálózatról jön), megbízhatatlan, amíg le nem ellenőrizted. A kód ne feltételezze, hogy „úgyis számot ír be”.
Engedj, nem tiltj (pozitív lista)Pontosan fogalmazd meg, mi az érvényes (életkor: egész, 10–120), és ami nem felel meg, azt utasítsd el. Ez biztonságosabb, mint a „tiltott dolgok listája”, amelyből mindig kimarad valami.
Szélsőértékek: ahol a hibák élnekA hibák többsége a határokon van: 0, 1, a legnagyobb, a legnagyobb + 1, üres, nagyon hosszú. A teszt (13.8 lecke) mindig a határokra figyel: határérték-elemzés.
Hol ellenőrizz?A felületen azonnal (jó visszajelzés), és a modellben is (a végső védelem, amely felület nélkül is áll: 12.6 lecke). A felületi ellenőrzés kényelem, a modellbeli a biztonság.

Jósolj!

Egy mező életkorát 10 és 120 között fogadod el. Melyik 8 értéket tesztelnéd az ellenőrzéshez?

Jóslat ellenőrzése

Határérték-elemzéssel: 9 (érvénytelen, a határ alatt), 10 (érvényes, alsó határ), 11, 119, 120 (érvényes, felső határ), 121 (érvénytelen), plusz üres és "abc". A hibák 10-nél és 120-nál, illetve a határ túloldalán szoktak lenni (< helyett <=).

A vezérlők beépített védelme

VezérlőBeállításMit véd?
NumericUpDownMinimum, Maximum, DecimalPlacesCsak szám, a tartományon belül (beírt értéket is a határra szorítja).
TextBoxMaxLength, CharacterCasingHosszkorlát, nagybetűs/kisbetűs kényszerítés.
ComboBoxDropDownStyle = DropDownListCsak a felsorolt értékek (nincs szabad gépelés).
DateTimePickerMinDate, MaxDate, FormatCsak érvényes dátum, a határok közt.
MaskedTextBoxMask (pl. 00/00/0000, (00) 000-0000)Rögzített formátum, számjegyek.
CheckBox, RadioButton, TrackBar—Eleve korlátozott lehetőségek.
Form1.cs (Load)C#
private void Form1_Load(object sender, EventArgs e)
{
nudKor.Minimum = 10;
nudKor.Maximum = 120;
nudKor.Value = 16;

txtNev.MaxLength = 60;

dtpSzulet.MinDate = new DateTime(1900, 1, 1);
dtpSzulet.MaxDate = DateTime.Today;

cmbOrszag.DropDownStyle = ComboBoxStyle.DropDownList;
}

// szűrés gépeléskor: csak számjegyek (a vágólapról beillesztést ez NEM fogja meg!)
private void txtIrsz_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar)) { e.Handled = true; } // a billentyűt elnyeli
}
A vezérlő megelőzA beépített korlát a legjobb: a hibás érték be sem írható. A NumericUpDown a számok, a DateTimePicker a dátumok kényelmes és biztonságos beviteli módja: sokkal jobb, mint egy TextBox és utólagos ellenőrzés.
De nem elégA KeyPress-szűrő a vágólapról beillesztett szöveget nem fogja meg (Ctrl+V), a NumericUpDown.Text pedig a szerkesztés közben még nem érvényes érték lehet. A végső ellenőrzés mindig a mentés/küldés előtt kell.
Maszkolt mezőA MaskedTextBox kényelmes, de a Text értéke tartalmazza a maszk jeleit ((06) 123-4567): olvasd a MaskCompleted és a TextMaskFormat beállítást. A telefonszám formátumai országonként sokfélék: ne legyél túl szigorú.
AkadálymentességAz ellenőrzés üzenete legyen szöveges és a mezőhöz kötött (ErrorProvider), ne csak szín. A Label + AccessibleName megmondja, mit vár a mező (13.9 lecke után a használhatóságnál bővül).

Jósolj!

A NumericUpDown Maximum értéke 120. A felhasználó beírja, hogy 500, és rögtön a gombra kattint, anélkül, hogy a mezőt elhagyta volna. Mit olvasol a Value-ból?

Jóslat ellenőrzése

Nem mindig azt, amit gondolsz: a NumericUpDown a beírt szöveget csak a mező elhagyásakor (vagy Enternél) értelmezi, és akkor a határra szorítja (120). A Text viszont a beírt 500-at mutatja. Mentés előtt hívd a nudKor.ValidateText() vagy a ValidateChildren() metódust, vagy a vezérlő Value értéke helyett ellenőrizd a Textet is.

Számok olvasása: kultúra, túlcsordulás, decimal

Form1.cs (using System.Globalization;)C#
// A KULTÚRA számít: magyar gépen a tizedeselválasztó a VESSZŐ
double d;
double.TryParse("3,14", out d); // hu-HU gépen: 3,14 ✓; en-US gépen: ✗ (vagy 314!)
double.TryParse("3.14", out d); // hu-HU gépen: ✗ vagy 314 (a pont ezres-elválasztó lehet!)

// tudatos választás: a felhasználó bevitele a SAJÁT kultúrájában (CurrentCulture, ez az alapértelmezés)...
bool ok = double.TryParse(txtSzam.Text, NumberStyles.Float, CultureInfo.CurrentCulture, out d);

// ...a fájlban/protokollban tárolt szám viszont mindig InvariantCulture (pont), hogy gépfüggetlen legyen
string tarolt = d.ToString(CultureInfo.InvariantCulture);
double.TryParse(tarolt, NumberStyles.Float, CultureInfo.InvariantCulture, out d);

// TÚLCSORDULÁS
int n;
bool jo = int.TryParse("3000000000", out n); // false: nem fér az int-be (max ≈ 2,1 milliárd)

int a = int.MaxValue;
int b = a + 1; // -2147483648: csendes körbefordulás, NINCS kivétel!
int c = checked(a + 1); // OverflowException: így jelez

// PÉNZ: decimal, nem double (a double bináris tört: 0,1 + 0,2 ≠ 0,3)
decimal ar;
decimal.TryParse(txtAr.Text, NumberStyles.Number, CultureInfo.CurrentCulture, out ar);
A vessző-pont csapdaA TryParse alapból a gép kultúráját használja. Magyar gépen "3.14" hibás vagy más értelmű lehet (ezres elválasztó), angolon a "3,14" az. A programod más gépen máshogy viselkedhet! Döntsd el: a felhasználói bevitel a felhasználó kultúrája szerint; a tárolt adat InvariantCulture.
Útmutató a felhasználónakHa tizedes bevitelt várhatsz, írd a mező mellé a formátumot (pl. 3,14), és fogadd el a pontot is, ha egyértelmű (text.Replace('.', ',') egy ismert kultúrában: óvatosan, ezres elválasztóval ütközhet).
TúlcsordulásAz int aritmetika alapból nem jelez: a int.MaxValue + 1 csendben negatív lesz. A checked kulcsszó (vagy a projekt Check for arithmetic overflow beállítása) OverflowException-t dob. Nagy számoknál long, decimal, BigInteger.
double és decimalA double kerekítési hibát hordoz (0.1 + 0.2 = 0.30000000000000004). Pénzhez és pontos tizedeshez decimal. A NaN és a végtelen is érvényes double: double.IsNaN, IsInfinity ellenőrzés szükséges, ha a bevitel lehet ilyen.

Jósolj!

Magyar nyelvű gépen a felhasználó beírja, hogy 1.234, és a program double.TryParse-szel olvassa. Szerinted mit kapsz?

Jóslat ellenőrzése

Gépenként változhat: a NumberStyles.Float (alapértelmezett double-nél) nem engedi az ezres-elválasztót, ezért a 1.234 magyar kultúrában általában hibás (false); de NumberStyles.Number mellett 1234 lehet. Ezért mindig add meg a NumberStyles és a CultureInfo paramétert, és tesztelj mindkét kultúrában.

Validating, ErrorProvider, ValidateChildren

Form1.csC#
// Validating: akkor fut, amikor a mező ELHAGYJA a fókuszt (és a CausesValidation igaz)
private void txtNev_Validating(object sender, CancelEventArgs e)
{
string hiba = BevitelEllenorzo.Nev(txtNev.Text); // az ellenőrzés külön osztályban (tesztelhető)

errorProvider1.SetError(txtNev, hiba ?? ""); // a hibaüzenet a mező mellett; az üres szöveg törli a jelet
// e.Cancel = hiba != null; // ha IGAZ, a felhasználó nem hagyhatja el a mezőt (zavaró lehet!)
}

// MENTÉSKOR: minden mezőt ellenőrzünk (a felhasználó átugorhatott mezőket)
private void btnMent_Click(object sender, EventArgs e)
{
if (!this.ValidateChildren()) // az összes vezérlő Validating eseményét lefuttatja
{
tsslUzenet.Text = "Javítsd a jelölt mezőket.";
return;
}

// ... mentés ...
}

// A Mégse gomb ne váltson ki ellenőrzést: CausesValidation = false
ErrorProviderA SetError(vezérlő, szöveg) piros felkiáltójelet tesz a mező mellé, és az egér fölötti szövegben mutatja az üzenetet. Üres szöveg törli a jelzést. A BlinkStyle = NeverBlink kikapcsolja a villogást (akadálymentesség, 6.9 lecke).
Mikor fut a Validating?A mező elhagyásakor. A Validated utána, sikeres ellenőrzés esetén. A e.Cancel = true megakadályozza a mező elhagyását, de ez bosszantó (a felhasználó „be van zárva”): általában csak jelezz, ne tilts.
ValidateChildren()Mentéskor ez az összes vezérlőre lefuttatja a Validating-et. Az eredménye false, ha bármelyik Cancel-t kért. Ha nem használsz e.Cancel-t, a hibákat te gyűjtsd (a központi ellenőrző metódus listát ad).
Központi ellenőrzőHa az ellenőrzés egy osztályban él (BevitelEllenorzo.Nev(...)), akkor a Validating, a mentés és a teszt ugyanazt használja: egyetlen szabály, nincs ellentmondás (12.7 lecke).

Jósolj!

A felhasználó a Név mezőt kihagyja (soha nem kattint bele), és rögtön a Mentés gombra kattint. Lefut-e a txtNev_Validating?

Jóslat ellenőrzése

Nem: a Validating csak a fókusz elhagyásakor fut, a kihagyott mező sosem kapta meg a fókuszt. Ezért kell a ValidateChildren() (vagy a központi ellenőrzés) a mentés gombban: minden mezőt ellenőriz, a kihagyottakat is.

📷 Képernyőkép helye

Mit tegyél ide: a regisztrációs űrlap ErrorProvider jelzésekkel és a határérték-teszt eredményei.Javasolt fájlnév: winforms-13-5-bevitel.webp · Alt szöveg: A regisztrációs űrlap bevitel-ellenőrzéssel

Hibakeresés: te vagy a hibadetektív

Mi a baj, és hogyan javítod?

Gondold végig az okot, és csak utána nyisd le a megoldást.

1. A csak szóközt tartalmazó név átmegy

if (txtNev.Text == "") { /* hiba */ }
Hiba és javítás

A " " nem egyenlő az üres szöveggel. string.IsNullOrWhiteSpace(txtNev.Text).

2. A 120 éves még érvénytelen

if (kor < 10 || kor >= 120) { /* hiba */ }
Hiba és javítás

Határérték-hiba: a felső határ 120 érvényes, ezért kor > 120. Mindig teszteld a határokat (9, 10, 120, 121).

3. A tizedesszám máshogy működik a barátom gépén

double.TryParse(txtAr.Text, out ar);
Hiba és javítás

A kultúra (vessző/pont) gépenként eltér. Add meg a NumberStyles és CultureInfo paramétert, és tárolt adatnál InvariantCulture.

4. A mentés elfogad hibás mezőket

A felhasználó kihagyott egy mezőt, a mentés mégis lefut.

Ok és javítás

Csak a Validating-re hagyatkoztál, amely a kihagyott mezőre nem fut. A mentés előtt ValidateChildren() vagy a központi ellenőrzés mindenre.

5. A felhasználó nem tud kilépni a mezőből

e.Cancel = true;   // a Validating kezelőben, minden hibánál
Hiba és javítás

Az e.Cancel „bezárja” a felhasználót a hibás mezőbe (és a Mégse gomb is tiltott lehet). Jelezz az ErrorProviderrel, és a CausesValidation = false a Mégse gombon.

6. Az int összeadás csendben negatív lesz

int osszeg = db1 + db2;   // mindkettő nagy
Hiba és javítás

Túlcsordulás. checked(db1 + db2) vagy long használata; az érték tartományát korlátozd a bevitelnél.

Mini projekt: regisztrációs űrlap központi ellenőrzéssel

Készíts regisztrációs űrlapot, amelynek minden mezőjét központi, tesztelhető osztály ellenőrzi:

  1. Mezők: txtNev (kötelező, 2–60 karakter), txtKor (TextBox, egész, 10–120), txtEmail (kötelező, egyszerű szabály), txtTelefon (opcionális, ha megadott: 9–15 számjegy, a +, szóköz és kötőjel megengedett), dtpSzulet (nem lehet jövőbeli), txtOsszeg (decimal, 0–1 000 000, vessző), txtFajl (érvényes fájlnév); Mentés, Mégse; ErrorProvider; állapotsor.
  2. BevitelEllenorzo osztály (statikus, string hibaüzenetet ad, null ha jó): Nev, Kor, Email, Telefon, Szuletes, Osszeg, Fajlnev; a felület szöveget ad át, nem vezérlőt.
  3. Validating: minden mezőn a megfelelő ellenőrző hívása, ErrorProvider.SetError; e.Cancel nincs.
  4. Mentés: a ValidateChildren() mellett a központi OsszesHiba() metódus gyűjti az összes hibát; a hibák felsorolása az állapotsorban (3 hiba: Név, E-mail, Összeg), a fókusz az első hibás mezőre.
  5. Kultúra: a szám és összeg olvasása CurrentCulture szerint, NumberStyles megadásával; a mentett érték (ToString(CultureInfo.InvariantCulture)) a naplóba/fájlba.
  6. Határérték-táblázat: a leírásban táblázat minden mezőhöz: üres, alsó határ −1, alsó határ, felső határ, felső határ +1, szélsőséges (nagyon hosszú, speciális karakter): a vártnak és a kapottnak megfelelően.
  7. Tesztek: a BevitelEllenorzo automatikus tesztjei (legalább 20 ellenőrzés) a Debug kimenetbe, en-US és hu-HU kultúrával is (CultureInfo.CurrentCulture ideiglenes cseréje).
  8. Akadálymentesség: a hibaüzenet szöveges; ErrorProvider.BlinkStyle = NeverBlink; a mező AccessibleName; Enter a mentés (AcceptButton), Esc a mégse.
  9. Teszteld: minden határérték, üres űrlap mentése, csak szóközök, 1000 karakteres név, 1.234 és 1,234 az összegnél, jövőbeli születési dátum, fájlnév tiltott jelekkel (a/b, CON).
Megoldás megnyitása (próbáld ki előbb önállóan!)
BevitelEllenorzo.cs és Form1.cs (using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text.RegularExpressions;)C#
public static class BevitelEllenorzo
{
public static string Nev(string s)
{
if (string.IsNullOrWhiteSpace(s)) { return "A név kötelező."; }

s = s.Trim();

if (s.Length < 2) { return "A név legalább 2 karakter."; }
if (s.Length > 60) { return "A név legfeljebb 60 karakter."; }

return null;
}

public static string Kor(string s)
{
if (string.IsNullOrWhiteSpace(s)) { return "Az életkor kötelező."; }

int kor;

if (!int.TryParse(s.Trim(), NumberStyles.Integer, CultureInfo.CurrentCulture, out kor)) { return "Az életkor egész szám kell legyen."; }
if (kor < 10 || kor > 120) { return "Az életkor 10 és 120 között lehet."; }

return null;
}

public static string Email(string s)
{
if (string.IsNullOrWhiteSpace(s)) { return "Az e-mail kötelező."; }

s = s.Trim();

if (s.Length > 120) { return "Az e-mail túl hosszú."; }

int at = s.IndexOf('@');

if (at <= 0 || at != s.LastIndexOf('@') || s.IndexOf('.', at) < at + 2 || s.EndsWith(".") || s.Contains(" ")) { return "Az e-mail cím hibás (pl. nev@pelda.hu)."; }

return null;
}

public static string Telefon(string s)
{
if (string.IsNullOrWhiteSpace(s)) { return null; } // opcionális

if (!Regex.IsMatch(s.Trim(), @"^\+?[0-9 \-]+$")) { return "A telefonszám csak számjegyet, +, szóközt és kötőjelet tartalmazhat."; }

int db = s.Count(char.IsDigit);

if (db < 9 || db > 15) { return "A telefonszám 9–15 számjegy legyen."; }

return null;
}

public static string Szuletes(DateTime d)
{
if (d.Date > DateTime.Today) { return "A születési dátum nem lehet jövőbeli."; }
if (d.Year < 1900) { return "A születési dátum 1900 utáni legyen."; }

return null;
}

public static string Osszeg(string s)
{
if (string.IsNullOrWhiteSpace(s)) { return "Az összeg kötelező."; }

decimal ar;

if (!decimal.TryParse(s.Trim(), NumberStyles.Number, CultureInfo.CurrentCulture, out ar)) { return "Az összeg szám kell legyen (tizedesjel: " + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + ")."; }
if (ar < 0 || ar > 1000000m) { return "Az összeg 0 és 1 000 000 között lehet."; }

return null;
}

public static string Fajlnev(string s)
{
if (string.IsNullOrWhiteSpace(s)) { return "A fájlnév kötelező."; }

s = s.Trim();

if (s.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) { return "A fájlnév tiltott karaktert tartalmaz."; }
if (s.Length > 100) { return "A fájlnév legfeljebb 100 karakter."; }

string alap = Path.GetFileNameWithoutExtension(s).ToUpperInvariant();

if (new[] { "CON", "PRN", "AUX", "NUL", "COM1", "LPT1" }.Contains(alap)) { return "Ez a név Windowson fenntartott."; }

return null;
}

public static List<string> OsszesHiba(string nev, string kor, string email, string tel, DateTime szulet, string osszeg, string fajl)
{
List<string> hibak = new List<string>();
string h;

if ((h = Nev(nev)) != null) { hibak.Add("Név: " + h); }
if ((h = Kor(kor)) != null) { hibak.Add("Életkor: " + h); }
if ((h = Email(email)) != null) { hibak.Add("E-mail: " + h); }
if ((h = Telefon(tel)) != null) { hibak.Add("Telefon: " + h); }
if ((h = Szuletes(szulet)) != null) { hibak.Add("Születés: " + h); }
if ((h = Osszeg(osszeg)) != null) { hibak.Add("Összeg: " + h); }
if ((h = Fajlnev(fajl)) != null) { hibak.Add("Fájlnév: " + h); }

return hibak;
}
}

// ---- Form1.cs ----
private void Form1_Load(object sender, EventArgs e)
{
errorProvider1.BlinkStyle = ErrorBlinkStyle.NeverBlink;
dtpSzulet.MaxDate = DateTime.Today;
btnMegse.CausesValidation = false;
}

private void txtNev_Validating(object s, CancelEventArgs e) { errorProvider1.SetError(txtNev, BevitelEllenorzo.Nev(txtNev.Text) ?? ""); }
private void txtKor_Validating(object s, CancelEventArgs e) { errorProvider1.SetError(txtKor, BevitelEllenorzo.Kor(txtKor.Text) ?? ""); }
private void txtEmail_Validating(object s, CancelEventArgs e) { errorProvider1.SetError(txtEmail, BevitelEllenorzo.Email(txtEmail.Text) ?? ""); }
private void txtTelefon_Validating(object s, CancelEventArgs e) { errorProvider1.SetError(txtTelefon, BevitelEllenorzo.Telefon(txtTelefon.Text) ?? ""); }
private void txtOsszeg_Validating(object s, CancelEventArgs e) { errorProvider1.SetError(txtOsszeg, BevitelEllenorzo.Osszeg(txtOsszeg.Text) ?? ""); }
private void txtFajl_Validating(object s, CancelEventArgs e) { errorProvider1.SetError(txtFajl, BevitelEllenorzo.Fajlnev(txtFajl.Text) ?? ""); }

private void btnMent_Click(object sender, EventArgs e)
{
List<string> hibak = BevitelEllenorzo.OsszesHiba(txtNev.Text, txtKor.Text, txtEmail.Text, txtTelefon.Text, dtpSzulet.Value, txtOsszeg.Text, txtFajl.Text);

ValidateChildren(); // a jelzések (ErrorProvider) frissítése a kihagyott mezőkre is

if (hibak.Count > 0)
{
tsslUzenet.Text = hibak.Count + " hiba: " + string.Join("; ", hibak.Take(3)) + (hibak.Count > 3 ? "..." : "");

// a fókusz az első hibás mezőre
if (BevitelEllenorzo.Nev(txtNev.Text) != null) { txtNev.Focus(); }
else if (BevitelEllenorzo.Kor(txtKor.Text) != null) { txtKor.Focus(); }
else if (BevitelEllenorzo.Email(txtEmail.Text) != null) { txtEmail.Focus(); }

return;
}

decimal osszeg = decimal.Parse(txtOsszeg.Text.Trim(), NumberStyles.Number, CultureInfo.CurrentCulture);

lstEredmeny.Items.Add(txtNev.Text.Trim() + "; " + txtKor.Text.Trim() + "; " + osszeg.ToString(CultureInfo.InvariantCulture)); // tárolt forma: pont
tsslUzenet.Text = "Mentve.";
}
📷 Képernyőkép helye

Mit tegyél ide: a kész regisztrációs űrlap több hibás mezővel és a hibák összegzésével.Javasolt fájlnév: winforms-13-5-kesz.webp · Alt szöveg: A kész regisztrációs űrlap

Három önálló gyakorlófeladat

Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.

1. Jelszóellenőrző

Írj ellenőrzőt: legalább 8 karakter, kis- és nagybetű, számjegy; a megerősítéssel egyeznie kell. Milyen határeseteket tesztelsz?

Egy lehetséges megoldás

Pontosan 7 és 8 karakter, csak kisbetű, csak nagybetű, nincs számjegy, üres, szóközöket tartalmazó, eltérő megerősítés, nagyon hosszú. A hibaüzenet mondja meg, mi hiányzik (nem csak „érvénytelen”).

2. Dátumintervallum

Két DateTimePicker (kezdés, befejezés): hogyan ellenőrzöd, hogy a befejezés nem előbbi?

Egy lehetséges megoldás

Mezők közti ellenőrzés: veg < kezdes hibaüzenet a végdátum mezőnél; mindkét mező Validating-jében (és mentéskor) lefuttatod; az azonos nap érvényes.

3. Tesztkészlet

Írj tesztet a BevitelEllenorzo.Kor metódushoz (9, 10, 120, 121, üres, "abc", " 15 ", "1e2").

Egy lehetséges megoldás

A " 15 " érvényes (a Trim miatt); a "1e2" az NumberStyles.Integer mellett hibás (nincs kitevő). A teszt a vártat (hibaüzenet vagy null) hasonlítja: a döntést a szabályból, nem a programból vezesd le.

Gyakorlótár: 6 további feladat

Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.

Alap szint

1. Üres vagy szóköz?

Melyik metódus kezeli a csak szóközöket is?

Megoldás megnyitása

string.IsNullOrWhiteSpace (az IsNullOrEmpty a szóközöket nem).

2. Vezérlő választása

Melyik vezérlő véd jobban egy 1–10 közötti pontszámnál: TextBox vagy NumericUpDown?

Megoldás megnyitása

A NumericUpDown (Minimum/Maximum): a hibás érték be sem írható; a végső ellenőrzés mentéskor mégis kell.

Közepes szint

3. Határértékek

Egy mező 1–100 közötti egész: sorold fel a határérték-teszteket.

Megoldás megnyitása

0, 1, 2, 99, 100, 101; plusz üres, szöveg, tizedes (1,5), nagyon nagy szám (int.MaxValue + 1 szöveg).

4. Mikor fut a Validating?

Fókuszvesztéskor vagy gépeléskor?

Megoldás megnyitása

Fókuszvesztéskor (a mező elhagyásakor). Gépelés közbeni ellenőrzéshez a TextChanged esemény kell.

Kihívás szint

5. Kultúra-teszt

Hogyan teszteled egy hu-HU gépen az en-US viselkedést?

Megoldás megnyitása

A tesztben ideiglenesen cseréled a CultureInfo.CurrentCulture értékét (new CultureInfo("en-US")), futtatod az ellenőrzést, és visszaállítod (try–finally).

6. Szerveroldali ellenőrzés

Miért kell a modellben is ellenőrizni, ha a felület már ellenőrzött?

Megoldás megnyitása

A modellnek más forrásból (fájl, hálózat, másik felület) is kaphat adatot, és a felületi ellenőrzés kihagyható; a modell az utolsó védelem.

Gyors önellenőrzés

Válaszolj fejben, és csak utána nyisd le a választ.

1. Mik a bevitel hibafajtái?

Üres, rossz formátum, tartományon kívüli, szélsőérték, túl hosszú, különleges karakter, ellentmondó.

2. Mi a határérték-elemzés?

A határokon és azok két oldalán tesztelsz (alsó −1, alsó, felső, felső +1).

3. Mi a kultúra-csapda?

A tizedesjel (vessző/pont) és az ezres-elválasztó gépenként eltér: add meg a CultureInfot és NumberStylest.

4. Mire jó a ValidateChildren?

Az összes vezérlő ellenőrzését lefuttatja (a kihagyott mezőket is).

5. Mit tesz az ErrorProvider?

Hibajelet és üzenetet tesz a mező mellé.

6. Double vagy decimal pénzhez?

decimal: pontos tizedes; a double kerekítési hibát hordoz.

7. Miért központi az ellenőrzés?

Egy szabály él, amelyet a felület, a mentés és a teszt is használ.

Mit tudsz már?

  • Felismered a bevitel hibafajtáit és a szélsőértékeket.
  • A vezérlők beépített korlátait és az ErrorProvidert használod.
  • Helyesen olvasol számot kultúrától függetlenül, és kezeled a túlcsordulást.
  • Központi, tesztelhető ellenőrzést építesz, és határérték-teszteléssel ellenőrzöd.

Következő lecke: Fájlkezelési és adatbázis-kivételek

A környezeti hibák kezelése: hiányzó fájl, jogosultság, zárolt fájl, kapcsolati hiba, és a biztonságos erőforrás-használat.