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:
Inserisci UN nome alla volta: "Mario"
π ListBox:
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.
- 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
- 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();
}
}
}
- π¬ 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!
- 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
- 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Γ !
- Interfaccia
- TextBox:
txtTaskβ Descrizione task - ComboBox:
cmbPrioritaβ PrioritΓ (Bassa/Media/Alta) - Button:
btnAggiungiβ Aggiungi task - Button:
btnRimuoviβ Rimuovi task selezionato - ListBox:
lstTaskβ Elenco task
- 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
Nelle Prossime Lezioni:
- π 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!
π Teoria collegata (percorso C# β il linguaggio, esempi in console): Array e collezioni.
