Press "Enter" to skip to content

Windows forms alcune funzionalità per gestire i controlli

In questo articolo, mostro alcune delle operazioni che si possono fare per accedere e modificare i dati e l’aspetto di alcuni controlli su una Windows Form, in risposta a Questo Thread sul forum italiano Microsoft per lo sviluppo in C#.

La domanda era “Si può accedere ai controlli di una form usando il loro nome?”.

Ovviamente la risposta è Si, vediamo la form che ho disegnato:

Ho inserito vari controlli, pannelli e splitter per mostrare alcune cose che possiamo fare su una form.

La prima cosa da fare con i controlli con cui vogliamo interagire da codice è dar loro un nome che abbia senso.

In questo caso, il Button selezionato l’ho chiamato btnChangeButtonColor, perché quello che farà al suo click è modificare il background color dei button della form.

Prima di mostrare il codice delle varie azioni, c’è una modifica da fare a livello di program.cs per evitare frustrazioni.

static class Program
	{
		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main()
		{
			//Disattiviamo gli stili di windows
			//Application.EnableVisualStyles();
			//Application.SetCompatibleTextRenderingDefault(false);
			Application.Run(new FrmMain());
		}
	}

Ho modificato il codice del main, commentando 2 righe che sono inserite automaticamente nel Main dal Template dei programmi Windows Forms e servono a fare in modo che i nostri programmi assumano i colori e la forma del tema di WIndows correntemente selezionato dall’utente.

Questa è una funzionalità ottima per programmi gestionali, perché tutto ha lo stesso aspetto, ma quando è attiva, i button, le textbox e il resto dei controlli non modificano il proprio colore (nel mio caso il Background) ma mantengono quello del tema corrente di Windows.

Preparazioni

Prima di spiegare le funzioni facciamo un giro sul codice di preparazione, per permettere di creare gli effetti di modifica casuale dei dati da parte dei bottoni, ho creato alcune collezioni di dati che verranno usate allo scopo, sono state inizializzate nel costruttore della Form.

List<string> mNomi;
List<string> mCognomi;
List<string> mIndirizzi;
List<string> mCitta;
List<Color> mColors;
List<Button> mButtons;
private Random mRnd;

la m che fa da prefisso a tutti i nomi la uso per indicare che sono delle variabili Member ovvero definite a livello di classe.

Il contenuto delle collezioni, dovrebbe essere chiaro dal nome delle stesse, sono dati che saranno usati in modo casuale dai metodi implementati sui vari Button.

La collezione Buttons verrà inizializzata invece dal metodo che Lista i componenti della Form andando a leggere quelli di tipo button per poterne poi variare il colore di sfondo.

L’oggetto Random dal nome dovrebbe suggerirvi qualcosa, ne parliamo un po’ più in giù.

public FrmMain()
{
	InitializeComponent();
	mNomi = new List<string>()
	{
		"Mario",
		"Filippo",
		"Michele",
		"Francesco",
		"Giorgio",
		"Roberto",
		"Giovanna",
		"Patrizia",
		"Maria",
		"Marina",
		"Giuliana"
	};

Le collection sono inizializzate nel costruttore, questa è la prima e ci fornisce i Nomi delle persone.

mCognomi = new List<string>()
{
	"Rossi",
	"Guglielmi",
	"Rosi",
	"De Marini",
	"Luciani",
	"Toscanini",
	"Bacchetti",
	"Chiarvesio",
	"Peres",
	"Kunz",
	"Damiani",
	"Gorghi"
};

La seconda è la collezione dei cognomi.

mIndirizzi = new List<string>()
{
	"Viale Venezia, 189",
	"Viale Monza, 890",
	"Via Monte Grappa, 78",
	"Via Poscolle, 7",
	"Via del Gelso, 97",
	"Via Mercato vecchio, 65",
	"Piazza I° Maggio, 65",
	"Piazzale G.B. Cella 5",
	"Via Lanceri di Sardegna 44",
	"Vicolo Muratti, 22",
	"Viale delle Ferriere, 88"

};

La terza collezione è quella degli indirizzi.

mCitta = new List<string>()
{
	"Buttrio (UD)",
	"Roma (RM)",
	"Milano (MI)",
	"Mortegliano (UD)",
	"Lignano Sabbiadoro (UD)",
	"San Vito al Tagliamento (PN)",
	"San Stino di Livenza (TV)",
	"Treviso (TV)",
	"Trieste (TS)",
	"Bibione (VE)",
	"Jesolo (VE)",
};

La quarta collezione sono le città e province

mColors = new List<Color>()
{
	Color.Red,
	Color.PowderBlue,
	Color.Plum,
	Color.Pink,
	Color.Lime,
	Color.Yellow,
	Color.Orange,
	Color.Salmon,
	Color.LightBlue,
	Color.LightCyan,
	Color.OldLace

};

La quinta sono i colori con cui dipingeremo gli sfondi delle Textbox e dei Button.

mRnd = new Random((int)DateTime.Now.Ticks);
mButtons = new List<Button>();

Infine, generiamo la collection dei button, che riempiremo nel metodo che lista i controlli e creiamo un oggetto Random, che viene fornito da .Net per generare numeri casuali. Lo userò per leggere in modo casuale il contenuto delle 5 collezioni e creare Persone ed indirizzi e selezionare colori per gli sfondi. 

Ed ora che abbiamo preparato il necessario partiamo con il codice importante.

Lista i controlli della Form

Listare tutti i controlli (e quindi sapere come accedere a tali controlli) di una Form è una cosa molto semplice, anche se prevede l’uso di una funzione ricorsiva, in quanto su una form mediamente complessa come la nostra vi sono controlli contenitore in cui vengono inseriti altri controlli e contenitori nei contenitori. Ecco il motivo di avere una funzione ricorsiva.

Nel nostro caso, abbiamo la seguente situazione:

  • La Form contiene 3 controlli, due Panel e uno Splitter verticale
  • Il pannello di destra contiene 6 button
  • Il pannello di sinistra contiene a sua volta un Panel, Uno splitter ed una Textbox Multilinea
  • Il pannello in alto contiene le label, le textbox, le 3 checkbox e infine una Groupbox
  • La groupbox a sua volta contiene 4 radiobutton

La descrizione ci fa notare quanto con poco abbiamo creato qualcosa di complesso.

Ecco il codice che sta dietro al button BtnListControls:

private void BtnListControls_Click(object sender, EventArgs e)
{
	try
	{
		StringBuilder sb = new StringBuilder();
		sb.AppendLine("Lista dei controlli della form");
		sb.AppendLine(new string('-', 80));
		mButtons.Clear();
		FindControls(this.Controls, sb);

		ResultText.Text = sb.ToString();

	}
	catch (Exception ex)
	{
		MessageBox.Show(ex.Message);
	}
}

Per listare i controlli creiamo uno StringBuilder in cui scriveremo la nostra lista, scriviamo un titolo, tracciamo una riga di trattini, e poi cancelliamo la collezione di oggetti Button (serve perché potremmo cliccare più volte il button e alla seconda volta raddoppieremmo la collection e questo darebbe origine a cose strane). Dopo di che, chiamiamo la funzione ricorsiva FindControls a cui passiamo la lista di controlli della Form (this.Controls) e lo StringBuilder per compilare il testo.

Eseguita la funzione, copiamo il contenuto dello StringBuilder nel Text della Textbox Multilinea ResultText.

private void FindControls(Control.ControlCollection controls, StringBuilder sb)
{
	foreach (Control ctl in controls)
	{
		sb.AppendFormat("{0} - {1}", ctl.GetType().Name, ctl.Name);
		sb.AppendLine();
		if (ctl.Controls != null && ctl.Controls.Count > 0)
		{
			FindControls(ctl.Controls, sb);
		}
		if (ctl is Button)
		{
			Button btn = ctl as Button;

			if (btn != null)
			{
				mButtons.Add(btn);
				if (btn.Name == "btnDynamic1")
				{
					//prima tolgo l'event handler
					//Altrimenti se rieseguo questo
					//pezzo di codice, viene assegnato (ed eseguito) più volte
					//potete provare e vedere l'effetto che fa
					btn.Click -= BtnDynamic1_Click;
					btn.Click += BtnDynamic1_Click;
					btn.Text = "Colora textbox";
				}
				if (btn.Name == "btnDynamic2")
				{
					//prima tolgo l'event handler (come sopra)
					btn.Click -= BtnDynamic2_Click;
					btn.Click += BtnDynamic2_Click;
					btn.Text = "Cancella Result Text";
				}
				if (btn.Name == "btnDynamic3")
				{
					//prima tolgo l'event handler (come sopra)
					btn.Click -= BtnDynamic3_Click;
					btn.Click += BtnDynamic3_Click;
					btn.Text = "Cambia opzioni";

				}
			}
		}
	}
}

Il codice qui sopra, riporta la funzione ricorsiva, che è piuttosto semplice, infatti si risolve nelle prime 6 righe, il codice che segue serve solo per riconoscere i Button, inizializzare dinamicamente il nome e l’event handler dei 3 button Dynamic e riempire la collection dei Button in modo da poterli colorare.

La ricorsione è così descritta:

  1. Per ognuno dei controlli contenuti nella collezione controls che ti è stata passata,
  2. Aggiungi allo StringBuilder il Nome della classe del controllo ed il nome dell’istanza del controllo.
  3. Aggiungi un accapo allo StringBuilder.
  4. Se il controllo ha a sua volta dei controlli nella sua lista Controls, chiama te stessa (ricorsione).

Il codice del primo bottone dinamico, cambia colore alle textbox

private void BtnDynamic1_Click(object sender, EventArgs e)
{
	int idx = mRnd.Next(0, 10);
	txtCittaProvincia.BackColor = mColors[idx];
	idx = mRnd.Next(0, 10);
	txtNome.BackColor = mColors[idx];
	idx = mRnd.Next(0, 10);
	txtIndirizzo.BackColor = mColors[idx];
	idx = mRnd.Next(0, 10);
	txtCognome.BackColor = mColors[idx];

}

Codice molto semplice, tradotto in: 

  • Crea un numero casuale tra 0 e 10
  • Prendi il colore con l’indice generato e assegnalo a txtCittaProvincia.BackColor
  • Ripeti per le altre 3 textbox.

Il codice del secondo bottone dinamico, cancella il ResultText

private void BtnDynamic2_Click(object sender, EventArgs e)
{
	ResultText.Text = null;
}

Ancor più semplice, metti a null il testo della textbox multilinea.

Il codice del terzo bottone dinamico, Cambia casualmente le options

private void BtnDynamic3_Click(object sender, EventArgs e)
{
	int val = mRnd.Next(0, 40);
	if (val < 10)
	{
		optInsufficiente.Checked = true;
	}
	else if (val >= 10 && val < 20)
	{
		optSufficiente.Checked = true;
	}
	else if (val >= 20 && val < 30)
	{
		optBuono.Checked = true;
	}
	else if (val >= 30 )
	{
		optOttimo.Checked = true;
	}

}

In questo caso, creiamo un numero casuale fra 0 e 40 ed in base alla decina in cui si trova mettiamo a True l’option button relativo. Faccio notare come in Windows Forms, quando una serie di RadioButton sono posti in una GroupBox o un Panel o altro contenitore, automaticamente ponendo uno di essi a True tutti gli altri vengono posti a False.

Il codice del button Write Some Text crea dati casuali nelle 4 textbox

private void btnWriteSomeText_Click(object sender, EventArgs e)
{
	try
	{
		int idx = mRnd.Next(0, 10);
		txtNome.Text = mNomi[idx];
		idx = mRnd.Next(0, 10);
		txtCognome.Text = mCognomi[idx];
		idx = mRnd.Next(0, 10);
		txtIndirizzo.Text = mIndirizzi[idx];
		idx = mRnd.Next(0, 10);
		txtCittaProvincia.Text = mCitta[idx];
	}
	catch (Exception ex)
	{
		MessageBox.Show(ex.Message);
	}
}

Nel caso del Button WriteSomeText, usiamo ancora il Randomizzatore per generare un indice fra 0 e 10 e con tale indice estraiamo un dato dalle collezioni di nomi, cognomi, indirizzi e città.

 

Il button che cambia colore ai button

private void btnChangeButtonColor_Click(object sender, EventArgs e)
{
	try
	{
		foreach (Button btn in mButtons)
		{
			int idx = mRnd.Next(0, 10);
			btn.BackColor = mColors[idx];
		}
	}
	catch (Exception ex)
	{
		MessageBox.Show(ex.Message);
	}
}

In questo caso, utilizziamo la collection dei Button che abbiamo costruito e generiamo un colore casuale per ognuno dei button aggiornando il background dei button stessi.

In questo breve articolo, dedicato ai principianti, abbiamo illustrato come fare ad accedere ai controlli e alle loro proprietà all’interno del codice di una Windows Form.