ListBox e ComboBox: Teoria e Pratica

Gestisci elenchi di dati con interfacce professionali

🎯 Cosa Imparerai in Questa Lezione

Hai già imparato a raccogliere un singolo dato alla volta con TextBox.
Ma cosa succede quando devi gestire elenchi di elementi?
Prodotti in un inventario, servizi di un hotel, task da completare…

Qui entrano in gioco ListBox e ComboBox: i controlli
più potenti per gestire liste di dati!

✨ Dalla TextBox alla ListBox

📝 TextBox (Lezione 3):

Inserisci UN nome alla volta: “Mario”

📋 ListBox (Lezione 4):

Gestisci MOLTI nomi: Mario, Luigi, Anna, Sara…

📚 Controlli che Padroneggerai
  • ListBox: Lista visibile di elementi (vedi tutti, selezioni uno o più)
  • ComboBox: Menu a tendina (risparmia spazio, selezioni solo uno)
  • List<string>: Lista dinamica che può crescere
  • foreach: Scorrere tutti gli elementi di una lista

🤔 ListBox vs ComboBox: Qual è la Differenza?

📋 ListBox

TUTTI GLI ELEMENTI VISIBILI

□ Mela

■ Banana

□ Arancia

□ Pera

□ Kiwi

💡 Quando usarla:

  • Lista prodotti inventario
  • Elenco servizi disponibili
  • Task da completare
  • File da processare
✅ Vantaggi:

  • Vedi subito tutti gli elementi
  • Puoi selezionarne più di uno
  • Ideale per liste lunghe con scrollbar

🔽 ComboBox

MENU A TENDINA

Abbigliamento ▼

Abbigliamento

Detersivi

Casa

Alimentari

Sport

💡 Quando usarla:

  • Categorie prodotto
  • Tipi di camera hotel
  • Priorità task (Bassa/Media/Alta)
  • Elenchi con poche opzioni
✅ Vantaggi:

  • Occupa poco spazio
  • Elegante per poche opzioni
  • Perfetta per categorizzazioni

🎯 Regola Pratica:

ListBox = Lista completa visibile (come un menu ristorante aperto)
ComboBox = Menu compatto (come un menu a tendina del telefono)

📋 Proprietà e Metodi Fondamentali

🔑 Proprietà Principali

Proprietà Cosa Rappresenta Esempio ListBox Esempio ComboBox
Items La collezione di tutti gli elementi nella lista lstProdotti.Items cmbCategoria.Items
SelectedItem L’elemento attualmente selezionato lstProdotti.SelectedItem cmbCategoria.SelectedItem
SelectedIndex La posizione dell’elemento selezionato (0=primo) lstProdotti.SelectedIndex cmbCategoria.SelectedIndex
Text Il testo dell’elemento selezionato lstProdotti.Text cmbCategoria.Text

⚡ Metodi Principali

Metodo Cosa Fa Sintassi
Items.Add() Aggiunge un elemento alla fine della lista lstProdotti.Items.Add("Mela");
Items.Remove() Rimuove un elemento specifico lstProdotti.Items.Remove("Mela");
Items.RemoveAt() Rimuove l’elemento in una posizione specifica lstProdotti.Items.RemoveAt(0);
Items.Clear() Rimuove TUTTI gli elementi lstProdotti.Items.Clear();
Items.Insert() Inserisce un elemento in una posizione specifica lstProdotti.Items.Insert(0, "Banana");
⚠️ IMPORTANTE: SelectedIndex = -1

Quando nessun elemento è selezionato, SelectedIndex vale -1.
Devi sempre controllare questo valore prima di usare SelectedItem!

// ❌ SBAGLIATO - può crashare!
string prodotto = lstProdotti.SelectedItem.ToString();

// ✅ CORRETTO - controlla prima
if (lstProdotti.SelectedIndex != -1)
{
    string prodotto = lstProdotti.SelectedItem.ToString();
    MessageBox.Show($"Hai selezionato: {prodotto}");
}
else
{
    MessageBox.Show("Seleziona un prodotto prima!");
}

📦 Teoria: List<string> – La Lista Dinamica

🤔 Perché Usare una List<string>?

La ListBox mostra gli elementi all’utente, ma dove li memorizzi nel codice?
Qui entra in gioco List<string>: una lista che può crescere
dinamicamente senza limiti!

🎯 Analogia: La List<string> è come uno scaffale elastico.
Puoi aggiungere infiniti oggetti, e lo scaffale si allunga automaticamente!

🔑 Confronto: Array vs List

📦 Array (dimensione fissa):

// Devi dichiarare la dimensione SUBITO
string[] frutti = new string[3];
frutti[0] = "Mela";
frutti[1] = "Banana";
frutti[2] = "Arancia";
// Non puoi aggiungerne altri!

📋 List (dimensione dinamica):

// Lista vuota che può crescere
List<string> frutti = new List<string>();
frutti.Add("Mela");
frutti.Add("Banana");
frutti.Add("Arancia");
frutti.Add("Pera"); // Continua all'infinito!

⚡ Metodi Principali di List<string>

Esempio Completo
// 1️⃣ CREARE una lista vuota
List<string> prodotti = new List<string>();

// 2️⃣ AGGIUNGERE elementi
prodotti.Add("Laptop");
prodotti.Add("Mouse");
prodotti.Add("Tastiera");

// 3️⃣ RIMUOVERE elemento specifico
prodotti.Remove("Mouse");  // Rimuove "Mouse"

// 4️⃣ RIMUOVERE elemento per posizione
prodotti.RemoveAt(0);  // Rimuove il primo (Laptop)

// 5️⃣ VERIFICARE se contiene un elemento
if (prodotti.Contains("Tastiera"))
{
    MessageBox.Show("Abbiamo tastiere!");
}

// 6️⃣ CONTARE gli elementi
int quantità = prodotti.Count;  // Quanti prodotti?

// 7️⃣ PULIRE tutta la lista
prodotti.Clear();  // Rimuove tutto!

💡 Pattern Tipico: List + ListBox

La best practice è usare una List<string> per memorizzare i dati,
e poi “sincronizzarla” con la ListBox quando cambia:

// Lista dati (dietro le quinte)
private List<string> listaProdotti = new List<string>();

// Metodo per aggiungere prodotto
private void AggiungiProdotto(string prodotto)
{
    // 1. Aggiungi alla List
    listaProdotti.Add(prodotto);
    
    // 2. Aggiorna la ListBox
    AggiornaListBox();
}

// Metodo per sincronizzare ListBox con List
private void AggiornaListBox()
{
    lstProdotti.Items.Clear();  // Pulisci la ListBox
    
    foreach (string prodotto in listaProdotti)
    {
        lstProdotti.Items.Add(prodotto);  // Riempi con i dati aggiornati
    }
}

🔄 Teoria: Il Ciclo foreach

🤔 Cos’è il foreach?

Il foreach è un ciclo che scorre automaticamente tutti gli
elementi di una lista, uno per uno. È perfetto per processare tutti i prodotti, tutti i
task, tutti i servizi…

🎯 Analogia: Il foreach è come un nastro trasportatore che porta
ogni oggetto davanti a te, uno alla volta, senza che tu debba fare nulla!

Sintassi foreach
// foreach (tipo nomeVariabile in collezione)
foreach (string prodotto in listaProdotti)
{
    // Qui "prodotto" rappresenta UN elemento alla volta
    MessageBox.Show(prodotto);
}

// Esempio pratico:
List<string> frutti = new List<string> { "Mela", "Banana", "Arancia" };

foreach (string frutto in frutti)
{
    Console.WriteLine(frutto);
}

// Output:
// Mela
// Banana
// Arancia

🔑 Confronto: for vs foreach

for (tradizionale):

// Devi gestire l'indice manualmente
for (int i = 0; i < frutti.Count; i++)
{
    string frutto = frutti[i];
    Console.WriteLine(frutto);
}

foreach (moderno e pulito):

// Automatico, nessun indice!
foreach (string frutto in frutti)
{
    Console.WriteLine(frutto);
}

💡 Quando Usare foreach
  • ✅ Quando devi scorrere TUTTI gli elementi
  • ✅ Quando non ti serve sapere la posizione (indice)
  • ✅ Per rendere il codice più leggibile
  • ❌ Non usarlo se devi modificare la lista mentre la scorri (usa for normale)

🏪 Esercizio 1: Gestionale Inventario Semplice

Crea un’applicazione per gestire un inventario di prodotti.
L’utente può aggiungere prodotti con nome, prezzo, quantità e categoria,
visualizzarli in una ListBox e rimuoverli.

1

Interfaccia Grafica da Creare

  • TextBox: txtNome → Nome prodotto
  • TextBox: txtPrezzo → Prezzo
  • TextBox: txtQuantita → Quantità
  • ComboBox: cmbCategoria → Categoria prodotto
  • Button: btnAggiungi → Aggiungi prodotto
  • Button: btnRimuovi → Rimuovi prodotto selezionato
  • ListBox: lstInventario → Visualizza elenco prodotti

2

Il Codice Completo con Spiegazioni

Form1.cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace InventarioSemplice
{
    public partial class Form1 : Form
    {
        // ═══════════════════════════════════════
        // VARIABILE GLOBALE: Lista prodotti
        // ═══════════════════════════════════════
        private List<string> listaProdotti;

        public Form1()
        {
            InitializeComponent();
            
            // Inizializza la lista vuota
            listaProdotti = new List<string>();
            
            // Popola la ComboBox categorie
            InizializzaCategorie();
        }

        // ═══════════════════════════════════════
        // METODO: Popola ComboBox categorie
        // ═══════════════════════════════════════
        private void InizializzaCategorie()
        {
            cmbCategoria.Items.Add("Scegli categoria");
            cmbCategoria.Items.Add("Abbigliamento");
            cmbCategoria.Items.Add("Detersivi");
            cmbCategoria.Items.Add("Casa");
            cmbCategoria.Items.Add("Alimentari");
            cmbCategoria.Items.Add("Sport");
            cmbCategoria.Items.Add("Elettronica");
            
            // Seleziona la prima opzione di default
            cmbCategoria.SelectedIndex = 0;
        }

        // ═══════════════════════════════════════
        // EVENTO: Click su Aggiungi
        // ═══════════════════════════════════════
        private void btnAggiungi_Click(object sender, EventArgs e)
        {
            // 1️⃣ VALIDAZIONE: Controlla campi vuoti
            if (!ControllaCampi())
                return;  // Esci se non valido

            // 2️⃣ VALIDAZIONE: Controlla che prezzo e quantità siano numeri
            if (!ValidaPrezzo(txtPrezzo.Text) || !ValidaQuantita(txtQuantita.Text))
                return;

            // 3️⃣ CONVERSIONE prezzo con formattazione
            double prezzo = Convert.ToDouble(txtPrezzo.Text);
            string prezzoFormattato = prezzo.ToString("C");  // Es: € 5,50

            // 4️⃣ CREA la stringa prodotto
            string prodotto = $"{txtNome.Text} - {txtQuantita.Text} - {prezzoFormattato} - {cmbCategoria.SelectedItem}";

            // 5️⃣ AGGIUNGI alla lista
            listaProdotti.Add(prodotto);

            // 6️⃣ AGGIORNA la ListBox
            AggiornaInventario();

            // 7️⃣ PULISCI i campi
            PulisciCampi();
        }

        // ═══════════════════════════════════════
        // METODO: Controlla campi vuoti
        // ═══════════════════════════════════════
        private bool ControllaCampi()
        {
            if (string.IsNullOrEmpty(txtNome.Text))
            {
                MessageBox.Show("Inserisci il nome del prodotto!", 
                              "Attenzione",
                              MessageBoxButtons.OK, 
                              MessageBoxIcon.Warning);
                return false;
            }
            
            if (string.IsNullOrEmpty(txtPrezzo.Text))
            {
                MessageBox.Show("Inserisci il prezzo!", 
                              "Attenzione",
                              MessageBoxButtons.OK, 
                              MessageBoxIcon.Warning);
                return false;
            }
            
            if (string.IsNullOrEmpty(txtQuantita.Text))
            {
                MessageBox.Show("Inserisci la quantità!", 
                              "Attenzione",
                              MessageBoxButtons.OK, 
                              MessageBoxIcon.Warning);
                return false;
            }
            
            if (cmbCategoria.SelectedIndex == 0)
            {
                MessageBox.Show("Seleziona una categoria!", 
                              "Attenzione",
                              MessageBoxButtons.OK, 
                              MessageBoxIcon.Warning);
                return false;
            }
            
            return true;  // Tutto OK!
        }

        // ═══════════════════════════════════════
        // METODO: Valida prezzo (deve essere numero)
        // ═══════════════════════════════════════
        private bool ValidaPrezzo(string testo)
        {
            try
            {
                Convert.ToDouble(testo);
                return true;
            }
            catch
            {
                MessageBox.Show("Il prezzo deve essere un numero valido!", 
                              "Errore",
                              MessageBoxButtons.OK, 
                              MessageBoxIcon.Error);
                return false;
            }
        }

        // ═══════════════════════════════════════
        // METODO: Valida quantità (deve essere intero)
        // ═══════════════════════════════════════
        private bool ValidaQuantita(string testo)
        {
            try
            {
                Convert.ToInt32(testo);
                return true;
            }
            catch
            {
                MessageBox.Show("La quantità deve essere un numero intero!", 
                              "Errore",
                              MessageBoxButtons.OK, 
                              MessageBoxIcon.Error);
                return false;
            }
        }

        // ═══════════════════════════════════════
        // METODO: Aggiorna ListBox con i prodotti
        // ═══════════════════════════════════════
        private void AggiornaInventario()
        {
            // 1. Pulisci la ListBox
            lstInventario.Items.Clear();
            
            // 2. Riempi con tutti i prodotti dalla List
            foreach (string prodotto in listaProdotti)
            {
                lstInventario.Items.Add(prodotto);
            }
        }

        // ═══════════════════════════════════════
        // METODO: Pulisce i campi input
        // ═══════════════════════════════════════
        private void PulisciCampi()
        {
            txtNome.Text = "";
            txtPrezzo.Text = "";
            txtQuantita.Text = "";
            cmbCategoria.SelectedIndex = 0;
            
            // Metti il focus sul primo campo
            txtNome.Focus();
        }

        // ═══════════════════════════════════════
        // EVENTO: Click su Rimuovi
        // ═══════════════════════════════════════
        private void btnRimuovi_Click(object sender, EventArgs e)
        {
            // 1️⃣ Controlla che ci sia una selezione
            if (lstInventario.SelectedIndex == -1)
            {
                MessageBox.Show("Seleziona un prodotto da eliminare!", 
                              "Attenzione",
                              MessageBoxButtons.OK, 
                              MessageBoxIcon.Warning);
                return;
            }

            // 2️⃣ Rimuovi dalla List (alla posizione selezionata)
            listaProdotti.RemoveAt(lstInventario.SelectedIndex);

            // 3️⃣ Aggiorna la ListBox
            AggiornaInventario();
        }
    }
}

3

🎬 Come Funziona? (Flusso Completo)

Scenario: Aggiungere un Prodotto

1️⃣ L’utente compila:

  • Nome: “Maglietta Nike”
  • Prezzo: “29.99”
  • Quantità: “5”
  • Categoria: “Abbigliamento”

2️⃣ Clicca “Aggiungi”:

  • ControllaCampi() → ✅ Tutti compilati
  • ValidaPrezzo() → ✅ “29.99” è un numero
  • ValidaQuantita() → ✅ “5” è un intero

3️⃣ Crea la stringa:

"Maglietta Nike - 5 - € 29,99 - Abbigliamento"

4️⃣ Aggiunge alla List:

listaProdotti.Add(prodotto);

5️⃣ Aggiorna la ListBox:

Pulisce lstInventario.Items e la riempie con tutti i prodotti dalla List usando foreach

✅ Risultato Visibile:

□ Maglietta Nike – 5 – € 29,99 – Abbigliamento

🏨 Esercizio 2: Prenotazione Hotel

Crea un sistema di prenotazione hotel dove l’utente sceglie il tipo di camera
(Singola/Doppia/Suite) e può aggiungere servizi extra da una lista.
L’app calcola il prezzo totale!

1

Interfaccia

  • ComboBox: cmbCamera → Tipi camera (Singola €80, Doppia €120, Suite €200)
  • ListBox: lstServiziDisponibili → Servizi disponibili
  • ListBox: lstServiziScelti → Servizi scelti dall’utente
  • Button: btnAggiungiServizio → Sposta servizio da disponibili a scelti
  • Button: btnRimuoviServizio → Toglie servizio dai scelti
  • Button: btnCalcolaTotale → Calcola il prezzo finale
  • Label: lblTotale → Mostra il totale

2

Codice Semplificato

PrenotazioneHotel.cs
using System;
using System.Windows.Forms;

namespace PrenotazioneHotel
{
    public partial class Form1 : Form
    {
        // Prezzi camere
        private int prezzoSingola = 80;
        private int prezzoDoppia = 120;
        private int prezzoSuite = 200;
        
        // Prezzi servizi
        private int prezzoColazione = 15;
        private int prezzoParcheggio = 10;
        private int prezzoSpa = 25;

        public Form1()
        {
            InitializeComponent();
            InizializzaCamere();
            InizializzaServizi();
        }

        // ═══════════════════════════════════════
        // Popola ComboBox camere
        // ═══════════════════════════════════════
        private void InizializzaCamere()
        {
            cmbCamera.Items.Add("Camera Singola - € 80");
            cmbCamera.Items.Add("Camera Doppia - € 120");
            cmbCamera.Items.Add("Suite - € 200");
            cmbCamera.SelectedIndex = 0;  // Seleziona la prima
        }

        // ═══════════════════════════════════════
        // Popola ListBox servizi disponibili
        // ═══════════════════════════════════════
        private void InizializzaServizi()
        {
            lstServiziDisponibili.Items.Add("Colazione in camera - € 15");
            lstServiziDisponibili.Items.Add("Parcheggio - € 10");
            lstServiziDisponibili.Items.Add("Accesso SPA - € 25");
        }

        // ═══════════════════════════════════════
        // EVENTO: Aggiungi servizio
        // ═══════════════════════════════════════
        private void btnAggiungiServizio_Click(object sender, EventArgs e)
        {
            // Controlla che ci sia una selezione
            if (lstServiziDisponibili.SelectedIndex == -1)
            {
                MessageBox.Show("Seleziona un servizio da aggiungere!");
                return;
            }
            
            // Prendi il servizio selezionato
            string servizio = lstServiziDisponibili.SelectedItem.ToString();
            
            // Aggiungilo ai servizi scelti
            lstServiziScelti.Items.Add(servizio);
            
            // Rimuovilo dai disponibili
            lstServiziDisponibili.Items.RemoveAt(lstServiziDisponibili.SelectedIndex);
        }

        // ═══════════════════════════════════════
        // EVENTO: Rimuovi servizio
        // ═══════════════════════════════════════
        private void btnRimuoviServizio_Click(object sender, EventArgs e)
        {
            // Controlla selezione
            if (lstServiziScelti.SelectedIndex == -1)
            {
                MessageBox.Show("Seleziona un servizio da rimuovere!");
                return;
            }
            
            // Prendi il servizio
            string servizio = lstServiziScelti.SelectedItem.ToString();
            
            // Rimettilo nei disponibili
            lstServiziDisponibili.Items.Add(servizio);
            
            // Toglilo dai scelti
            lstServiziScelti.Items.RemoveAt(lstServiziScelti.SelectedIndex);
        }

        // ═══════════════════════════════════════
        // EVENTO: Calcola totale
        // ═══════════════════════════════════════
        private void btnCalcolaTotale_Click(object sender, EventArgs e)
        {
            int totale = 0;
            
            // 1️⃣ Aggiungi prezzo camera
            string camera = cmbCamera.SelectedItem.ToString();
            if (camera.Contains("Singola"))
                totale += prezzoSingola;
            else if (camera.Contains("Doppia"))
                totale += prezzoDoppia;
            else if (camera.Contains("Suite"))
                totale += prezzoSuite;

            // 2️⃣ Aggiungi prezzi servizi scelti
            foreach (string servizio in lstServiziScelti.Items)
            {
                if (servizio.Contains("Colazione"))
                    totale += prezzoColazione;
                else if (servizio.Contains("Parcheggio"))
                    totale += prezzoParcheggio;
                else if (servizio.Contains("SPA"))
                    totale += prezzoSpa;
            }

            // 3️⃣ Mostra il totale
            lblTotale.Text = $"Totale: € {totale}";
            lblTotale.ForeColor = Color.Green;
        }
    }
}

✅ Esercizio 3: Gestione Task con Priorità

Crea una To-Do List dove l’utente può aggiungere task con un livello di
priorità (Bassa/Media/Alta). I task vengono mostrati con l’etichetta di priorità!

1

Interfaccia

  • TextBox: txtTask → Descrizione task
  • ComboBox: cmbPriorita → Priorità (Bassa/Media/Alta)
  • Button: btnAggiungi → Aggiungi task
  • Button: btnRimuovi → Rimuovi task selezionato
  • ListBox: lstTask → Elenco task

2

Codice Semplificato

GestioneTask.cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace GestioneTask
{
    public partial class Form1 : Form
    {
        private List<string> listaTask;
        
        public Form1()
        {
            InitializeComponent();
            listaTask = new List<string>();
            InizializzaPriorita();
        }

        // ═══════════════════════════════════════
        // Popola ComboBox priorità
        // ═══════════════════════════════════════
        private void InizializzaPriorita()
        {
            cmbPriorita.Items.Add("Bassa");
            cmbPriorita.Items.Add("Media");
            cmbPriorita.Items.Add("Alta");
            cmbPriorita.SelectedIndex = 1;  // Media di default
        }

        // ═══════════════════════════════════════
        // EVENTO: Aggiungi task
        // ═══════════════════════════════════════
        private void btnAggiungi_Click(object sender, EventArgs e)
        {
            // Controlla campo vuoto
            if (string.IsNullOrEmpty(txtTask.Text))
            {
                MessageBox.Show("Scrivi un task!");
                return;
            }
            
            // Crea la stringa task con priorità
            string priorita = cmbPriorita.SelectedItem.ToString();
            string task = $"[{priorita}] {txtTask.Text}";
            
            // Aggiungi alla lista
            listaTask.Add(task);
            
            // Aggiorna ListBox
            AggiornaListaTask();
            
            // Pulisci il campo
            txtTask.Text = "";
            txtTask.Focus();
        }

        // ═══════════════════════════════════════
        // Aggiorna ListBox
        // ═══════════════════════════════════════
        private void AggiornaListaTask()
        {
            lstTask.Items.Clear();
            
            foreach (string task in listaTask)
            {
                lstTask.Items.Add(task);
            }
        }

        // ═══════════════════════════════════════
        // EVENTO: Rimuovi task
        // ═══════════════════════════════════════
        private void btnRimuovi_Click(object sender, EventArgs e)
        {
            if (lstTask.SelectedIndex == -1)
            {
                MessageBox.Show("Seleziona un task da rimuovere!");
                return;
            }
            
            listaTask.RemoveAt(lstTask.SelectedIndex);
            AggiornaListaTask();
        }
    }
}

🎓 Riepilogo: Cosa Hai Imparato

✅ Competenze Acquisite

1️⃣ ListBox e ComboBox

Differenze, quando usare l’uno o l’altro, proprietà Items, SelectedItem, SelectedIndex

2️⃣ List<string>

Lista dinamica che può crescere, Add(), Remove(), RemoveAt(), Contains(), Count

3️⃣ Ciclo foreach

Scorrere automaticamente tutti gli elementi di una lista per processarli

4️⃣ Pattern List + ListBox

Memorizzare dati in List, sincronizzare con ListBox usando metodo AggiornaListBox()

5️⃣ Validazione Completa

Controllo campi vuoti, validazione numeri, gestione SelectedIndex == -1

6️⃣ Progetti Completi

Inventario, Prenotazione Hotel, Gestione Task – applicazioni reali e funzionanti

🚀 Prossimi Passi

📖 Nella Lezione 5 Imparerai:

  • 🚗 Classi Personalizzate: Creare la classe Automobile invece di usare stringhe
  • 📊 List<Automobile>: Liste di oggetti complessi
  • 🔧 Progetti Avanzati: Parco Auto con modifica, ordinamento, statistiche
  • 💾 Persistenza Dati: Salvare e caricare da file CSV/TXT

🎯 Passerai dalle stringhe semplici agli oggetti complessi!

Lezione 4 – ListBox e ComboBox: Teoria e Pratica

Corso C# Completo con Interfaccia Grafica – Da Zero a Esperto

Torna in alto