Grafikus C# – Windows Forms tanfolyam › 8.3 lecke Windows Forms · 8.3 lecke · táblázat A DataGridView: oszlopok, sorok és cellák
DataGridView a Windows Forms legerősebb vezérlője: táblázat, amelyben sorokat és oszlopokat jeleníthetsz meg, szerkeszthetsz, rendezhetsz. A 3. fejezetben már használtad adatbázis-adatok megjelenítésére. Most a vezérlőt önmagában ismered meg: kódból adsz hozzá oszlopokat (szöveg, jelölőnégyzet, legördülő lista, gomb), sorokat és cellákat kezelsz, kijelölést olvasol, és az eseményeivel reagálsz a felhasználóra. A legfontosabb csapdák: az új sor és a cellaérték típusa (object).
A lecke végére
- kódból adsz oszlopokat a táblázathoz (
TextBox,CheckBox,ComboBox,Buttonoszlop), és beállítod a megjelenésüket; - sorokat és cellákat kezelsz (
Rows.Add,Cells,RemoveAt), és a cellaértéket típushelyesen olvasod; - a kijelölést (
SelectionMode,SelectedRows,CurrentCell) használod; - reagálsz az eseményekre (
CellValueChanged,CellContentClick,CellFormatting); - tudod, mi az „új sor” (
IsNewRow), és hogyan kerüld anullértékeket; - kezeled a
DataErroreseményt.
Mielőtt elkezded
Ehhez a leckéhez a 3.4 lecke (DataGridView első használata), a 8.2 lecke (kijelölés, Items), az 5.5 lecke (változás-események, jelző) és a 6.2 lecke (Dock, Anchor) szükséges.
Oszlopok
A tábla oszlopait a tervezőben (Edit Columns) vagy kódból adod meg. Az oszlop típusa határozza meg, hogyan jelenik meg és szerkeszthető a cella:
| Oszloptípus | Cella |
|---|---|
DataGridViewTextBoxColumn | Szöveg vagy szám (az alapértelmezés). |
DataGridViewCheckBoxColumn | Jelölőnégyzet (bool érték). |
DataGridViewComboBoxColumn | Legördülő lista (Items vagy DataSource). |
DataGridViewButtonColumn | Gomb a cellában (Text, UseColumnTextForButtonValue). |
DataGridViewImageColumn, DataGridViewLinkColumn | Kép, hivatkozás. |
dgv.AutoGenerateColumns = false;
dgv.Columns.Clear();
DataGridViewTextBoxColumn nev = new DataGridViewTextBoxColumn();
nev.Name = "colNev"; // a kódbeli azonosító
nev.HeaderText = "Név"; // a fejléc szövege
nev.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
nev.FillWeight = 40; // a Fill oszlopok közti arány
dgv.Columns.Add(nev);
DataGridViewTextBoxColumn ar = new DataGridViewTextBoxColumn();
ar.Name = "colAr";
ar.HeaderText = "Ár (Ft)";
ar.DefaultCellStyle.Format = "N0"; // ezres tagolás
ar.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
ar.Width = 100;
dgv.Columns.Add(ar);
DataGridViewCheckBoxColumn kesz = new DataGridViewCheckBoxColumn();
kesz.Name = "colKesz";
kesz.HeaderText = "Kész";
dgv.Columns.Add(kesz);
DataGridViewButtonColumn torol = new DataGridViewButtonColumn();
torol.Name = "colTorol";
torol.HeaderText = "";
torol.Text = "Törlés";
torol.UseColumnTextForButtonValue = true; // minden cellában ez a felirat
dgv.Columns.Add(torol);Name a kódbeli azonosító (dgv.Columns["colAr"]), a HeaderText a felhasználó által látott fejléc. Mindkettőt add meg.Fill az oszlopot a szabad helyre nyújtja (a FillWeight adja az arányt), a AllDirectCells a tartalomhoz igazodik, a None fix szélességű (Width). Egy táblázatban általában egy-két Fill oszlop van.Format (N0, 0.00, d dátum), Alignment, BackColor, ForeColor, Font. A számokat jobbra igazítjuk.false), különben duplázódnak.Jósolj!
A HeaderText értéke "Ár", de a Name nincs megadva, és a kód a dgv.Columns["Ar"] oszlopot kéri. Mi történik?
Jóslat ellenőrzése
A szöveges indexelő a Name alapján keres, és nem a HeaderText szerint: a kódból létrehozott oszlop neve üres, ezért a keresés null értéket ad (vagy kivételt dob a következő hivatkozásnál). Mindig adj Name értéket, és azzal hivatkozz.
Sorok és cellák
// sor hozzáadása: az értékek az oszlopok sorrendjében (a gomboszlop értéke nem kell)
int i = dgv.Rows.Add("Alma", 250, false); // az új sor sorszáma
dgv.Rows.Add("Körte", 320, true);
// cella olvasása és írása: oszlopnév vagy sorszám szerint
object ertek = dgv.Rows[i].Cells["colAr"].Value; // object típusú!
dgv.Rows[i].Cells["colAr"].Value = 300;
// típushelyes olvasás: a Value null vagy más típusú is lehet
int ar;
if (int.TryParse(Convert.ToString(dgv.Rows[i].Cells["colAr"].Value), out ar))
{
// használható az ar
}
// az összes sor bejárása: az „új sor” (üres, beírásra váró) kihagyása
int osszeg = 0;
foreach (DataGridViewRow sor in dgv.Rows)
{
if (sor.IsNewRow)
{
continue;
}
int egyAr;
if (int.TryParse(Convert.ToString(sor.Cells["colAr"].Value), out egyAr))
{
osszeg += egyAr;
}
}
dgv.Rows.RemoveAt(0); // törlés sorszám szerint
dgv.Rows.Clear(); // minden sor törléseobject: lehet szöveg, szám, bool vagy null (üres cella). Ezért nem használunk közvetlen átalakítást ((int)Value), hanem TryParse-t a Convert.ToString eredményével (az null értéket üres szövegre alakítja).AllowUserToAddRows igaz (alap), a tábla alján egy üres „új sor” áll, amelybe a felhasználó beírhat. Ez a sor a Rows gyűjtemény utolsó eleme (IsNewRow = true), a Rows.Count számába is beletartozik, értékei null.Rows.Add(értékek) az új sor sorszámát adja. Sok sor feltöltésénél a SuspendLayout sokat gyorsít, de a DataGridViewnak nincs BeginUpdate párja: az adatkötés (8.4 lecke) gyorsabb.Jósolj!
A táblában három adatsor van, és az AllowUserToAddRows igaz. Mit ad a dgv.Rows.Count, és mi történik, ha ciklusban az összes sor colAr celláját (int) átalakítással olvasod?
Jóslat ellenőrzése
A Rows.Count értéke 4 (a három adatsor és az új sor). Az új sor colAr cellájának értéke null, és az (int)null átalakítás NullReferenceException kivételt dob. Az IsNewRow ellenőrzés és a TryParse véd.
Kijelölés és szerkesztés
| Tulajdonság | Jelentése |
|---|---|
SelectionMode | CellSelect (alap), FullRowSelect (az egész sor), FullColumnSelect, RowHeaderSelect. |
MultiSelect | Több sor/cella egyszerre. |
CurrentCell, CurrentRow | Az aktuális (kurzort tartalmazó) cella és sor. |
SelectedRows, SelectedCells | A kijelölt sorok és cellák gyűjteménye. |
ReadOnly | A tábla, oszlop vagy cella szerkeszthetősége. |
AllowUserToAddRows, AllowUserToDeleteRows | Új sor és a Delete billentyűvel törlés engedélyezése. |
RowHeadersVisible | A sorfejlécek (bal oszlop) látszanak-e. |
dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect; // sorkijelölés: kényelmesebb törléshez
dgv.MultiSelect = true;
dgv.AllowUserToAddRows = false; // nincs üres „új sor”: egyszerűbb a bejárás
dgv.Columns["colNev"].ReadOnly = true;
dgv.RowHeadersVisible = false;
// a kijelölt sorok törlése (visszafelé: a gyűjtemény módosul)
for (int i = dgv.SelectedRows.Count - 1; i >= 0; i--)
{
dgv.Rows.RemoveAt(dgv.SelectedRows[i].Index);
}
// az aktuális sor
if (dgv.CurrentRow != null)
{
lblNev.Text = Convert.ToString(dgv.CurrentRow.Cells["colNev"].Value);
}IsNewRow ellenőrzés akkor is jó szokás).SelectedRows sorrendje a kijelölés sorrendjét követheti, nem a sorok sorrendjét. Törlésnél az Index értéket használd, és ellenőrizd a bejárás módját (visszafelé).CurrentRow null: ellenőrizd.Jósolj!
Három sor van kijelölve, és a törlő ciklus előrefelé halad (foreach (DataGridViewRow s in dgv.SelectedRows) dgv.Rows.Remove(s);). Mi történik?
Jóslat ellenőrzése
A törlés megváltoztatja a kijelölést (a SelectedRows gyűjteményt), ezért a foreach kihagyhat sorokat vagy kivételt dobhat. Másolatot készíts a kijelölt sorokról (List<DataGridViewRow>), vagy járj visszafelé az indexeken.
Események és formázás
// a cella értéke megváltozott (a szerkesztés befejezése után)
private void dgv_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0) // a fejléc sora -1
{
return;
}
Osszesit();
}
// a jelölőnégyzet azonnali érvényesítése: kattintáskor, nem a cella elhagyásakor
private void dgv_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (dgv.IsCurrentCellDirty)
{
dgv.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
// a gomb a cellában
private void dgv_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && dgv.Columns[e.ColumnIndex].Name == "colTorol")
{
dgv.Rows.RemoveAt(e.RowIndex);
}
}
// formázás megjelenítéskor: a negatív szám piros
private void dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.RowIndex >= 0 && dgv.Columns[e.ColumnIndex].Name == "colAr" && e.Value != null)
{
int ar;
if (int.TryParse(e.Value.ToString(), out ar) && ar < 0)
{
e.CellStyle.ForeColor = Color.Firebrick;
}
}
}
// érvénytelen érték (például szöveg egy szám oszlopba adatkötésnél)
private void dgv_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
e.ThrowException = false;
lblUzenet.Text = "Érvénytelen érték a(z) " + (e.RowIndex + 1) + ". sorban.";
}RowIndex -1: az első ellenőrzés mindig ez legyen, különben a cellaelérés hibát dob.CurrentCellDirtyStateChanged és a CommitEdit azonnali változást ad.CellContentClick csak a cella tartalmára (gomb, jelölőnégyzet) kattintva fut, a CellClick a cella bármely pontjára. A gombokhoz az előbbi való.e.CellStyle), az adatot ne.Jósolj!
A CellValueChanged kezelő a dgv.Rows[e.RowIndex] sort olvassa. A felhasználó a fejlécre kattint (rendezés), és a CellValueChanged eseményt a kód e.RowIndex ellenőrzés nélkül kezeli. Mi történik?
Jóslat ellenőrzése
A fejléc-eseményeknél a RowIndex -1, és a dgv.Rows[-1] ArgumentOutOfRangeException kivételt dob. A CellClick, CellContentClick és a legtöbb cellaesemény kezelőjének első sora az if (e.RowIndex < 0) return; legyen.
Mit tegyél ide: egy DataGridView négy oszloppal (Név, Ár, Kész jelölőnégyzet, Törlés gomb) és néhány sorral.Javasolt fájlnév: winforms-8-3-tablazat.webp · Alt szöveg: DataGridView különféle oszlopokkal
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. NullReferenceException az összegzésnél
foreach (DataGridViewRow s in dgv.Rows)
{
osszeg += (int)s.Cells["colAr"].Value; // az új sor értéke null
}Hiba és javítás
Hagyd ki az új sort (IsNewRow), és használj TryParse-t a Convert.ToString eredményén.
2. ArgumentOutOfRangeException fejléckattintásra
A cellaeseményt a fejlécre kattintva a program összeomlik. Az Ok és javítás
e.RowIndex a fejlécnél -1. Az első sor: if (e.RowIndex < 0) return;.
3. A Columns["név"] null
A kód nem találja az oszlopot, pedig látszik a fejléce. A Ok és javítás
HeaderText és a Name két külön tulajdonság. Az indexelő a Name alapján keres: add meg a Name értéket.
4. A jelölőnégyzet értéke késve változik
A A CellValueChanged csak a cella elhagyásakor fut.Ok és javítás
CurrentCellDirtyStateChanged eseményben hívd a CommitEdit(DataGridViewDataErrorContexts.Commit) metódust.
5. A gomb a cellában nem reagál
A gomboszlop kattintására semmi nem történik. Nincs feliratkozva a Ok és javítás
CellContentClick eseményre, vagy a kezelő nem ellenőrzi az oszlopot jól (Columns[e.ColumnIndex].Name). Ellenőrizd az eseménykötést a tervezőben.
6. Az oszlopok megduplázódnak
Kódból adtál oszlopokat, és a táblázat dupla oszlopot mutat. Az Ok és javítás
AutoGenerateColumns igaz maradt adatkötésnél: állítsd false értékre, ha az oszlopokat te adod meg.
Mini projekt: osztályzat-nyilvántartó
Készíts táblázatot a diákok jegyeinek kezelésére:
dgv(Dock = Fillegy panelen,AllowUserToAddRows = false,FullRowSelect) oszlopai: Név (Fill), Matek, Magyar, Történelem (szám oszlopok, jobbra igazítva, 70 széles), Átlag (csak olvasható,0.00formátum), Törlés (gomb).- Az Új diák gomb (és a
txtNevmező Enter) új sort ad a névvel; a jegyek üresek. - A jegy cellák értéke 1–5 közötti egész lehet. A
CellValueChangedújraszámolja a sor átlagát az érvényes jegyekből (az üres és az érvénytelen cellát kihagyva). - A
CellFormattingaz 1,5 alatti átlagot piros félkövérrel, a 4,5 feletti átlagot zölddel jelöli (jellel is: ▼ / ▲, 6.9 lecke). - Az
lblOsszesitomutatja a diákok számát és az osztályátlagot (az átlagok átlaga, ahol van). - A Törlés gomb a cellában megerősítéssel törli a sort (
CellContentClick). - Teszteld: új diákok, jegyek beírása (érvényes és érvénytelen), üres sor, törlés, a színezés, az összesítés frissülése.
Megoldás megnyitása (próbáld ki előbb önállóan!)
Az átlagszámítás egy közös metódusban van (SorAtlag), amelyet a CellValueChanged hív, ügyelve arra, hogy az Átlag oszlop maga is változtatja az értéket (a jelző védi a végtelen hurkot).
private readonly string[] jegyOszlopok = { "colMatek", "colMagyar", "colTort" };
private bool szamol = false;
private void Form1_Load(object sender, EventArgs e)
{
dgv.AutoGenerateColumns = false;
dgv.AllowUserToAddRows = false;
dgv.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dgv.RowHeadersVisible = false;
DataGridViewTextBoxColumn nev = new DataGridViewTextBoxColumn { Name = "colNev", HeaderText = "Név", AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill };
dgv.Columns.Add(nev);
string[] fejlec = { "Matek", "Magyar", "Történelem" };
for (int i = 0; i < jegyOszlopok.Length; i++)
{
DataGridViewTextBoxColumn o = new DataGridViewTextBoxColumn { Name = jegyOszlopok[i], HeaderText = fejlec[i], Width = 70 };
o.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
dgv.Columns.Add(o);
}
DataGridViewTextBoxColumn atlag = new DataGridViewTextBoxColumn { Name = "colAtlag", HeaderText = "Átlag", Width = 80, ReadOnly = true };
atlag.DefaultCellStyle.Format = "0.00";
atlag.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
dgv.Columns.Add(atlag);
DataGridViewButtonColumn torol = new DataGridViewButtonColumn { Name = "colTorol", HeaderText = "", Text = "Törlés", UseColumnTextForButtonValue = true, Width = 80 };
dgv.Columns.Add(torol);
Osszesit();
}
private void UjDiak()
{
string nev = txtNev.Text.Trim();
if (nev.Length == 0) { return; }
dgv.Rows.Add(nev);
txtNev.Clear();
txtNev.Focus();
Osszesit();
}
private void btnUj_Click(object sender, EventArgs e) { UjDiak(); }
private void txtNev_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter) { e.SuppressKeyPress = true; UjDiak(); }
}
// a sor átlaga: az üres és az érvénytelen jegyeket kihagyja; null, ha nincs érvényes jegy
private double? SorAtlag(DataGridViewRow sor)
{
int db = 0;
int osszeg = 0;
foreach (string oszlop in jegyOszlopok)
{
int jegy;
if (int.TryParse(Convert.ToString(sor.Cells[oszlop].Value), out jegy) && jegy >= 1 && jegy <= 5)
{
osszeg += jegy;
db++;
}
}
if (db == 0) { return null; }
return (double)osszeg / db;
}
private void dgv_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0 || szamol) { return; }
szamol = true;
double? atlag = SorAtlag(dgv.Rows[e.RowIndex]);
dgv.Rows[e.RowIndex].Cells["colAtlag"].Value = atlag.HasValue ? (object)atlag.Value : null;
szamol = false;
Osszesit();
}
private void Osszesit()
{
double ossz = 0;
int db = 0;
foreach (DataGridViewRow sor in dgv.Rows)
{
if (sor.IsNewRow) { continue; }
double? a = SorAtlag(sor);
if (a.HasValue) { ossz += a.Value; db++; }
}
lblOsszesito.Text = dgv.Rows.Count + " diák, osztályátlag: " + (db == 0 ? "–" : (ossz / db).ToString("0.00"));
}
private void dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.RowIndex < 0 || dgv.Columns[e.ColumnIndex].Name != "colAtlag" || e.Value == null) { return; }
double a = Convert.ToDouble(e.Value);
if (a < 1.5)
{
e.Value = "▼ " + a.ToString("0.00");
e.FormattingApplied = true;
e.CellStyle.ForeColor = Color.Firebrick;
e.CellStyle.Font = new Font(dgv.Font, FontStyle.Bold);
}
else if (a > 4.5)
{
e.Value = "▲ " + a.ToString("0.00");
e.FormattingApplied = true;
e.CellStyle.ForeColor = Color.FromArgb(0, 100, 40);
}
}
private void dgv_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0 || dgv.Columns[e.ColumnIndex].Name != "colTorol") { return; }
string nev = Convert.ToString(dgv.Rows[e.RowIndex].Cells["colNev"].Value);
if (MessageBox.Show(this, "Törlöd: " + nev + "?", "Törlés", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
{
dgv.Rows.RemoveAt(e.RowIndex);
Osszesit();
}
}Három önálló gyakorlófeladat
Egyszerre csak egyet csinálj, és csak utána nyisd ki a megoldást.
1. Sorok száma és kijelölés
Az állapotsor mutassa: 12 sor, 3 kijelölt. Melyik eseményben frissíted, és mire kell vigyáznod az új sornál? A Egy lehetséges megoldás
SelectionChanged és a RowsAdded/RowsRemoved eseményekben. Az új sor miatt AllowUserToAddRows = false esetén a Rows.Count pontos.private void dgv_SelectionChanged(object sender, EventArgs e)
{
lblInfo.Text = dgv.Rows.Count + " sor, " + dgv.SelectedRows.Count + " kijelölt";
}
2. Váltakozó sorszín
A páratlan sorok háttere világosszürke. Melyik tulajdonsággal, és milyen kontraszt kell a szövegnek? Az Egy lehetséges megoldás
AlternatingRowsDefaultCellStyle.BackColor tulajdonsággal; a szöveg sötét maradjon (kontraszt, 6.9 lecke).dgv.AlternatingRowsDefaultCellStyle.BackColor = Color.FromArgb(244, 240, 250);
dgv.DefaultCellStyle.ForeColor = Color.FromArgb(30, 25, 40);
3. ComboBox oszlop
A Szint oszlop legördülő lista (Kezdő, Haladó, Mester). Hogyan hozod létre, és mit teszel az új sorral? A Egy lehetséges megoldás
DataGridViewComboBoxColumn Items gyűjteménye adja a választékot; sor hozzáadásakor a cella értékének a lista egyik elemének kell lennie (különben DataError).DataGridViewComboBoxColumn szint = new DataGridViewComboBoxColumn { Name = "colSzint", HeaderText = "Szint" };
szint.Items.AddRange("Kezdő", "Haladó", "Mester");
dgv.Columns.Add(szint);
int i = dgv.Rows.Add();
dgv.Rows[i].Cells["colSzint"].Value = "Kezdő"; // a lista egyik eleme
Gyakorlótár: 6 további feladat
Alap, közepes és kihívás szinten gyakorolhatsz. Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. Name és HeaderText
Mi a különbség a két tulajdonság között, és melyiket használod hivatkozáshoz? A Megoldás megnyitása
HeaderText a látható fejléc, a Name a kódbeli azonosító: a Columns["név"] indexelő ezt használja.
2. Az új sor
Hogyan ismered fel, és hogyan tiltod le? A Megoldás megnyitása
sor.IsNewRow igaz az üres beviteli sorra; a AllowUserToAddRows = false megszünteti.
Közepes szint
3. Oszlop összege
Írj metódust, amely az Ár oszlop összegét számolja (érvényes számok, új sor kihagyva). Ciklus Megoldás megnyitása
IsNewRow ellenőrzéssel és TryParse-szal.private decimal Osszeg(string oszlop)
{
decimal ossz = 0;
foreach (DataGridViewRow sor in dgv.Rows)
{
decimal ertek;
if (!sor.IsNewRow && decimal.TryParse(Convert.ToString(sor.Cells[oszlop].Value), out ertek))
{
ossz += ertek;
}
}
return ossz;
}
4. Sorok színezése feltétel szerint
Az Ár 1000 feletti sorai legyenek sárga hátterűek. Hol színezel (és miért nem a A CellValueChanged-ben)?Megoldás megnyitása
CellFormatting eseményben: a megjelenítés dönti el a stílust, így a rendezés és görgetés után is helyes.private void dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.RowIndex < 0) { return; }
int ar;
if (int.TryParse(Convert.ToString(dgv.Rows[e.RowIndex].Cells["colAr"].Value), out ar) && ar > 1000)
{
e.CellStyle.BackColor = Color.LemonChiffon;
e.CellStyle.ForeColor = Color.Black;
}
}
Kihívás szint
5. Sorok mozgatása
A Fel gomb a kijelölt sort egy hellyel feljebb viszi. Hogyan oldod meg a A sor kivétele (DataGridView-ban?Megoldás megnyitása
Rows.Remove), beszúrása (Rows.Insert(index, sor)), és a kijelölés visszaállítása. Adatkötéses tábláknál a mozgatás az adatgyűjteményben történik (8.4 lecke).private void btnFel_Click(object sender, EventArgs e)
{
if (dgv.CurrentRow == null || dgv.CurrentRow.Index == 0) { return; }
int i = dgv.CurrentRow.Index;
DataGridViewRow sor = dgv.Rows[i];
dgv.Rows.RemoveAt(i);
dgv.Rows.Insert(i - 1, sor);
dgv.ClearSelection();
dgv.Rows[i - 1].Selected = true;
}
6. Szerkesztés letiltása feltétel szerint
A Kész sorok többé nem szerkeszthetők. Melyik eseményt használod? A Megoldás megnyitása
CellBeginEdit eseményt: az e.Cancel = true megakadályozza a szerkesztést.private void dgv_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
object kesz = dgv.Rows[e.RowIndex].Cells["colKesz"].Value;
if (kesz is bool && (bool)kesz && dgv.Columns[e.ColumnIndex].Name != "colKesz")
{
e.Cancel = true;
}
}
Gyors önellenőrzés
1. Milyen típusú a cella értéke?
object: lehet szöveg, szám, bool vagy null.
2. Mi az új sor?
A tábla alján álló üres sor (IsNewRow), amelybe a felhasználó beírhat; a Rows.Count része, értékei null.
3. Mi az e.RowIndex a fejléc eseményeinél?
-1: ellenőrizd az eseménykezelő elején.
4. Hogyan törlöd a kijelölt sorokat?
Visszafelé haladó ciklussal az Index értékek alapján (a kijelölés törlés közben változik).
5. Miért kell a CommitEdit a jelölőnégyzetnél?
Az érték alapból a cella elhagyásakor érvényesül; a CommitEdit azonnal.
6. Mi a különbség a CellClick és a CellContentClick között?
A CellContentClick csak a tartalomra (gomb, jelölőnégyzet) kattintva fut.
7. Mire való a CellFormatting?
A cella megjelenítésének módosítása (szín, szöveg) rajzoláskor, az adat módosítása nélkül.
Mit tudsz már?
- Kódból építesz táblázatot különféle oszloptípusokkal.
- Sorokat és cellákat kezelsz típushelyesen, kerülöd az új sor és a
nullcsapdáit. - Kijelölést olvasol, és biztonságosan törölsz.
- Eseményekkel reagálsz, formázol (
CellFormatting), és kezeled aDataErroreseményt.
Következő lecke: List, BindingList és BindingSource
Az adatot a gyűjtemény tartja: a táblázat vagy lista csak megjeleníti, és magától frissül.



