O aplicație reală rareori încape într-o singură fereastră. Operațiile de introducere a datelor, setările, rapoartele, dialogurile de confirmare — toate au sens pe ferestre separate, care se deschid la nevoie și se închid după ce și-au îndeplinit rolul.
În exercițiu, Form1 este fereastra principală care afișează lista angajaților. FormAngajat este o fereastră secundară care apare când utilizatorul vrea să adauge sau să editeze un angajat. Cele două ferestre trebuie să comunice: Form1 trimite date către FormAngajat (angajatul de editat) și primește date înapoi (AngajatRezultat).
Show() vs. ShowDialog() — modal și non-modal
Există două moduri de a deschide un formular secundar.
Show() — non-modal:
FormAngajatf=newFormAngajat(null);f.Show();// codul continua imediat aici, fara sa astepte inchiderea lui f
Formularul se deschide și codul din Form1 continuă să ruleze imediat. Utilizatorul poate interacționa cu ambele ferestre simultan. Este potrivit pentru ferestre care rămân deschise în paralel, cum ar fi un panou de instrumente sau un log în timp real.
ShowDialog() — modal:
DialogResultrezultat=f.ShowDialog();// codul se opreste AICI pana cand utilizatorul inchide f// dupa inchidere, rezultat contine ce a ales utilizatorul
Formularul se deschide și blochează complet fereastra care l-a deschis. Utilizatorul nu poate interacționa cu Form1 cât timp FormAngajat este deschis. Este varianta corectă pentru dialoguri de adăugare, editare și confirmare.
📸 SCREENSHOT: Aplicația cu FormAngajat deschis deasupra Form1. Arată că Form1 este vizibil în fundal dar nu poate fi accesat (titlul lui apare estompat sau bara de titlu e inactivă). Evidențiază că FormAngajat este în prim-plan și activ.
Transmiterea datelor către formularul secundar
Cel mai clar mecanism este prin constructor. FormAngajat primește datele de care are nevoie la creare:
FormAngajat primește parametrul în constructor și decide ce face cu el:
Alternativa la constructor este prin proprietăți publice: setezi proprietățile după new FormAngajat() și înainte de ShowDialog(). Constructorul este mai clar și mai sigur — datele sunt disponibile de la momentul creării obiectului.
Citirea rezultatului din formularul secundar
Există două mecanisme complementare.
DialogResult — răspunsul la întrebarea „utilizatorul a confirmat sau a anulat?":
Proprietatea publică AngajatRezultat — datele introduse de utilizator:
Combinarea celor două: DialogResult.OK garantează că AngajatRezultat a fost populat. Codul din Form1 citește proprietatea doar după ce verifică DialogResult.
using cu formulare
Formularul secundar implementează IDisposable și alocă resurse de sistem (handles Windows). Folosirea using garantează eliberarea lor:
using este patternul recomandat pentru orice formular deschis cu ShowDialog().
Accesul la fereastra părinte
Uneori formularul secundar are nevoie de referință la cel care l-a deschis. ShowDialog(this) transmite referința la fereastra curentă ca Owner:
Din FormAngajat, fereastra care l-a deschis este accesibilă prin this.Owner:
În exercițiu nu avem nevoie de acest mecanism, dar este util de știut pentru situații mai complexe.
// Adaugare: transmitem null — formularul stie ca e gol
using (FormAngajat f = new FormAngajat(null))
{
if (f.ShowDialog() == DialogResult.OK)
{
// ...
}
}
// Editare: transmitem angajatul de editat
Angajat selectat = angajati[dgvAngajati.SelectedRows[0].Index];
using (FormAngajat f = new FormAngajat(selectat))
{
if (f.ShowDialog() == DialogResult.OK)
{
// ...
}
}
public partial class FormAngajat : Form
{
private Angajat angajatDeEditat;
public FormAngajat(Angajat angajat)
{
InitializeComponent();
angajatDeEditat = angajat;
}
private void FormAngajat_Load(object sender, EventArgs e)
{
if (angajatDeEditat != null)
{
// Modul editare: completam campurile cu datele existente
this.Text = "Editează angajat";
txtNume.Text = angajatDeEditat.Nume;
txtPrenume.Text = angajatDeEditat.Prenume;
// ...
}
else
{
// Modul adaugare: campuri goale
this.Text = "Angajat nou";
}
}
}
using (FormAngajat f = new FormAngajat(null))
{
DialogResult rezultat = f.ShowDialog();
if (rezultat == DialogResult.OK)
{
// utilizatorul a apasat OK si datele sunt valide
Angajat nou = f.AngajatRezultat;
angajati.Add(nou);
}
// daca rezultat == DialogResult.Cancel, nu facem nimic
}
// In FormAngajat:
public Angajat AngajatRezultat { get; private set; }
private void btnOk_Click(object sender, EventArgs e)
{
if (!Valideaza()) return; // nu inchidem daca validarea esueaza
AngajatRezultat = new Angajat
{
Nume = txtNume.Text.Trim(),
Prenume = txtPrenume.Text.Trim(),
// ...
};
this.DialogResult = DialogResult.OK; // inchide formularul
}
// Fara using — resursa nu e eliberata imediat
FormAngajat f = new FormAngajat(null);
f.ShowDialog();
// Cu using — eliberat automat la iesirea din bloc
using (FormAngajat f = new FormAngajat(null))
{
if (f.ShowDialog() == DialogResult.OK)
{
Angajat nou = f.AngajatRezultat;
angajati.Add(nou);
}
} // f.Dispose() este apelat automat aici
f.ShowDialog(this); // this = Form1, devine Owner al lui FormAngajat