Login Login
MORE

WIDGETS

Widgets

Wanted articles
Who is online?
Article tools

Difference between revisions of "CSharp:WindowsForm Tips"

From Aino Wiki

Jump to: navigation, search
(Popolamento Bindig)
 
(No difference)

Latest revision as of 16:19, 20 March 2024

Interfaccia

Form

Ricerca di un controllo

Dopo aver aggiunto dinamicamente dei controlli può esser necessario trovarli per cambiarne il contenuto ad es.:
TextBox tbx = this.Controls.Find("textBox1", true).FirstOrDefault() as TextBox;
tbx.Text = "found!";

Aggiornamento Label di un Form

Ecco come aggiornate una label in un loop al fine di tener traccia delle iterazioni. Usando il metodo Refresh:
int portNr = Convert.ToInt32(this.TxtPortServer.Text);
int localPortNr = Convert.ToInt32(this.TxtLocalPort.Text);
string ipServerAddress = this.TxtIPServerAddress.Text;
UdpClient udpClient = new UdpClient(localPortNr);
 
do
{
	//udpClient = new UdpClient(localPortNr);
	byte[] bytes = Encoding.ASCII.GetBytes(this.TxtStringToMessageToSend.Text);
	udpClient.Send(bytes, (int)bytes.Length, ipServerAddress, portNr);
 
	loopCounter++;
	LabelIteration.Text = loopCounter.ToString();
	LabelIteration.Refresh();
	//SSNrIteration.r
	if (ChkLoopInputSentences.Checked)
	{ 
		Thread.Sleep(1 * 1000);
	}
} while (ChkLoopInputSentences.Checked 
	&& loopCounter < maxLoop);
udpClient.Close();

In realtà occorrerebbe creare un thread separato per fare una cosa pulita, comunque sia ci sono degli hacking (dei trucchi per aggirare l'ostacolo) un di questi è l'uso di Application.DoEvents(), da usare al posto del .Refresh().

Aggiornamento usando Threads

DOC MSDN Microsoft
Poichè la UI è un thread a parte occorre in realtà un meccanismo dedicato per avere gli aggiornamenti, ecco come usando i delegati:

delegate void SetTextCallback(string text);
 
private void MioMetodo()
{
	try
	{
		// ...
	}
	catch (Exception ex)
	{
		SSListnerStatus.Text = "Exception!";
		Application.DoEvents();
		AppendTxtUDPListnerLog("[MioMetodo()] " + ex.Message);
		Application.DoEvents();
	}
}
 
private void AppendTxtUDPListnerLog(string text)
{
	if (this.TxtUDPListnerLog.InvokeRequired)
	{
		SetTextCallback d = new SetTextCallback(AppendTxtUDPListnerLog);
		this.Invoke(d, new object[] { text });
	}
	else
	{
		this.TxtUDPListnerLog.Text += text;
	}
}

Cambio stile a controlli dinamicamente

Ecco come cambiare il font ad una label:
mainForm.lblName.Font = new Font("Arial", mainForm.lblName.Font.Size);

Cambiando il peso in bold:

LblCompayName.Font = new Font(LblCompayName.Font, FontStyle.Bold);

Evento chiusura Form

Ecco come intercettare l'evento di chiusura di una windows Form application FormClosing (Form closing Exit).
// Aggiunta dell'Handler:
this.FormClosing += FrmMain_FormClosing;
 
// Ecco un tipico metodo handler di gestione uscita:
private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
{
	if (e.CloseReason == CloseReason.UserClosing)
	{
		DialogResult result = MessageBox.Show("Do you really want to exit?", "Dialog Title", MessageBoxButtons.YesNo);
		if (result == DialogResult.Yes)
		{
			Environment.Exit(0);
		}
		else
		{
			e.Cancel = true;
		}
	}
	else
	{
		e.Cancel = true;
	}
}

TextBox

Auto scroll down

Ecco come far aggiornare una textBox multiline per andare automaticamente sotto all'ultima aggiunta inserita.
Occorre usare il metodo TextBox.AppendText(string text). Se ciò non dovesse funzionare seguire: stackoverflow e l'esempio in stackoverflow
Dopo aver impostato:

Multiline = True 
ScrollBars = Both
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();

Far comparire la clessidra

Per operazioni che richiedono l'attesa dell'utente si può far comparire la clessidra (hourglass) come puntatore. Attenzione a settare il cursore alla sua forma di default dopo la sezione Finally di una Try catch.
// Impostazione precedente del puntatore:
Cursor previousCursor = Cursor.Current;
 
// Imposta il cursore con la clessidra (hourglass)
Cursor.Current = Cursors.WaitCursor;
try
{
    // ... operazioni dispendiose di tempo
}
catch
{
}
finally
{
    // Impostazione del puntatore con la freccia di default
    Cursor.Current = Cursors.Default;
}

Icona applicazione

Per avere sia l'icona associata al Form che quella che appare nella Taskbar occorre valorizzare la proprietà Icon del Form ma anche occorre creare una cartella Resource (sotto la cartella principale del progetto) con dentro un file icona dal nome Icon.ico.
Infine per associare l'icona all'eseguibile occorre andare nelle proprietà del progetto, tab 'application' e associare un file *.ico alla sezione "Resource" 'Icon and manifest'.
Oppure:

WinForm default Icon.png

InputBox

Come ottenere un semplice dato mediante apposito popup? C# non ha nulla che ci aiuti allora ci posson essere diverse soluzioni che riporto come da Stackoverflow:

MessageBox custom

Originale: stackoverflowAggiungere la seguente classe:
public static class Prompt
{
    public static string ShowDialog(string text, string caption)
    {
        Form prompt = new Form()
        {
            Width = 500,
            Height = 150,
            FormBorderStyle = FormBorderStyle.FixedDialog,
            Text = caption,
            StartPosition = FormStartPosition.CenterScreen
        };
        Label textLabel = new Label() { Left = 50, Top=20, Text=text };
        TextBox textBox = new TextBox() { Left = 50, Top=50, Width=400 };
        Button confirmation = new Button() { Text = "Ok", Left=350, Width=100, Top=70, DialogResult = DialogResult.OK };
        confirmation.Click += (sender, e) => { prompt.Close(); };
        prompt.Controls.Add(textBox);
        prompt.Controls.Add(confirmation);
        prompt.Controls.Add(textLabel);
        prompt.AcceptButton = confirmation;
 
        return prompt.ShowDialog() == DialogResult.OK ? textBox.Text : "";
    }
}
Ed usare l'oggetto così:
string promptValue = Prompt.ShowDialog("Test", "123");

Usando libreria VisualBasic

Originale: stackoverflow
Referenziare:

try referencing Microsoft.VisualBasic.dll
Quindi usare la seguente
Microsoft.VisualBasic.Interaction.InputBox("Question?","Title","Default Text");
oppure:
using Microsoft.VisualBasic;

...

Interaction.InputBox("Question?","Title","Default Text");

ComboBox

Popolamento Bindig

Popola una comboBox usando come data source un dizionario chiave-valore.

private string BindTABDBQuery()
{
	string strError = string.Empty;
	string strCmbDisplayMember = string.Empty;
	try
	{
		Dictionary<string, string> dctCmbBoxSource = new Dictionary<string, string>();
 
		// Dato il servizio corrente carica le stringhe di connessione al DB
 
		#region Popola la combo con le query SQL ovvero i files nella cartella attesa
		// Carico il contenuto della cartella
		string[] fileQrySQLPaths = Directory.GetFiles(Model.Configuration.PathDataReadyQuerySQL, "*.sql");
 
		BindingSource bndSrcCmbDBQry_ReadyQueries = new BindingSource();                
 
		dctCmbBoxSource = new Dictionary<string, string>();
		dctCmbBoxSource.Add("Select a query", string.Empty);
 
		foreach (string fileQrySQL in fileQrySQLPaths)
		{
			strCmbDisplayMember = Path.GetFileNameWithoutExtension(fileQrySQL);
			dctCmbBoxSource.Add(strCmbDisplayMember, fileQrySQL);
		}
		bndSrcCmbDBQry_ReadyQueries.DataSource = dctCmbBoxSource;
		CmbDBQry_ReadyQueries.DataSource = bndSrcCmbDBQry_ReadyQueries;
		CmbDBQry_ReadyQueries.DisplayMember = "Key";
		CmbDBQry_ReadyQueries.ValueMember = "Value";
		#endregion
	}
	catch (Exception ex)
	{
		Cursor.Current = Cursors.Default;
		m_loggerForm.Error("Ex.: '{0}'\r\n\r\n{1}", ex.Message, ex.StackTrace);
	}
	return strError;
}

Verifica selezione comboBox precedente

private void CmbDBQry_ReadyQueries_SelectedIndexChanged(object sender, EventArgs e)
{
	string strMsgError = string.Empty;
	string keySQLFile = string.Empty;
	string fullPathSQLFile = string.Empty;
	string contentSQLFile = string.Empty;
	try
	{
		Cursor.Current = Cursors.WaitCursor;
		keySQLFile = ((KeyValuePair<string, string>)CmbDBQry_ReadyQueries.SelectedItem).Key;
		fullPathSQLFile = ((KeyValuePair<string, string>)CmbDBQry_ReadyQueries.SelectedItem).Value;
 
		if (keySQLFile != c_defaultCmbSelQry
			&& !string.IsNullOrWhiteSpace(fullPathSQLFile))
		{
			contentSQLFile = FileHelper.GetTextFileContent(fullPathSQLFile, out strMsgError);
			if (string.IsNullOrWhiteSpace(strMsgError))
			{
				Cursor.Current = Cursors.Default;
				MessageBox.Show(string.Format("{0}", strMsgError), string.Format("CmbDBQry_ReadyQueries_SelectedIndexChanged"),
							MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}
			TxtDBQry_EditQryLoaded.Text = contentSQLFile;
		}
	}
	catch (Exception ex)
	{
		Cursor.Current = Cursors.Default;
		m_loggerForm.Error("Ex.: '{0}'\r\n\r\n{1}", ex.Message, ex.StackTrace);
		MessageBox.Show(string.Format("{0}", ex.Message), string.Format("CmbDBQry_ReadyQueries_SelectedIndexChanged"),
						MessageBoxButtons.OK, MessageBoxIcon.Error);
	}
	finally
	{
		Cursor.Current = Cursors.Default;
	}
}

Esempio di popolamento di una ComboBox mediante dati provenienti da un enumerativo e acquisizione dell'enumerativo dalla ComboBox.
Si usa anche ciclare con una FOR EACH sugli elementi della struttura enumerativa.

public enum EnumTxtEncoding
{
	notDefined = 0,
	ASCII = 1,
	BigEndianUnicode = 2,
	Default = 3,
	Unicode = 4,
	UTF32 = 5,
	UTF7 = 6,
	UTF8 = 7
}
 
public static T ParseEnum<T>(string value)
{
	return (T)Enum.Parse(typeof(T), value, true);
}
 
private void FillCmbBxTxtEncoding()
{
	Dictionary<int, string> dctEnumTxtEncoding = new Dictionary<int, string>();
	BindingSource bndEnumTxtEncoding = new BindingSource();
 
	foreach (EnumTxtEncoding item in (EnumTxtEncoding[])Enum.GetValues(typeof(EnumTxtEncoding)))
	{
		dctEnumTxtEncoding.Add((int)item, item.ToString());
	}
 
	bndEnumTxtEncoding.DataSource = dctEnumTxtEncoding;            
	CmbBxTxtEncoding.DataSource = bndEnumTxtEncoding;
	CmbBxTxtEncoding.DisplayMember = "Value";
	CmbBxTxtEncoding.ValueMember = "Key";
}
 
//--------------Utilizzo--------------------------------------
 
string strFileEncoding = null;
EnumTxtEncoding fileEncoding = EnumTxtEncoding.notDefined;
 
strFileEncoding = ((KeyValuePair<int, string>)CmbBxTxtEncoding.SelectedItem).Value;
fileEncoding = ParseEnum<EnumTxtEncoding>(strFileEncoding);

Pre-Selezione

Il consiglio è di preselezionare medinte l'indice dell'elemento nella lista con cui è popoplata la ComboBox.
Nel seguente esempio la ComboBox è popolata con un dizionario per cui l'indice dell'elemento da selezionare si ottiene trasformando il dizionario dei valori in array ed usando poi la fuinzione di ricerca sull'array!

//  Metodo di popolamento della comboBox con in input parametro opzionale il valore da PRE-SELEZIONARE
private void Populate_CmbBox_PictureSizeMode(string defaultKeyText = "")
{
	m_dctCmbBoxPictureSizeMode.Add("Normal", PictureBoxSizeMode.Normal);
	m_dctCmbBoxPictureSizeMode.Add("StretchImage", PictureBoxSizeMode.StretchImage);
	m_dctCmbBoxPictureSizeMode.Add("AutoSize", PictureBoxSizeMode.AutoSize);
	m_dctCmbBoxPictureSizeMode.Add("CenterImage", PictureBoxSizeMode.CenterImage);
	m_dctCmbBoxPictureSizeMode.Add("Zoom", PictureBoxSizeMode.Zoom);
 
	BindingSource bndSrcCmbPictureSizeMode = new BindingSource();
 
	bndSrcCmbPictureSizeMode.DataSource = m_dctCmbBoxPictureSizeMode;
	CmbBox_PictureSizeMode.DataSource = bndSrcCmbPictureSizeMode;
	CmbBox_PictureSizeMode.DisplayMember = "Key";
	CmbBox_PictureSizeMode.ValueMember = "Value";
	if (defaultKeyText != string.Empty)
	{
		int i =  Array.IndexOf(m_dctCmbBoxPictureSizeMode.Keys.ToArray(), defaultKeyText);
		CmbBox_PictureSizeMode.SelectedIndex = i;
	}
}

TabControl

Come intercettare l'evento cambio di un TAB dell'interfaccia?
// Aggiungere manualmente il riferimento gestore dell'evento (l'handler)
MioTABControl.Selecting += new TabControlCancelEventHandler(MioTABControl_Selecting);
 
// E poi l'handler che segue
private void MioTABControl_Selecting(object sender, TabControlCancelEventArgs e)
{
        TabPage current = (sender as TabControl).SelectedTab;
        //Si valida la scelta oppure si annulla come segue:
        e.Cancel = true;
}

ListBox

Popolamento con un array di stringhe e gestione della selezione:

private static string[] m_arrStrFilteredItem;
 
//...
m_arrStrFilteredItem = GetArraySearchResult(keyToSearch);
//Popolamento del ListItem
LstB_CredentialFilesFound.DataSource = m_arrStrFilteredItem;
 
 
private void LstB_CredentialFilesFound_SelectedIndexChanged(object sender, EventArgs e)
{
	string strFileNameSelected = string.Empty;
 
	//Selezione del testo del ListItem selezionato!
	strFileNameSelected = LstB_CredentialFilesFound.GetItemText(LstB_CredentialFilesFound.SelectedItem);
 
	Item_BP itemSelected = m_LstDBIndex.Where(x => x.FileName == strFileNameSelected).Single();
	BindItem_BP_4Edit(itemSelected);
}

GridView

Link interno Soluzioni

PictureBox

Fonti: microsoft.com

PctBx_ImgViewDoc.Image = Image.FromFile("fullPathNomeFile");
//Oppure funziona anche:
PctBx_ImgViewDoc.ImageLocation = "fullPathNomeFile";

Per rimuovere l'immagine:

if (PctBx_ImgViewDoc.Image != null)
{  
   PctBx_ImgViewDoc.Image.Dispose();  
   PctBx_ImgViewDoc.Image = null;  
}

I/O

Intercattare la tastiera

Leggere: learn.microsoft.com KeyPreview.
Occorre abilitare questo comportamento impostando KeyPreview=True;. Indica se il Form riceverà gli eventi di pressione dei tasti prima che gli stessi risultino conclusi passando al controllo che ha il focus.
E' sufficiente impostare questa proprietà nel costruttore dell'oggetto Form, segue esempio:

namespace MiaApplicazione
{
    public partial class FrmMain : Form
    {
        public FrmMain()
        {
            this.KeyPreview = true;  // <---- !!!
            InitializeComponent();
        }
    }
}

Intercettare un tasto premuto

Si posson intercettare la maggior parte degli eventi di 'tasto premuto' gestendo gli eventi "KeyDown" e "KeyUp" ed occorre tener presente la seguente sequenza completa con cui si susseguono gli eventi:

  1. KeyDown. Evento generato nonappena l'utente preme un tasto e si ripete continuamente sinché l'utente non lo rilascia;
  2. KeyPress. Evento generato per i tasti carattere mentre il tasto è premuto e rilasciato. Differisce dagli eventi "KeyDown" e "KeyUp" che son generati ANCHE per i tasti NON carattere.
  3. KeyUp. Generato DOPO che l'utente ha rilasciato un tasto.

Per gestire l'ultimo degli eventi elencati prima, nell'handler dell'EventLoad del form inserire:

this.KeyUp += new System.Windows.Forms.KeyEventHandler(KeyEvent);

L'handler sarà:

private void KeyEvent(object sender, KeyEventArgs e) //Keyup Event 
    {
        if (e.KeyCode == Keys.F9)
        {
            MessageBox.Show("Function F9"); 
        }
        if (e.KeyCode == Keys.F6)
        {
            MessageBox.Show("Function F6");
        }
        else
            MessageBox.Show("No Function");
 
    }

Tasti fereccia

 

Ambiente

Rete

Ottenere l'IP ed il nome della macchina locale (Da stackoverflow):

String strHostName = string.Empty;
 
public static string GetLocalIPAddress()
{
        var host = Dns.GetHostEntry(Dns.GetHostName());
        foreach (var ip in host.AddressList)
        {
            if (ip.AddressFamily = AddressFamily.InterNetwork)
            {
                return ip.ToString();
            }
        }
        throw new Exception("Local IP Address Not Found!");
}

Mappa e Links


C# | Windows Form | Applicazioni Grafiche


Visual Studio | Programmazione