Grafikus C# – Windows Forms tanfolyam › 7.6 lecke

Windows Forms · 7.6 lecke · saját párbeszédablak

Új Form hozzáadása és modalitás

Ha a MessageBox kevés (adatbevitel, több mező, saját gombfeliratok), saját párbeszédablakot készítesz: egy új Form-ot. Ebben a leckében megtanulod az új ablak hozzáadását a projekthez, a párbeszédablak tervezési szabályait (keret, gombok, kezdőhely), a modalitás fajtáit, és egy fontos mintát: hogyan kommunikál egy nem modális ablak (keresés és csere) a főablakkal úgy, hogy közben nem „ismeri” azt (események, 5.1 lecke).

  • kb. 110 perc
  • közepes szint
  • saját dialógus
Anime stílusú fiú és lány egy C# programozási feladatot beszél meg

A lecke végére

  • új Form-ot adsz a projekthez, és elnevezed a konvenció szerint;
  • a párbeszédablakot a szabályok szerint állítod be (FixedDialog, CenterParent, AcceptButton, CancelButton…);
  • megkülönbözteted az alkalmazás-, a tulajdonos- és a nem modális ablakot;
  • nem modális keresőablakot kötsz a főablakhoz eseményekkel (laza csatolás);
  • kezeled a keresés és csere műveleteit egy RichTextBox-ban (Find, SelectedText);
  • felismered a gyakori hibákat (szoros csatolás, Hide és Close keveredése).

Mielőtt elkezded

Ehhez a leckéhez a 7.5 lecke (Show, ShowDialog, élettartam), az 5.1 és 5.7 lecke (események, saját esemény, leiratkozás) és a 6.7 lecke (AcceptButton, CancelButton) szükséges.

7.5 Show és ShowDialog →

Új Form hozzáadása a projekthez

  1. A Solution Explorerben jobb gomb a projekten → Add → Form (Windows Forms) (újabb Visual Studióban Add → New Item → Windows Forms → Form).
  2. Add meg a nevet: a konvenció szerint a név …Form-ra végződik (KeresForm, BeallitasokForm, NevjegyForm). A név a fájl- és az osztálynév is lesz.
  3. A Visual Studio három fájlt hoz létre: KeresForm.cs (a te kódod), KeresForm.Designer.cs (a tervező generálta, ne szerkeszd kézzel) és KeresForm.resx (erőforrások). Az Add után megnyílik a tervező.
  4. Tervezd meg a felületet (6. fejezet eszközei), és állítsd be a Properties ablakban a párbeszédablak jellemzőit (lásd lent).
  5. Nyisd meg a főablak kódjából: new KeresForm().ShowDialog(this) vagy Show(this) (7.5 lecke).
partial classAz ablak osztálya partial: a KeresForm.cs és a Designer.cs egyetlen osztályt alkot (12.2 lecke). A te kódod mindig az .cs fájlban legyen.
NévA jó név megmondja a szerepet (BeallitasokForm), nem a sorszámot (Form2). Az átnevezéshez használd a Rename parancsot (F2), hogy a hivatkozások is frissüljenek.
NamespaceAz új ablak a projekt névterébe kerül, ezért a főablakból közvetlenül elérhető (new KeresForm()).
Több projektNagyobb programban az ablakok mappákba rendezhetők (Forms, Dialogs), de a névtér módosításra figyelj.

A párbeszédablak tervezési szabályai

TulajdonságÉrtékMiért?
FormBorderStyleFixedDialogNem méretezhető, párbeszédablak-szerű (6.1 lecke).
MinimizeBox, MaximizeBoxFalseA dialógust nem kicsinyítjük és nem nagyítjuk.
ShowInTaskbarFalseNincs külön tálcagomb: a főablak része.
StartPositionCenterParentA tulajdonos ablak közepén jelenik meg.
ShowIconFalseTisztább megjelenés.
AcceptButton, CancelButtonaz OK és a MégseEnter és Esc (6.7 lecke).
Textbeszédes címMit csinál az ablak (Keresés és csere).
Elrendezésgombok jobb alul, TableLayoutPanelSzokott elrendezés; betűmérethez igazodik (6.8 lecke).
AutoSizeTrue, GrowAndShrinkAz ablak a tartalomhoz igazodik (opcionális).
BeallitasokForm.cs (konstruktor, vagy a tervezőben)C#
public BeallitasokForm()
{
InitializeComponent();

this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.MinimizeBox = false;
this.MaximizeBox = false;
this.ShowInTaskbar = false;
this.ShowIcon = false;
this.StartPosition = FormStartPosition.CenterParent;

this.AcceptButton = btnOk;
this.CancelButton = btnMegse;
}

Jósolj!

A dialógus StartPosition értéke CenterParent, de a hívó ShowDialog() hívást tulajdonos nélkül használ. Hol jelenik meg az ablak?

Jóslat ellenőrzése

A CenterParent értékhez tulajdonos kell: tulajdonos nélkül az ablak a rendszer által választott helyen jelenik meg (nem biztos, hogy a főablak közepén). Ezért mindig ShowDialog(this). (Tulajdonos nélküli ShowDialog() esetén a .NET az aktív ablakot használja tulajdonosként, de erre ne építs.)

A modalitás fajtái

FajtaHogyan?Viselkedés
Tulajdonos-modálisShowDialog(owner)A tulajdonos (és az alkalmazás többi ablaka) le van tiltva, amíg a dialógus nyitva van.
Egymásba ágyazott modálisa dialógusból újabb ShowDialog(this)Verem: a legutóbbi aktív, az alatta lévők letiltva. Bezárás fordított sorrendben.
Nem modális, tulajdonossalShow(owner)Mindkét ablak használható; a tulajdonolt a tulajdonos fölött marad.
Nem modális, függetlenShow()Független ablak (a főablak mögé is kerülhet).
Miért modális a döntés?Ha a dialógus a főablak adatain dolgozik (beállítás, szerkesztés), a főablakot le kell tiltani, különben a felhasználó közben megváltoztathatná azt, amit a dialógus éppen szerkeszt.
Miért nem modális a kereső?A keresés közben a szerkesztésnek folytathatónak kell lennie: a felhasználó keres, javít, tovább keres.
Modális ablak és időzítőA modális ablak alatt az időzítők és események tovább futnak (a kód nem „áll le”): egy Timer a főablakban a dialógus alatt is tüzel, és a letiltott főablakot módosíthatja.
Dialógus a Load-banHa a főablak Load eseményében hívsz ShowDialog-ot, a főablak csak a dialógus bezárása után válik láthatóvá. Bejelentkezésre inkább a Program.cs (6.7 lecke) való.

Jósolj!

A főablakban egy 1 másodperces Timer az állapotsorban az időt frissíti. A felhasználó megnyit egy modális dialógust. Frissül-e az állapotsor idő?

Jóslat ellenőrzése

Igen, az óra tovább jár: a modális ablak a felhasználói bevitelt tiltja le, az üzenetfeldolgozás (időzítők, rajzolás) folytatódik. Ha a háttérben futó kód a dialógus alatt módosítaná a főablak adatait, ez zavart okozhat, ezért az ilyen kódot is érdemes a modalitáshoz igazítani.

Nem modális ablak és a főablak összekötése eseményekkel

A keresőablak Show(this) hívással nyílik, és a főablak szerkesztőjében keres. Hogyan éri el az ablak a szerkesztőt? Két lehetőség van:

Szoros csatolás (kerüld)

A kereső ablak megkapja a főablakot vagy a RichTextBox-ot, és közvetlenül dolgozik vele (fo.rtbSzoveg.Find(...)). Gyors, de a kereső csak ezzel az egy főablakkal működik, és a főablak belső vezérlői nyilvánosak lesznek.

Laza csatolás: események (ajánlott)

A kereső ablak eseményt vált ki (Keresés kérése), amelyre a főablak feliratkozik, és ő végzi a keresést. A kereső nem ismeri a főablakot, bármelyik ablakkal együtt használható, és a főablak vezérlői privátak maradnak (5.1, 5.7 lecke).

KeresForm.csC#
public class KeresEventArgs : EventArgs
{
public string Keresett { get; set; }
public string Csere { get; set; }
public bool KisbetuErzekeny { get; set; }
}

public partial class KeresForm : Form
{
// az ablak három műveletet kér a tulajdonostól
public event EventHandler<KeresEventArgs> KovetkezoKeres;
public event EventHandler<KeresEventArgs> CsereKeres;
public event EventHandler<KeresEventArgs> MindetCsereliKeres;

private KeresEventArgs Argumentumok()
{
return new KeresEventArgs
{
Keresett = txtKeres.Text,
Csere = txtCsere.Text,
KisbetuErzekeny = chkKisbetu.Checked
};
}

private void btnKovetkezo_Click(object sender, EventArgs e)
{
KovetkezoKeres?.Invoke(this, Argumentumok());
}

private void btnCsere_Click(object sender, EventArgs e)
{
CsereKeres?.Invoke(this, Argumentumok());
}

private void btnMind_Click(object sender, EventArgs e)
{
MindetCsereliKeres?.Invoke(this, Argumentumok());
}

// a bezárás elrejtés: az állapot (szöveg, jelölőnégyzet) megmarad
private void KeresForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
this.Hide();
}
}
}
Esemény mint „kérés”Az ablak nem tudja, mi történik a kéréssel: csak jelzi, hogy a felhasználó keresni akar, és átadja a beállításokat. A feldolgozás a feliratkozó dolga.
EventArgs leszármazottA KeresEventArgs osztály hordozza az adatot (5.2 lecke). Így az esemény paramétere típusos, nem kell a vezérlőkre hivatkozni.
Hide a bezáráskorA FormClosing a felhasználói bezárást elrejtésre cseréli. A program kilépésekor (CloseReason más) az ablak ténylegesen bezárul, ezért nem akadályozza a kilépést.
Feliratkozás és leiratkozásA főablak a kereső ablak élettartama alatt iratkozik fel, és az ablak a főablakkal együtt él, ezért itt a leiratkozás nem kritikus; a rövidebb élettartamú ablakoknál az 5.7 lecke szabálya érvényes.

Jósolj!

A KeresForm a FormClosing eseményben mindig megszakítja a bezárást (e.Cancel = true), a CloseReason vizsgálata nélkül. Be tud-e záródni a program a keresőablak nyitva hagyásával?

Jóslat ellenőrzése

Nem rendesen: a főablak bezárásakor a tulajdonolt ablak is bezáródna, de a Cancel megakadályozza, ezért a kilépés elakad (vagy a program a háttérben marad). Ezért kell a CloseReason vizsgálata: csak a UserClosing (a felhasználó X-e) esetén rejtsd el, minden más okra engedd a bezárást.

📷 Képernyőkép helye

Mit tegyél ide: a szerkesztő ablak és fölötte a „Keresés és csere” ablak a mezőkkel, jelölőnégyzettel és négy gombbal.Javasolt fájlnév: winforms-7-6-kereso.webp · Alt szöveg: A keresés és csere ablak a szerkesztő fölött

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 dialógus nem a főablak közepén jelenik meg

Az új ablak a képernyő egy véletlen pontján nyílik.

Ok és javítás

A StartPosition nem CenterParent, vagy nincs tulajdonos. Állítsd CenterParent értékre, és hívd a ShowDialog(this) metódust.

2. A kereső nem működik másik szerkesztővel

// KeresForm.cs
private void btnKovetkezo_Click(object sender, EventArgs e)
{
((Form1)this.Owner).rtbSzoveg.Find(txtKeres.Text); // csak a Form1-gyel működik
}
Hiba és javítás

Szoros csatolás: az ablak ismeri a főablak típusát és belső vezérlőjét. Használj eseményt (vagy interfészt), így a kereső bármelyik ablakkal együtt működik, és a főablak vezérlői nem kell, hogy nyilvánosak legyenek.

3. A kereső nem zárul be, és a program nem lép ki

A főablak bezárása után a program még fut.

Ok és javítás

A FormClosing minden bezárást megakadályoz. Csak a felhasználói bezárást rejtsd el: if (e.CloseReason == CloseReason.UserClosing).

4. A dialógus bezárása után az adatok elvesznek

A beállítóablak újranyitásakor üres mezők jelennek meg.

Ok és javítás

A ShowDialog ablakot minden nyitáskor új példányként hozod létre, és a mezőket nem töltöd fel a meglévő értékekkel. Add át az aktuális értékeket nyitáskor (konstruktor vagy tulajdonságok, 7.7 lecke).

5. Az OK gomb nem zár

A felhasználó az OK-t megnyomja, de az ablak nyitva marad.

Ok és javítás

A gomb DialogResult értéke None, és a kód sem állítja be a form DialogResult értékét. Állítsd be a gombon (OK), vagy sikeres ellenőrzés után kódból (6.7 lecke).

6. NullReferenceException az eseménynél

KovetkezoKeres(this, Argumentumok());   // nincs feliratkozó: null
Hiba és javítás

Az eseményt ?.Invoke(...) módon váltsd ki: ha nincs feliratkozó, nem történik semmi (5.1 lecke).

Mini projekt: keresés és csere

Készíts szerkesztőt keresés és csere ablakkal:

  1. Főablak: rtbSzoveg (RichTextBox, Dock = Fill), menü: Szerkesztés → Keresés és csere... (Ctrl+F és Ctrl+H is), állapotsor (tsslUzenet).
  2. KeresForm: txtKeres, txtCsere, chkKisbetu (Kis- és nagybetű megkülönböztetése), gombok: Következő, Csere, Mindet cseréli, Bezár (CancelButton, elrejt). Párbeszédablak-beállítások: FixedDialog, ShowInTaskbar = False, CenterParent.
  3. A KeresForm három eseményt vált ki (KovetkezoKeres, CsereKeres, MindetCsereliKeres) KeresEventArgs adattal; nem ismeri a főablakot.
  4. A főablak egypéldányos mintával kezeli az ablakot: nyitáskor a kijelölt szöveg a keresőmezőbe kerül, a fókusz a txtKeres mezőre.
  5. Következő keresés: a kijelölés vége után keres (RichTextBox.Find), a találatot kijelöli és láthatóvá görgeti; a dokumentum végén az elejétől folytatja (körbe); ha nincs találat, az állapotsor üzen (Nincs találat).
  6. Csere: ha a kijelölés megegyezik a keresett szöveggel, kicseréli, majd a következő találatra lép; különben csak keres.
  7. Mindet cseréli: az összes előfordulást kicseréli, az állapotsor mutatja a darabszámot (5 csere).
  8. Teszteld: kis- és nagybetű, a dokumentum vége (körbe), nincs találat, csere majd következő, mindet cseréli, az ablak bezárása és újranyitása (a mezők megmaradnak), a főablak bezárása nyitott keresővel.
Megoldás megnyitása (próbáld ki előbb önállóan!)

A keresés a RichTextBox.Find(szöveg, kezdet, beállítások) metódusra épül, amely a találat kezdő indexét adja (vagy -1 értéket). A RichTextBoxFinds.MatchCase a kisbetű-érzékenység. A Mindet cseréli a szöveg tartalmát egyszerre cseréli (a formázás elveszhet a Text felülírásánál), ezért a példa ciklusban, találatonként dolgozik.

Form1.csC#
private KeresForm kereso = null;

private void miKeres_Click(object sender, EventArgs e)
{
if (kereso == null || kereso.IsDisposed)
{
kereso = new KeresForm();
kereso.KovetkezoKeres += Kereso_KovetkezoKeres;
kereso.CsereKeres += Kereso_CsereKeres;
kereso.MindetCsereliKeres += Kereso_MindetCsereliKeres;
}

if (!kereso.Visible)
{
kereso.Show(this);
}

kereso.Activate();
kereso.Elokeszit(rtbSzoveg.SelectedText); // a KeresForm metódusa: a kijelölt szöveg a keresőmezőbe
}

private bool Keres(KeresEventArgs a)
{
if (a.Keresett.Length == 0)
{
return false;
}

RichTextBoxFinds opciok = a.KisbetuErzekeny ? RichTextBoxFinds.MatchCase : RichTextBoxFinds.None;
int kezdet = rtbSzoveg.SelectionStart + rtbSzoveg.SelectionLength;

int talalat = rtbSzoveg.Find(a.Keresett, Math.Min(kezdet, rtbSzoveg.TextLength), opciok);

if (talalat < 0 && kezdet > 0)
{
talalat = rtbSzoveg.Find(a.Keresett, 0, opciok); // körbe: az elejétől
}

if (talalat < 0)
{
tsslUzenet.Text = "Nincs találat: " + a.Keresett;
return false;
}

rtbSzoveg.Select(talalat, a.Keresett.Length);
rtbSzoveg.ScrollToCaret();
tsslUzenet.Text = "Találat a(z) " + (talalat + 1) + ". karakternél.";
return true;
}

private void Kereso_KovetkezoKeres(object sender, KeresEventArgs e)
{
Keres(e);
this.Activate(); // a főablak szerkesztőjére a fókusz visszaadása (a kereső nyitva marad)
}

private void Kereso_CsereKeres(object sender, KeresEventArgs e)
{
StringComparison osszehasonlitas = e.KisbetuErzekeny ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;

if (e.Keresett.Length > 0 && string.Equals(rtbSzoveg.SelectedText, e.Keresett, osszehasonlitas))
{
rtbSzoveg.SelectedText = e.Csere;
}

Keres(e);
}

private void Kereso_MindetCsereliKeres(object sender, KeresEventArgs e)
{
if (e.Keresett.Length == 0)
{
return;
}

RichTextBoxFinds opciok = e.KisbetuErzekeny ? RichTextBoxFinds.MatchCase : RichTextBoxFinds.None;
int db = 0;
int hely = 0;

while (hely < rtbSzoveg.TextLength)
{
int talalat = rtbSzoveg.Find(e.Keresett, hely, opciok);

if (talalat < 0)
{
break;
}

rtbSzoveg.Select(talalat, e.Keresett.Length);
rtbSzoveg.SelectedText = e.Csere;

hely = talalat + e.Csere.Length; // a cserélt szövegen túl folytatjuk
db++;
}

tsslUzenet.Text = db + " csere";
}

// KeresForm.cs
public void Elokeszit(string kijelolt)
{
if (kijelolt.Length > 0 && !kijelolt.Contains(Environment.NewLine))
{
txtKeres.Text = kijelolt;
}

txtKeres.Focus();
txtKeres.SelectAll();
}
📷 Képernyőkép helye

Mit tegyél ide: a szerkesztő kijelölt találattal, a keresőablak és az állapotsor „5 csere” üzenettel.Javasolt fájlnév: winforms-7-6-kesz.webp · Alt szöveg: Keresés és csere a szerkesztőben

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. Névjegy ablak

Készíts NevjegyForm ablakot (program neve, verzió, szerző, OK gomb), a párbeszédablak szabályaival. Hogyan nyitod meg a Súgó → Névjegy menüpontból?

Egy lehetséges megoldás

Modális ablak using blokkban. Az OK gomb AcceptButton és CancelButton is lehet (nincs más gomb).

Form1.csC#
private void miNevjegy_Click(object sender, EventArgs e)
{
using (NevjegyForm ablak = new NevjegyForm())
{
ablak.ShowDialog(this);
}
}

2. Kérdező dialógus eredménnyel

A KerdesForm egy kérdést és egy szövegmezőt mutat. A hívó string választ kap (vagy null Mégse esetén). Hogyan oldod meg a statikus metódussal (6.7 lecke)?

Egy lehetséges megoldás

A statikus Kerdez metódus létrehozza az ablakot, megjeleníti, kiolvassa a választ, és felszabadít (using).

KerdesForm.csC#
public static string Kerdez(IWin32Window tulajdonos, string kerdes, string alap)
{
using (KerdesForm ablak = new KerdesForm())
{
ablak.lblKerdes.Text = kerdes;
ablak.txtValasz.Text = alap;
ablak.txtValasz.SelectAll();

return ablak.ShowDialog(tulajdonos) == DialogResult.OK ? ablak.txtValasz.Text : null;
}
}

3. A kereső ablak mindig a szerkesztő mellett

A keresőablak induláskor a főablak jobb szélén jelenjen meg (ne takarja a szöveget), de a képernyőn belül maradjon. Hogyan számolod a helyét?

Egy lehetséges megoldás

A StartPosition = Manual és a főablak helyéből, valamint a munkaterületből számolt Location (6.1 lecke).

Form1.csC#
private void KeresoHelye(Form ablak)
{
Rectangle munka = Screen.FromControl(this).WorkingArea;

ablak.StartPosition = FormStartPosition.Manual;

int x = Math.Min(this.Right - ablak.Width - 20, munka.Right - ablak.Width);
int y = Math.Max(munka.Top, this.Top + 80);

ablak.Location = new Point(x, y);
}

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. Párbeszédablak beállításai

Sorolj fel hat tulajdonságot, amelyet egy jó párbeszédablaknál beállítasz.

Megoldás megnyitása

FormBorderStyle = FixedDialog, MinimizeBox = False, MaximizeBox = False, ShowInTaskbar = False, StartPosition = CenterParent, AcceptButton és CancelButton.

2. Nevek

Nevezd át a következő osztályokat a konvenció szerint: Form2 (kereső), Form3 (beállítások), Form4 (névjegy).

Megoldás megnyitása

KeresForm, BeallitasokForm, NevjegyForm (a Visual Studio Rename parancsával, F2).

Közepes szint

3. Modális megerősítő dialógus

Készíts MegerositForm ablakot saját gombfeliratokkal (Mentés, Elvetés, Mégse), amely DialogResult.Yes, No, Cancel értéket ad. Miért jobb, mint a MessageBox?

Megoldás megnyitása

A gombfeliratok a műveletet nevezik meg (az Igen/Nem helyett), ami érthetőbb. A három gomb DialogResult értéke a tervezőben beállítható, kód nem kell.

4. Esemény helyett visszahívás

A keresőablak konstruktora kapjon egy Func<string, bool> típusú függvényt (a keresés végrehajtását). Mi a különbség az eseménnyel szemben?

Megoldás megnyitása

A visszahívással az ablak eredményt is kap (találat volt-e), és egyetlen feldolgozója van; az esemény több feliratkozót és nincs visszatérési értéket enged. Az esemény a megszokottabb Windows Forms minta, a visszahívás egyszerűbb, ha egy válasz kell.

KeresForm.csC#
private readonly Func<string, bool> keres;

public KeresForm(Func<string, bool> keresFuggveny)
{
InitializeComponent();
keres = keresFuggveny;
}

private void btnKovetkezo_Click(object sender, EventArgs e)
{
lblEredmeny.Text = keres(txtKeres.Text) ? "Találat." : "Nincs találat.";
}

Kihívás szint

5. Interfész a laza csatoláshoz

Definiálj IKeresheto interfészt (bool KeresKovetkezo(string, bool)), amelyet a főablak megvalósít, és a kereső ablak ezt kapja. Mi az előnye az eseménnyel szemben?

Megoldás megnyitása

A szerződés kifejezett: a kereső tudja, mit vár a tulajdonostól, és az eredmény közvetlenül visszajön. Hátrány: a kereső ismer egy interfészt (de nem a főablak típusát).

IKeresheto.csC#
public interface IKeresheto
{
bool KeresKovetkezo(string keresett, bool kisbetuErzekeny);
}

// Form1 : Form, IKeresheto — a metódus megvalósítása a Keres(...) hívása
// KeresForm: public KeresForm(IKeresheto cel) { InitializeComponent(); this.cel = cel; }

6. Az ablak állapotának megőrzése

A Beállítások ablak a bezárás után is emlékezzen a fülre, amelyen állt. Hogyan oldod meg modális ablaknál, amelyet minden nyitáskor újra létrehozol?

Megoldás megnyitása

A főablak (vagy a Settings) tárolja az utolsó fül sorszámát, és nyitáskor átadja az ablaknak (tulajdonság vagy konstruktor), zárás után kiolvassa.

Form1.csC#
private int utolsoFul = 0;

private void miBeallitasok_Click(object sender, EventArgs e)
{
using (BeallitasokForm ablak = new BeallitasokForm())
{
ablak.AktivFul = utolsoFul;
ablak.ShowDialog(this);
utolsoFul = ablak.AktivFul; // a zárás után is elérhető
}
}

Gyors önellenőrzés

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

1. Hogyan adsz új ablakot a projekthez?

Add → Form (Windows Forms), beszédes névvel (…Form).

2. Melyik FormBorderStyle való a párbeszédablaknak?

FixedDialog, kicsinyítő és nagyító gomb nélkül.

3. Mikor modális a dialógus?

Ha döntést vagy adatot kér a főablaktól függő adatokra, és a felhasználónak előbb be kell fejeznie.

4. Mi a laza csatolás előnye?

Az ablak nem ismeri a főablakot, ezért újrahasználható, és a főablak vezérlői privátak maradnak.

5. Miért kell a CloseReason vizsgálata az elrejtésnél?

Hogy a program kilépésekor az ablak bezáródjon; csak a felhasználói bezárást (UserClosing) rejtsd el.

6. Hogyan keresel a RichTextBox-ban?

Find(szöveg, kezdőindex, RichTextBoxFinds): a találat indexét adja (vagy -1), a Select és ScrollToCaret mutatja.

7. Mit tegyél, ha az események nincs feliratkozó?

Az ?.Invoke(...) hívás biztonságos: feliratkozó nélkül nem történik semmi.

Mit tudsz már?

  • Új ablakot adsz a projekthez, és párbeszédablakként állítod be.
  • Megkülönbözteted a modalitás fajtáit.
  • Nem modális ablakot kötsz a főablakhoz eseményekkel (laza csatolás).
  • Keresést és cserét valósítasz meg egy szerkesztőben.
  • Felismered a gyakori hibákat (szoros csatolás, FormClosing és kilépés).

Következő lecke: Adatátadás két Form között

Hogyan kerülnek az adatok az egyik ablakból a másikba: konstruktor, tulajdonság, esemény, és a másolat–hivatkozás különbsége.