Grafikus C# – Windows Forms tanfolyam › 6.4 lecke Windows Forms · 6.4 lecke · automatikus elrendezés Az TableLayoutPanel és FlowLayoutPanel
Anchor és a Dock egy-egy vezérlőt rendez. Egy űrlapon azonban gyakran egész csoportok vannak: címke–mező párok sorai, gombok sora, kártyák, amelyek sorokba törnek. Erre két tároló való: a TableLayoutPanel rácsba (sorok és oszlopok) rendezi a vezérlőket, százalékos vagy fix méretekkel, a FlowLayoutPanel pedig folyamatosan egymás után, sortöréssel. Ebben a leckében megtanulod mindkettőt, és azt is, hogyan állítsd össze belőlük a leggyakoribb űrlapmintákat.
A lecke végére
- rácsot építesz a
TableLayoutPanelsegítségével, és beállítod a sorok és oszlopok méretét (Absolute,Percent,AutoSize); - vezérlőt helyezel a cellákba (tervezőben és kódból), és összevonod a cellákat (
ColumnSpan,RowSpan); - a címke–mező űrlap mintát gyorsan és szépen felépíted;
- a
FlowLayoutPanelsegítségével folyamatos elrendezést készítesz (FlowDirection,WrapContents,SetFlowBreak); - dinamikus elemlistát építesz kódból, és tudod, mikor kell a
SuspendLayout; - felismered a gyakori hibákat (nem nyúló vezérlő, átlapolt cella, rossz méretezési típus).
Mielőtt elkezded
Ehhez a leckéhez a 6.2 lecke (Anchor, Dock) és a 6.3 lecke (tárolók, Controls) szükséges. Új projektben próbáld ki a példákat.
TableLayoutPanel: rács a vezérlőknek
A TableLayoutPanel sorokból és oszlopokból álló rács, amelynek minden cellájába egy vezérlő kerülhet. A rács arányait a tároló méretétől függően számolja újra, ezért az ablak átméretezésekor a tartalom rendezett marad. A tervezőben a vezérlőt a kiválasztott cellába húzod, és a rácsvonalakat a panel jobb felső sarkában lévő kis nyíl (Smart Tag) menüjéből szerkeszted (Edit Rows and Columns).
| Tulajdonság | Jelentése |
|---|---|
ColumnCount, RowCount | Az oszlopok és sorok száma. |
ColumnStyles, RowStyles | Az oszlopok és sorok méretezési szabálya (SizeType és érték). |
CellBorderStyle | A cellák körüli rácsvonalak (Single, Inset…). Tervezéskor hasznos a cellák megjelenítésére. |
GrowStyle | Mi történik, ha több vezérlő van, mint cella: AddRows (új sor), AddColumns (új oszlop), FixedSize (hiba). |
Dock | A rácsot általában Fill értékre állítjuk, hogy az egész tárolót kitöltse. |
// rács kódból: 2 oszlop, 3 sor
TableLayoutPanel tabla = new TableLayoutPanel();
tabla.Dock = DockStyle.Fill;
tabla.ColumnCount = 2;
tabla.RowCount = 3;
tabla.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize)); // 1. oszlop: a tartalomhoz igazodik
tabla.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100)); // 2. oszlop: a maradék hely
for (int i = 0; i < 3; i++)
{
tabla.RowStyles.Add(new RowStyle(SizeType.AutoSize));
}
// vezérlő a cellába: Add(vezérlő, oszlop, sor)
tabla.Controls.Add(new Label { Text = "Név:", Anchor = AnchorStyles.Left }, 0, 0);
tabla.Controls.Add(new TextBox { Dock = DockStyle.Fill }, 1, 0);
this.Controls.Add(tabla);
// lekérdezés és összevonás
Control mezo = tabla.GetControlFromPosition(1, 0); // (oszlop, sor)
tabla.SetColumnSpan(cimsor, 2); // a vezérlő két oszlopot foglal elPanel vagy FlowLayoutPanel tárolóba, és a tároló kerüljön a cellába.Dock = Fill kitölti a cellát, az Anchor = Left a cella bal oldalán, függőlegesen középre teszi (a Top nélküli Anchor középre igazít). Az alapértelmezett Anchor (Top, Left) a bal felső sarokba tesz.Margin tulajdonsága a cella és a vezérlő közötti távolság. Ez adja a rács „levegőjét”, ezért ne állítsd nullára.Jósolj!
Egy TextBox a TableLayoutPanel egyik cellájában van, Anchor = Top, Left (az alapérték). Az oszlop szélessége 400 képpont. Milyen széles a szövegmező?
Jóslat ellenőrzése
A szövegmező megtartja saját szélességét (például 100 képpont), és a cella bal felső sarkában áll. A cella mérete nem nyújtja meg: a vezérlő Dock = Fill vagy Anchor = Left, Right beállítása kell. Ez a leggyakoribb kérdés: „miért nem nyúlik a mezőm a rácsban?”
Sorok és oszlopok méretezése
Minden sor és oszlop méretét egy SizeType értékkel adod meg:
| SizeType | Jelentése | Mikor jó? |
|---|---|---|
Absolute | Fix képpontszám (például 100). Nem változik az ablakkal. | Fix szélességű oszlop (ikon, címke), fix magasságú sor. |
AutoSize | A legnagyobb tartalomhoz igazodik. | Címke oszlop (a leghosszabb címke szélessége), címsor magassága. |
Percent | A maradék helyen osztozik a többi Percent sorral/oszloppal, a megadott súly szerint. | Nyúló oszlop, arányos sorok. |
Absolute és AutoSize sorok/oszlopok foglalják el a helyüket, a Percent elemek a maradékon osztoznak. Ezért a „címke + nyúló mező” elrendezés: 1. oszlop AutoSize, 2. oszlop Percent 100.ColumnSpan és RowSpan több oszlopot vagy sort fed le egy vezérlővel (cím a két oszlop felett, nagy szöveges mező több soron át). A tervezőben a vezérlő tulajdonságai között is megjelenik (ColumnSpan, RowSpan).tabla.RowCount++, és hozzá egy RowStyle (tabla.RowStyles.Add(new RowStyle(SizeType.AutoSize))). A tervezőben a Smart Tag menüből.Jósolj!
Egy rács három oszlopának stílusa: Absolute 100, Percent 30, Percent 70. A rács 1100 képpont széles. Mekkorák az oszlopok?
Jóslat ellenőrzése
Az első oszlop 100 képpont, a maradék 1000 képponton osztozik a két százalékos oszlop: 300 és 700 képpont. Az ablak nagyításakor a fix oszlop marad, a másik kettő a megnövekedett maradékon osztozik 30:70 arányban.
Az űrlap-minta: címke és mező párok
Az egyik leggyakoribb elrendezés a címke–mező űrlap. Egy TableLayoutPanel így oldja meg szépen és átméretezhetően:
- Tegyél az ablakra egy
TableLayoutPanel-t (Dock = Fill,Padding: 12), 2 oszloppal, annyi sorral, ahány mező kell, plusz egy gombsorral. - Az 1. oszlop:
AutoSize(a leghosszabb címke szélessége). A 2. oszlop:Percent 100(a többi hely). - A sorok:
AutoSize(a vezérlők magassága szerint). Az utolsó sor lehetPercent 100, ha egy nagy szövegmező tölti ki a maradékot. - A címkék:
Anchor = Left(a cellában függőlegesen középre kerülnek a mezőhöz igazítva),AutoSize = True. - A mezők:
Dock = Fill(vagyAnchor = Left, Right), így kitöltik a második oszlopot. - A gombsor: egy
FlowLayoutPanela két oszlopra összevonva (ColumnSpan = 2), amelyben a gombok jobbra igazodnak (FlowDirection = RightToLeft).
private void SorHozzaad(TableLayoutPanel tabla, string cimke, Control mezo)
{
int sor = tabla.RowCount; // az új sor sorszáma
tabla.RowCount = tabla.RowCount + 1;
tabla.RowStyles.Add(new RowStyle(SizeType.AutoSize));
Label felirat = new Label();
felirat.Text = cimke;
felirat.AutoSize = true;
felirat.Anchor = AnchorStyles.Left;
mezo.Dock = DockStyle.Fill;
tabla.Controls.Add(felirat, 0, sor);
tabla.Controls.Add(mezo, 1, sor);
}Miért jobb ez, mint az Anchor?
Az űrlap a betűmérettől is független marad: ha a felhasználó nagyobb betűméretet állít be a Windowsban (6.8 lecke), az AutoSize címkeoszlop kitágul, és a mezők a maradékot kapják. A fix Location értékekkel és Anchor-ral készült űrlapon a vezérlők ilyenkor összecsúsznak.
Jósolj!
Az űrlap első oszlopa Percent 50, a második Percent 50 (a címke–mező mintában az AutoSize/Percent 100 helyett). Mit látsz a címkék és a mezők arányában?
Jóslat ellenőrzése
A címkék oszlopa az űrlap felét foglalja el, a címkék kicsik és bal oldalon állnak, mellettük hatalmas üres hely marad, és a mezők csak a jobb felet töltik ki. Az arányos oszlop a tartalomtól függetlenül nyúlik. A címke oszlopnak AutoSize, a mező oszlopnak Percent 100 a helyes beállítás.
FlowLayoutPanel: folyamatos elrendezés
A FlowLayoutPanel a benne lévő vezérlőket egymás után rendezi, mint a szöveg szavait: az elejétől haladva, és ha elfogy a hely, új sorba tör. Nem kell koordinátákat megadnod: a vezérlők sorrendje (a hozzáadás sorrendje) adja a helyüket. Fontos tulajdonságai:
| Tulajdonság | Jelentése |
|---|---|
FlowDirection | LeftToRight (alap), RightToLeft, TopDown, BottomUp: a folyás iránya. |
WrapContents | Igaz (alap): sortörés, ha elfogy a hely. Hamis: a vezérlők egy sorban maradnak (a kilógók levágódnak, AutoScroll mellett görgethetők). |
AutoScroll | Görgetősáv, ha a tartalom nagyobb. |
AutoSize, AutoSizeMode | A panel a tartalmához igazodik (GrowAndShrink). |
private void CimkeHozzaad(string szoveg)
{
Button cimke = new Button();
cimke.Text = szoveg + " ✕";
cimke.AutoSize = true;
cimke.Margin = new Padding(4);
cimke.Tag = szoveg;
cimke.Click += CimkeTorol_Click;
flpCimkek.Controls.Add(cimke); // a sorban az utolsó helyre kerül
}
private void CimkeTorol_Click(object sender, EventArgs e)
{
Button cimke = (Button)sender;
cimke.Click -= CimkeTorol_Click; // 5.7 lecke: leiratkozás és felszabadítás
flpCimkek.Controls.Remove(cimke);
cimke.Dispose();
}
private void txtUj_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter && txtUj.Text.Trim().Length > 0)
{
e.SuppressKeyPress = true;
CimkeHozzaad(txtUj.Text.Trim());
txtUj.Clear();
}
}
// sortörés kényszerítése egy vezérlő után
flpCimkek.SetFlowBreak(csoportCim, true);
// sorrend módosítása: a vezérlő az elejére kerül
flpCimkek.Controls.SetChildIndex(cimke, 0);Margin adja (alapértelmezésben 3 képpont). A FlowLayoutPanel nem ad külön „térköz” tulajdonságot.FlowDirection = RightToLeft beállítással a gombok jobbról balra követik egymást: az első hozzáadott gomb a jobb szélen áll. Ezért az OK gombot adjuk elsőnek, a Mégse gombot másodiknak.Jósolj!
A FlowLayoutPanel WrapContents értéke hamis, a panel szélessége 300 képpont, és tíz 80 képpont széles gombot adsz hozzá. Mit látsz?
Jóslat ellenőrzése
Mind a tíz gomb egyetlen sorban áll, és csak az első három-négy látszik, a többi a panel szélén túl kilóg, és levágódik. AutoScroll = true mellett vízszintes görgetősáv jelenik meg. Alapértelmezett WrapContents = true esetén a gombok három-négy darabonként új sorba törnének.
Mit tegyél ide: egy címkefelhő: a FlowLayoutPanel sorokba tört gombjai, alatta a beviteli mező új címkék hozzáadásához.Javasolt fájlnév: winforms-6-4-flow.webp · Alt szöveg: Sorokba törő címkék FlowLayoutPanelben
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 mező nem nyúlik a rácsban
A A vezérlő TextBox a második oszlopban kicsi marad, bármekkora az ablak.Ok és javítás
Anchor értéke az alapértelmezett (Top, Left), és a cella nem nyújtja. Állítsd a Dock értékét Fill-re, vagy az Anchor értékét Left, Right (Top, Left, Right) értékre.
2. Két vezérlő ugyanabban a cellában
tabla.Controls.Add(txtA, 1, 0);
tabla.Controls.Add(txtB, 1, 0); // ugyanaz a cella!Hiba és javítás
A két vezérlő átlapolódik (egymáson látszanak), a második takarja az elsőt. Egy cellába egy vezérlő való. Ha kettő kell, tedd őket egy Panel vagy FlowLayoutPanel tárolóba, és azt a tárolót tedd a cellába.
3. Az oszlop vagy sor szélessége nem a vártnak megfelelő
A Az Percent oszlopok mellett az AutoSize oszlop túl széles lett.Ok és javítás
AutoSize oszlop a legszélesebb tartalmát követi: egy hosszú, nem tördelt címke túlnyújtja az oszlopot. Állíts be a címkére MaximumSize értéket és AutoSize = True, vagy rövidítsd a címkét. A százalékos oszlopok a maradékon osztoznak, ezért kisebbek lesznek.
4. A FlowLayoutPanel nem tördel
A gombok egy sorban maradnak, és kilógnak. A Ok és javítás
WrapContents hamis (vagy a panel AutoSize értéke igaz, ezért a panel a tartalmához nő, és nincs mire tördelni). Kapcsold be a WrapContents tulajdonságot, és add meg a panel rögzített szélességét (Dock, Anchor, vagy MaximumSize).
5. Villog és lassú az elemek hozzáadása
for (int i = 0; i < 500; i++)
{
flp.Controls.Add(new Button()); // minden hozzáadás újraszámolja az elrendezést
}Hiba és javítás
Minden Add újrarendezi a panelt. Fogd közre flp.SuspendLayout(); és flp.ResumeLayout(); hívással: az elrendezés csak egyszer számolódik újra a végén. Sok elemnél (több száz) érdemes más megoldáson gondolkodni (lista, DataGridView), mert minden elem egy külön vezérlő.
6. Az oszlop nem érvényesül, pedig beállítottam
tabla.ColumnCount = 3;
// de a ColumnStyles gyűjtemény csak két elemet tartalmazHiba és javítás
A ColumnCount és a ColumnStyles nem mindig marad szinkronban. Minden oszlophoz tartozzon egy ColumnStyle (a hiányzó elemeket add hozzá, a felesleges stílusokat töröld), és kódból az oszlop hozzáadásakor a stílust is add hozzá.
Mini projekt: regisztrációs űrlap és címkefelhő
Készíts átméretezhető regisztrációs űrlapot, amelyben rács és folyamatos elrendezés együtt dolgozik:
- Az ablak:
MinimumSize480 × 460, egyTableLayoutPanel(tlp,Dock = Fill,Padding12) két oszloppal (AutoSize,Percent 100). - Az első sor egy
lblCimcímsor (Új felhasználó, nagyobb betű,ColumnSpan = 2). - A következő sorok: Név (
txtNev), E-mail (txtEmail), Születési dátum (dtpDatum), Ország (cmbOrszag), mindDock = Fill, a címkékAnchor = Left. - Egy Érdeklődési kör sor, amelynek mezője egy
FlowLayoutPanel(flpKorok,AutoSize) a címkék számára, alatta egytxtUjKormező: Enter új címkét ad hozzá, a címkére kattintva törlődik (Dispose, leiratkozás). - Az utolsó sor egy
FlowLayoutPanel(flpGombok,FlowDirection = RightToLeft,ColumnSpan = 2) a Regisztráció és Mégse gombbal; a jobb szélen álljon a Regisztráció gomb. - A Regisztráció gomb ellenőrzi a kötelező mezőket (név, e-mail
@jellel), éslblUzenetmutatja az eredményt (az érdeklődési körökkel együtt). - Teszteld: átméretezés (a mezők nyúlnak), nagyobb betűméret a Windowsban (az űrlap nem csúszik szét), sok címke hozzáadása (sortörés), címke törlése, a gombsor helye.
Megoldás megnyitása (próbáld ki előbb önállóan!)
A rács a tervezőben készül (Smart Tag → Edit Rows and Columns), a kód a címkefelhő és az ellenőrzés. A kör címkéi Button vezérlők, mert egy Label kattintása kevésbé kézenfekvő, de Label is használható. A Tag tárolja a kör nevét (5.8 lecke).
private void Form1_Load(object sender, EventArgs e)
{
this.MinimumSize = new Size(480, 460);
cmbOrszag.Items.AddRange(new object[] { "Magyarország", "Ausztria", "Szlovákia", "Románia" });
cmbOrszag.SelectedIndex = 0;
}
private void KorHozzaad(string nev)
{
foreach (Control c in flpKorok.Controls)
{
if (c.Tag != null && c.Tag.ToString().ToLower() == nev.ToLower())
{
return; // már szerepel
}
}
Button cimke = new Button();
cimke.Text = nev + " ✕";
cimke.AutoSize = true;
cimke.Margin = new Padding(3);
cimke.Tag = nev;
cimke.Click += Kor_Click;
flpKorok.Controls.Add(cimke);
}
private void Kor_Click(object sender, EventArgs e)
{
Button cimke = (Button)sender;
cimke.Click -= Kor_Click;
flpKorok.Controls.Remove(cimke);
cimke.Dispose();
}
private void txtUjKor_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
e.SuppressKeyPress = true;
string nev = txtUjKor.Text.Trim();
if (nev.Length > 0)
{
KorHozzaad(nev);
txtUjKor.Clear();
}
}
}
private void btnRegisztracio_Click(object sender, EventArgs e)
{
if (txtNev.Text.Trim().Length == 0)
{
lblUzenet.Text = "A név kötelező.";
txtNev.Focus();
return;
}
if (!txtEmail.Text.Contains("@"))
{
lblUzenet.Text = "Az e-mail címnek tartalmaznia kell a @ jelet.";
txtEmail.Focus();
return;
}
List<string> korok = new List<string>();
foreach (Control c in flpKorok.Controls)
{
korok.Add(c.Tag.ToString());
}
lblUzenet.Text = $"Regisztrálva: {txtNev.Text.Trim()} ({cmbOrszag.Text}), érdeklődés: {string.Join(", ", korok)}";
}
private void btnMegse_Click(object sender, EventArgs e)
{
this.Close();
}Mit tegyél ide: a kész űrlap: a rendezett címke–mező párok, alatta a címkék sorokba törve, és a jobb alsó sarokban a gombok.Javasolt fájlnév: winforms-6-4-kesz.webp · Alt szöveg: A regisztrációs űrlap és a címkefelhő
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. Számológép gombrács
Készíts 4 × 5 rácsot egy számológép gombjainak ( A rács automatikusan egyenlő méretű cellákra osztja a helyet, és az ablak átméretezésekor a gombok is nőnek. Kézi TableLayoutPanel, minden sor és oszlop Percent, a gombok Dock = Fill), amelynek gombjait kódból hozod létre, és egyetlen közös kezelő a Tag alapján dolgozik. Miért jobb ez a Location számításnál?Egy lehetséges megoldás
Location és Size számításnál a Resize eseményben kellene mindent újraszámolni.private void Form1_Load(object sender, EventArgs e)
{
string[] jelek = { "7", "8", "9", "÷", "4", "5", "6", "×", "1", "2", "3", "-", "0", ",", "=", "+" };
tlpGombok.ColumnCount = 4;
tlpGombok.RowCount = 4;
tlpGombok.ColumnStyles.Clear();
tlpGombok.RowStyles.Clear();
for (int i = 0; i < 4; i++)
{
tlpGombok.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 25));
tlpGombok.RowStyles.Add(new RowStyle(SizeType.Percent, 25));
}
for (int i = 0; i < jelek.Length; i++)
{
Button gomb = new Button();
gomb.Text = jelek[i];
gomb.Dock = DockStyle.Fill;
gomb.Tag = jelek[i];
gomb.Click += Gomb_Click;
tlpGombok.Controls.Add(gomb, i % 4, i / 4); // oszlop: maradék, sor: egész osztás
}
}
private void Gomb_Click(object sender, EventArgs e)
{
txtKijelzo.Text = txtKijelzo.Text + ((Button)sender).Tag;
}
2. Képgaléria méretezővel
Egy A FlowLayoutPanel tizenkét színes négyzetet (Panel) mutat. Egy TrackBar (40–160) a négyzetek méretét állítja, és a panel újrarendezi őket. Hogyan oldod meg hatékonyan?Egy lehetséges megoldás
Scroll esemény végigmegy a négyzeteken, és a méretet állítja. A SuspendLayout/ResumeLayout miatt a rendezés csak egyszer számolódik.private void Form1_Load(object sender, EventArgs e)
{
Random r = new Random();
for (int i = 0; i < 12; i++)
{
Panel negyzet = new Panel();
negyzet.BackColor = Color.FromArgb(r.Next(60, 230), r.Next(60, 230), r.Next(60, 230));
negyzet.Size = new Size(trbMeret.Value, trbMeret.Value);
flpGaleria.Controls.Add(negyzet);
}
}
private void trbMeret_Scroll(object sender, EventArgs e)
{
flpGaleria.SuspendLayout();
foreach (Control c in flpGaleria.Controls)
{
c.Size = new Size(trbMeret.Value, trbMeret.Value);
}
flpGaleria.ResumeLayout();
}
3. Dinamikus táblázatsorok
Egy A TableLayoutPanel három oszlopot (Termék, Mennyiség, Törlés) tartalmaz. Az Új sor gomb új sort ad hozzá egy TextBox, egy NumericUpDown és egy Törlés gombbal; a Törlés gomb az adott sort eltávolítja. Mi a nehézség a sor törlésével?Egy lehetséges megoldás
TableLayoutPanel nem tud „sort törölni”: a vezérlőket el kell távolítani, a többi sor vezérlőit pedig egy sorral feljebb kell helyezni, majd a RowCount csökkenthető. Egyszerűbb, ha minden sor egy Panel (vagy FlowLayoutPanel TopDown irányban), így a sor törlése egyetlen vezérlő eltávolítása.private void btnUjSor_Click(object sender, EventArgs e)
{
Panel sor = new Panel();
sor.Size = new Size(flpSorok.ClientSize.Width - 25, 32);
TextBox termek = new TextBox { Location = new Point(0, 4), Width = 200 };
NumericUpDown db = new NumericUpDown { Location = new Point(210, 4), Width = 70, Minimum = 1, Value = 1 };
Button torol = new Button { Text = "Törlés", Location = new Point(290, 2), Tag = sor };
torol.Click += SorTorol_Click;
sor.Controls.Add(termek);
sor.Controls.Add(db);
sor.Controls.Add(torol);
flpSorok.Controls.Add(sor);
}
private void SorTorol_Click(object sender, EventArgs e)
{
Button torol = (Button)sender;
Panel sor = (Panel)torol.Tag;
torol.Click -= SorTorol_Click;
flpSorok.Controls.Remove(sor);
sor.Dispose(); // a gyermekeit is felszabadítja
}
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. SizeType értékek
Add meg, melyik (a) SizeType-ot használnád: (a) egy ikon oszlop, amely mindig 32 képpont; (b) a címkék oszlopa, amely a leghosszabb címke szélességéhez igazodik; (c) az űrlap fő része, amely kitölti a maradék helyet.Megoldás megnyitása
Absolute 32; (b) AutoSize; (c) Percent 100.
2. Vezérlő a cellába kódból
Írd meg a kódot, amely egy Mentés gombot a rács 2. oszlopának 4. sorába (a számozás nullától) teszi, és kitölti a cellát. Az Megoldás megnyitása
Add(vezérlő, oszlop, sor) sorrendje (x, y). A 2. oszlop indexe 1, a 4. soré 3.Button mentes = new Button();
mentes.Text = "Mentés";
mentes.Dock = DockStyle.Fill;
tlp.Controls.Add(mentes, 1, 3);
Közepes szint
3. Címsor két oszlopon
Egy rács első sorában egy címke a két oszlopot lefedi, és középre igazított. Hogyan állítod be kódból? A Megoldás megnyitása
SetColumnSpan(címke, 2) hívással. A középre igazításhoz a címke szövege TextAlign = MiddleCenter, és a cellát kitölti a Dock = Fill.Label cim = new Label();
cim.Text = "Új felhasználó";
cim.Dock = DockStyle.Fill;
cim.TextAlign = ContentAlignment.MiddleCenter;
cim.Font = new Font(cim.Font.FontFamily, 14, FontStyle.Bold);
tlp.Controls.Add(cim, 0, 0);
tlp.SetColumnSpan(cim, 2);
4. Sortörés kategória után
Egy A FlowLayoutPanelben kategóriák címei (Label) és alattuk elemek (Button) állnak, és minden kategóriacím után új sor kezdődik. Hogyan érted el, hogy a cím külön sorban legyen?Megoldás megnyitása
SetFlowBreak(cím, true) a címke után sortörést kényszerít, így az elemek új sorban kezdődnek. Ha a következő cím előtt is új sor kell, az utolsó elem után is kell törés.Label gyumolcs = new Label { Text = "Gyümölcsök", AutoSize = true, Font = new Font(Font, FontStyle.Bold) };
flp.Controls.Add(gyumolcs);
flp.SetFlowBreak(gyumolcs, true); // a cím után új sor
foreach (string nev in new string[] { "Alma", "Körte", "Szilva" })
{
flp.Controls.Add(new Button { Text = nev, AutoSize = true });
}
Kihívás szint
5. Rács sorainak összehasonlítása a sebességben
Mérd meg a A Stopwatch segítségével, mennyi ideig tart 300 gomb hozzáadása egy FlowLayoutPanelhez SuspendLayout nélkül és azzal. Mit tapasztalsz?Megoldás megnyitása
SuspendLayout nélkül minden Add újrarendez, ezért a futásidő sokszorosa lehet. A pontos arány a géptől függ: futtasd le, és jegyezd fel az értékeket.private long Meres(bool felfuggeszt)
{
System.Diagnostics.Stopwatch ora = System.Diagnostics.Stopwatch.StartNew();
flp.Controls.Clear();
if (felfuggeszt)
{
flp.SuspendLayout();
}
for (int i = 0; i < 300; i++)
{
flp.Controls.Add(new Button { Text = i.ToString(), Width = 50 });
}
if (felfuggeszt)
{
flp.ResumeLayout();
}
ora.Stop();
return ora.ElapsedMilliseconds;
}
private void btnMeres_Click(object sender, EventArgs e)
{
long nelkul = Meres(false);
long vele = Meres(true);
lblEredmeny.Text = $"Nélküle: {nelkul} ms, vele: {vele} ms";
}
6. Melyik tároló való?
Dönts: (a) egy űrlap tíz címke–mező párral; (b) egy gombsor jobbra igazítva; (c) egy képgaléria, amely sorokba tör; (d) a bal oldali navigáció és a fő tartalom, a felhasználó húzásával átméretezhetően. Melyik tárolót használod mindegyikhez? (a) Megoldás megnyitása
TableLayoutPanel (AutoSize + Percent 100 oszlopok); (b) FlowLayoutPanel RightToLeft irányban; (c) FlowLayoutPanel sortöréssel; (d) SplitContainer (6.3 lecke).
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. Súlyt: a fix ( Két oszlop: az első Egy. Több vezérlőhöz tároló kell a cellában ( A megadott vezérlő után sortörést kényszerít a Sok vezérlő hozzáadásakor vagy módosításakor, hogy az elrendezés csak egyszer számolódjon újra a 1. Mit jelent a Percent a TableLayoutPanelben?
Absolute, AutoSize) elemek után megmaradó helyen osztozik a többi Percent elemmel, a megadott arányban.2. Hogyan nyúlik a vezérlő a cellában?
Dock = Fill vagy Anchor = Left, Right beállítással.3. Mi a helyes mintája a címke–mező űrlapnak?
AutoSize, a második Percent 100; a sorok AutoSize; a mezők Dock = Fill, a címkék Anchor = Left.4. Hány vezérlő fér egy cellába?
Panel, FlowLayoutPanel).5. Mire való a SetFlowBreak?
FlowLayoutPanelben.6. Hogyan készítesz jobbra igazított gombsort?
FlowLayoutPanel FlowDirection = RightToLeft irányban: az első hozzáadott gomb a jobb szélen áll.7. Mikor kell a SuspendLayout?
ResumeLayout hívásánál.
Mit tudsz már?
- Rácsot építesz a
TableLayoutPanelsegítségével, és beállítod a sorok és oszlopok méretezését. - A címke–mező űrlap mintát megépíted, és gombsort igazítasz jobbra.
- A
FlowLayoutPanelsegítségével folyamatos, sortörő elrendezést és dinamikus elemlistát készítesz. - Tudod, mikor kell a
SuspendLayout, és hogyan szabadítod fel a törölt vezérlőket. - Felismered a gyakori hibákat (nem nyúló vezérlő, átlapolt cella,
WrapContents).
Következő lecke: TabControl és többlapos felületek
A felület több oldalra osztása füles lapokkal: lapok, eseményeik, és a lapok kódból való kezelése.




