🪟 Dialog Forms e Comunicazione tra Finestre

Crea applicazioni professionali con più finestre che comunicano tra loro!

🎯 Cosa Imparerai in Questa Lezione

Fino ad ora hai lavorato con una sola finestra. Oggi scoprirai come creare
applicazioni multi-finestra come i programmi professionali:
login che apre la dashboard, pulsante “Dettagli” che apre una finestra con info,
finestre di conferma personalizzate! 🚀

✨ Concetti di Questa Lezione

🪟 Form Secondari

Creare altre finestre oltre alla principale. Ogni form può avere
controlli diversi e funzionalità specifiche.

💬 Show() vs ShowDialog()

Due modi di aprire finestre: Show = non blocca, ShowDialog = blocca
finché l’utente non chiude (modale).

📡 Passare Dati tra Form

Inviare informazioni da una finestra all’altra usando costruttori
e proprietà pubbliche.

📂 Dialog Predefiniti

Dialog già pronti di Windows: Apri File, Salva File, Scegli Colore,
Scegli Font. Pronti all’uso!

📚 Prerequisiti
  • ✅ Timer e ProgressBar (Lezione 9)
  • ✅ Concetti di variabili e costruttori
  • ✅ Gestione eventi

💬 Show() vs ShowDialog(): Differenze Cruciali

📄 Show() – Non Modale

Comportamento:

La finestra si apre ma NON blocca l’app principale.
L’utente può cliccare su entrambe le finestre.

💡 Quando usarlo:

  • Finestre di aiuto
  • Calcolatrice separata
  • Palette strumenti
  • Dashboard multi-finestra
Form2 finestra = new Form2();
finestra.Show();
// Il codice continua subito!

⏸️ ShowDialog() – Modale

Comportamento:

La finestra si apre e BLOCCA tutto il resto.
Devi chiuderla prima di usare l’app principale.

💡 Quando usarlo:

  • Login obbligatorio
  • Conferme importanti
  • Impostazioni da salvare
  • Form di inserimento dati
Form2 finestra = new Form2();
finestra.ShowDialog();
// Il codice aspetta qui finché chiudi!

🔐 Esercizio 1: Sistema di Login

▶ Obiettivo

Crea un sistema con 2 finestre: una per il login e una per
la dashboard principale. Solo con credenziali corrette si apre la dashboard!

1

Crea i Form

📝 Procedura:

  1. Progetto già ha Form1 (lo rinomineremo in FormLogin)
  2. Tasto destro sul progetto → Add → Form (Windows Forms)
  3. Nome: FormDashboard.cs → Add
  4. Ora hai 2 form!
🎨 FormLogin (Form1):

  • Label: “Username:”
  • TextBox: txt_username
  • Label: “Password:”
  • TextBox: txt_password (PasswordChar = ‘*’)
  • Button: btn_login (Text = “🔓 Login”)
  • Label: lbl_errore (Text = “”, ForeColor = Red)

🎨 FormDashboard:

  • Label: lbl_benvenuto (Text = “Benvenuto, [Nome]!”, Font grande)
  • Label: “Dashboard Principale”
  • Button: btn_logout (Text = “🔒 Logout”)

2

Codice FormLogin (Form1.cs)

FormLogin.cs
using System;
using System.Windows.Forms;

namespace SistemaLogin
{
    public partial class Form1 : Form
    {
        // Credenziali hardcoded (in app reale: database!)
        private const string USERNAME_CORRETTO = "admin";
        private const string PASSWORD_CORRETTA = "1234";

        public Form1()
        {
            InitializeComponent();
            
            // Imposta PasswordChar per nascondere password
            txt_password.PasswordChar = '●';
            
            // Permetti login con INVIO
            this.AcceptButton = btn_login;
        }

        // ═══════════════════════════════════════════
        // PULSANTE LOGIN
        // ═══════════════════════════════════════════
        private void btn_login_Click(object sender, EventArgs e)
        {
            // Prendi le credenziali inserite
            string username = txt_username.Text.Trim();
            string password = txt_password.Text;

            // Validazione base
            if (string.IsNullOrWhiteSpace(username))
            {
                lbl_errore.Text = "❌ Inserisci lo username!";
                txt_username.Focus();
                return;
            }

            if (string.IsNullOrWhiteSpace(password))
            {
                lbl_errore.Text = "❌ Inserisci la password!";
                txt_password.Focus();
                return;
            }

            // Verifica credenziali
            if (username == USERNAME_CORRETTO && password == PASSWORD_CORRETTA)
            {
                // ✅ LOGIN RIUSCITO!
                
                // Crea e mostra la dashboard
                FormDashboard dashboard = new FormDashboard(username);
                dashboard.Show();
                
                // NASCONDI il form di login (non chiudere!)
                this.Hide();
                
                // Quando chiude la dashboard, chiudi anche login
                dashboard.FormClosed += (s, args) => this.Close();
            }
            else
            {
                // ❌ LOGIN FALLITO
                lbl_errore.Text = "❌ Username o password errati!";
                txt_password.Clear();
                txt_password.Focus();
                
                // Bonus: animazione shake
                this.Left -= 10;
                System.Threading.Thread.Sleep(50);
                this.Left += 20;
                System.Threading.Thread.Sleep(50);
                this.Left -= 10;
            }
        }
    }
}

3

Codice FormDashboard.cs

FormDashboard.cs
using System;
using System.Windows.Forms;

namespace SistemaLogin
{
    public partial class FormDashboard : Form
    {
        private string nomeUtente;

        // ═══════════════════════════════════════════
        // COSTRUTTORE: Riceve il nome utente dal login
        // ═══════════════════════════════════════════
        public FormDashboard(string username)
        {
            InitializeComponent();
            
            // Salva il nome utente
            this.nomeUtente = username;
            
            // Personalizza il benvenuto
            lbl_benvenuto.Text = $"👋 Benvenuto, {nomeUtente}!";
            
            // Imposta titolo finestra
            this.Text = $"Dashboard - {nomeUtente}";
        }

        // ═══════════════════════════════════════════
        // PULSANTE LOGOUT
        // ═══════════════════════════════════════════
        private void btn_logout_Click(object sender, EventArgs e)
        {
            DialogResult risultato = MessageBox.Show(
                "Sei sicuro di voler uscire?",
                "Conferma Logout",
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question);

            if (risultato == DialogResult.Yes)
            {
                // Chiudi la dashboard
                // Questo farà chiudere anche il FormLogin
                this.Close();
            }
        }

        // ═══════════════════════════════════════════
        // EVENTO: Quando la finestra si chiude
        // ═══════════════════════════════════════════
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            
            MessageBox.Show($"Arrivederci, {nomeUtente}!", 
                          "Logout", 
                          MessageBoxButtons.OK, 
                          MessageBoxIcon.Information);
        }
    }
}

4

🎬 Come Funziona

📋 Flusso Completo:

  1. App si apre → mostra FormLogin
  2. Utente inserisce: Username = “admin”, Password = “1234”
  3. Clicca Login → credenziali corrette ✅
  4. FormDashboard si apre con “Benvenuto, admin!”
  5. FormLogin si nasconde (Hide, non Close!)
  6. Utente clicca Logout → conferma “Sei sicuro?”
  7. Clicca Yes → Dashboard si chiude
  8. Evento FormClosed di Dashboard chiude anche FormLogin
  9. Applicazione termina

📚 Concetti Chiave – Costruttori

Costruttore con Parametri
Permette di passare dati quando crei un form

// Nel form che riceve i dati
public FormDashboard(string username)
{
    InitializeComponent();
    this.nomeUtente = username;
}

// Nel form che apre
FormDashboard dash = new FormDashboard("Mario");
dash.Show();

this.Hide() vs this.Close()
Nascondere vs chiudere una finestra

this.Hide();   // Nasconde ma il form esiste ancora in memoria
this.Show();   // Mostra di nuovo un form nascosto

this.Close();  // Chiude e DISTRUGGE il form
// Dopo Close() non puoi più fare Show()!

AcceptButton
Pulsante che si “clicca” quando premi INVIO

// Nel costruttore del form
this.AcceptButton = btn_login;

// Ora premere INVIO = cliccare btn_login

✅ DialogResult: Sapere Cosa Ha Scelto l’Utente

Quando usi ShowDialog(), puoi sapere quale pulsante ha cliccato
l’utente: OK, Cancel, Yes, No, ecc. Usa la proprietà DialogResult!

🎯 Valori Disponibili

DialogResult.OK          // Pulsante OK
DialogResult.Cancel      // Pulsante Cancel
DialogResult.Yes         // Pulsante Yes
DialogResult.No          // Pulsante No
DialogResult.Abort       // Pulsante Abort
DialogResult.Retry       // Pulsante Retry
DialogResult.Ignore      // Pulsante Ignore

📋 Esercizio 2: Gestionale Clienti con Dettagli

▶ Obiettivo

Lista clienti. Clicchi “Dettagli” → si apre finestra con tutte le info del cliente!

1

Crea Classe Cliente

// Classe per rappresentare un cliente
public class Cliente
{
    public string Nome { get; set; }
    public string Cognome { get; set; }
    public string Email { get; set; }
    public string Telefono { get; set; }
    public string Citta { get; set; }
    
    public string NomeCompleto => $"{Nome} {Cognome}";
}

2

Form Principale (con ListBox)

public partial class FormPrincipale : Form
{
    private List clienti = new List();

    public FormPrincipale()
    {
        InitializeComponent();
        AggiungiClientiDiEsempio();
        CaricaLista();
    }

    private void AggiungiClientiDiEsempio()
    {
        clienti.Add(new Cliente 
        { 
            Nome = "Mario", Cognome = "Rossi", 
            Email = "mario@email.it", Telefono = "333-1234567", 
            Citta = "Roma" 
        });
        
        clienti.Add(new Cliente 
        { 
            Nome = "Laura", Cognome = "Bianchi", 
            Email = "laura@email.it", Telefono = "333-7654321", 
            Citta = "Milano" 
        });
    }

    private void CaricaLista()
    {
        lst_clienti.Items.Clear();
        foreach (Cliente c in clienti)
        {
            lst_clienti.Items.Add(c.NomeCompleto);
        }
    }

    // ═══════════════════════════════════════════
    // PULSANTE: Mostra Dettagli
    // ═══════════════════════════════════════════
    private void btn_dettagli_Click(object sender, EventArgs e)
    {
        if (lst_clienti.SelectedIndex == -1)
        {
            MessageBox.Show("Seleziona un cliente!", "Attenzione", 
                          MessageBoxButtons.OK, MessageBoxIcon.Warning);
            return;
        }

        // Prendi il cliente selezionato
        Cliente clienteSelezionato = clienti[lst_clienti.SelectedIndex];

        // Apri finestra dettagli (MODALE)
        FormDettagliCliente formDettagli = new FormDettagliCliente(clienteSelezionato);
        formDettagli.ShowDialog();
    }
}

3

FormDettagliCliente (Form Secondario)

public partial class FormDettagliCliente : Form
{
    private Cliente cliente;

    public FormDettagliCliente(Cliente c)
    {
        InitializeComponent();
        
        this.cliente = c;
        
        // Mostra i dettagli
        MostraDettagli();
    }

    private void MostraDettagli()
    {
        lbl_nome.Text = $"Nome: {cliente.Nome}";
        lbl_cognome.Text = $"Cognome: {cliente.Cognome}";
        lbl_email.Text = $"Email: {cliente.Email}";
        lbl_telefono.Text = $"Telefono: {cliente.Telefono}";
        lbl_citta.Text = $"Città: {cliente.Citta}";
        
        this.Text = $"Dettagli - {cliente.NomeCompleto}";
    }

    private void btn_chiudi_Click(object sender, EventArgs e)
    {
        this.Close();
    }
}

📂 Dialog Predefiniti di Windows

Windows ha già pronti dei dialog per operazioni comuni! Non devi crearli da zero!

📂 OpenFileDialog

Finestra “Apri File”

OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "File di testo|*.txt|Tutti i file|*.*";
ofd.Title = "Seleziona un file";

if (ofd.ShowDialog() == DialogResult.OK)
{
    string percorso = ofd.FileName;
    MessageBox.Show($"Hai scelto: {percorso}");
}

💾 SaveFileDialog

Finestra “Salva File”

SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "File di testo|*.txt";
sfd.DefaultExt = "txt";
sfd.FileName = "documento";

if (sfd.ShowDialog() == DialogResult.OK)
{
    string percorso = sfd.FileName;
    File.WriteAllText(percorso, "Contenuto");
}

🎨 ColorDialog

Scegli un colore

ColorDialog cd = new ColorDialog();

if (cd.ShowDialog() == DialogResult.OK)
{
    Color colore = cd.Color;
    this.BackColor = colore;
}

🔤 FontDialog

Scegli un font

FontDialog fd = new FontDialog();

if (fd.ShowDialog() == DialogResult.OK)
{
    Font font = fd.Font;
    lbl_testo.Font = font;
}

📝 Esercizio 3: Mini Editor di Testo

▶ Obiettivo

Editor con menu File (Nuovo, Apri, Salva) e Formato (Font, Colore)!

EditorTesto.cs (Versione Completa)
using System;
using System.IO;
using System.Windows.Forms;

namespace EditorTesto
{
    public partial class Form1 : Form
    {
        private string percorsoFileCorrente = "";

        public Form1()
        {
            InitializeComponent();
        }

        // ═══════════════════════════════════════════
        // MENU: File → Nuovo
        // ═══════════════════════════════════════════
        private void nuovoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(txt_editor.Text))
            {
                DialogResult ris = MessageBox.Show(
                    "Vuoi salvare le modifiche?", 
                    "Nuovo File",
                    MessageBoxButtons.YesNoCancel, 
                    MessageBoxIcon.Question);

                if (ris == DialogResult.Yes)
                {
                    SalvaFile();
                }
                else if (ris == DialogResult.Cancel)
                {
                    return;
                }
            }

            txt_editor.Clear();
            percorsoFileCorrente = "";
            this.Text = "Editor - Nuovo file";
        }

        // ═══════════════════════════════════════════
        // MENU: File → Apri
        // ═══════════════════════════════════════════
        private void apriToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "File di testo (*.txt)|*.txt|Tutti i file (*.*)|*.*";
            ofd.Title = "Apri file";

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    txt_editor.Text = File.ReadAllText(ofd.FileName);
                    percorsoFileCorrente = ofd.FileName;
                    this.Text = $"Editor - {Path.GetFileName(ofd.FileName)}";
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"Errore: {ex.Message}", "Errore", 
                                  MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        // ═══════════════════════════════════════════
        // MENU: File → Salva
        // ═══════════════════════════════════════════
        private void salvaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SalvaFile();
        }

        private void SalvaFile()
        {
            if (string.IsNullOrEmpty(percorsoFileCorrente))
            {
                // Prima volta: chiedi dove salvare
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.Filter = "File di testo (*.txt)|*.txt";
                sfd.DefaultExt = "txt";
                sfd.FileName = "documento";

                if (sfd.ShowDialog() == DialogResult.OK)
                {
                    percorsoFileCorrente = sfd.FileName;
                }
                else
                {
                    return;
                }
            }

            try
            {
                File.WriteAllText(percorsoFileCorrente, txt_editor.Text);
                MessageBox.Show("File salvato!", "Successo", 
                              MessageBoxButtons.OK, MessageBoxIcon.Information);
                this.Text = $"Editor - {Path.GetFileName(percorsoFileCorrente)}";
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Errore: {ex.Message}", "Errore", 
                              MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        // ═══════════════════════════════════════════
        // MENU: Formato → Font
        // ═══════════════════════════════════════════
        private void fontToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FontDialog fd = new FontDialog();
            fd.Font = txt_editor.Font;

            if (fd.ShowDialog() == DialogResult.OK)
            {
                txt_editor.Font = fd.Font;
            }
        }

        // ═══════════════════════════════════════════
        // MENU: Formato → Colore
        // ═══════════════════════════════════════════
        private void coloreToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ColorDialog cd = new ColorDialog();
            cd.Color = txt_editor.ForeColor;

            if (cd.ShowDialog() == DialogResult.OK)
            {
                txt_editor.ForeColor = cd.Color;
            }
        }

        // ═══════════════════════════════════════════
        // MENU: File → Esci
        // ═══════════════════════════════════════════
        private void esciToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}

🎓 Riepilogo

✅ Show() vs ShowDialog()

  • Show = non blocca
  • ShowDialog = blocca (modale)
✅ Passare Dati

  • Costruttori con parametri
  • Proprietà pubbliche
✅ Dialog Predefiniti

  • OpenFileDialog
  • SaveFileDialog
  • ColorDialog, FontDialog

🚀 Prossima Lezione

Hai imparato a creare app multi-finestra! Prossima lezione:
Validazione Avanzata con ErrorProvider, MaskedTextBox e UX professionale! ✨

Torna in alto