Technology Experience

.NET World

Programmazione, libri, snippet di codice, articoli tecnici

.NET World

Evento Validating. Ok per Windows Forms. Ma per Windows Mobile?

Introduzione per chi non sa di cosa si sta parlando
Facciamola breve. L’evento Validating è il metodo più vecchio per validare il contenuto di un controllo in un’applicazione Windows Forms. L’evento Validating si scatena un attimo prima che un determinato controllo perda il focus: nell’event handler implementate il controllo che volete, e se le cose non vanno come dovrebbero, impostate a true il valore della proprietà Cancel del parametro di tipo CancelEventArgs. Quindi, supponiamo:

1 private void textBox1_Validating(object sender, CancelEventArgs e) 2 { 3 if(string.IsNullOrEmpty(this.textBox1.Text)) 4 e.Cancel = true; 5 }

Il codice qui sopra valida il contenuto di una TextBox su una Windows Forms. Se la TextBox è vuota, non potete andarvene: dovete per forza digitare qualcosa.

Il discorso fatto sinora è valido fintantochè la proprietà CausesValidation della TextBox (più in generale…del controllo) è impostata a true. Se questa proprietà è impostata a false, l’evento Validating non viene più scatenato, e quindi i vostri controlli di validazione non vengono più eseguiti.

Per la serie…non si finisce mai di imparare

Ma non è finita qua. Oltre a CausesValidation, è possibile lavorare con la proprietà AutoValidate del form. Tecnicamente parlando, questa proprietà esiste per tutti i controlli che ereditano da ControlContainer (Panel, GroupBox, TabControl, etc.). Il valore di default è EnablePreventFocusChange: evita che il controllo perda il focus se la validazione non avviene con successo. Qui ci sono maggiori informazioni su questo argomento.

E’ possibile impostare AutoValidate a Disabled. Questo impedisce lo scatenarsi dell’evento Validating, anche se avete impostato CausesValidation a true per un determinato controllo. A cosa potrebbe servire? Gli scenari che mi sono venuti in mente sono fondamentalmente due:

  • Non posso validare un controllo alla volta. Mi spiego meglio. Non sempre posso validare – per esempio – la TextBox su cui mi trovo senza tenere in considerazione altri controlli sulla Windows Form: controlli su cui magari devo ancora passare. Piccolo esempio: per validare una CodiceFiscaleTextBox sulla lunghezza (11 per partita iva o 16 per codice fiscale), devo anche controllare quale degli OptionButton l’utente ha selezionato, per indicare se è un privato o un utente aziendale.
  • Voglio validare esplicitamente quando lo dico io.

Mettendo AutoValidate a Disabled, è sempre e comunque possibile validare il contenuto della Windows Form chiamando esplicitamente il metodo ValidateChildren(), che restituisce un booleano. Questo metodo itera su tutti i controlli della Windows Form e scatena l’evento Validating solo su quelli che hanno CausesValidation a true. La chiamata al metodo restituisce true se tutte le validazioni sono avvenute con successo; restituisce false se almeno una delle validazioni è fallita.

E su Mobile?

Il Compact Framework prevede l’evento Validating sui controlli. Ma non c’è modo di utilizzare AutoValidate sulla Form, e neppure di usare CausesValidation. A quest’ultima cosa è naturalmente possibile sopperire in modo abbastanza semplice, creando una classe che erediti da TextBox e che aggiunga questa proprietà booleana che esegua la validazione solo quando vale true.

Technorati Tags:   

Send to Kindle
.NET World

Primo tentativo di utilizzo di Linq4SP

Qualche giorno fa mio fratello ha bloggato parlando di questo provider per Linq, che permette di – passatemi il termine – interrogare una basedati Sharepoint usando i costrutti Linq di C# 3.0.

L’ho scaricato. Il file zip contiene un tool con GUI che, dato un Sharepoint Site Url, dovrebbe creare una classe che fa da context a Linq. Purtroppo – e segnatevelo se avete intenzione di usarlo – che questo tool richiede la presenza dell’assembly Microsoft.Sharepoint.dll, quindi deve girare sul server.

Non ho provato a vedere cosa succede ad eseguirlo su un server Sharepoint e poi ad utilizzare l’output su un altro client. Ma il discorso è sempre lì: un cliente che vuole interfacciarsi a Sharepoint non può utilizzare il suo object model, ma deve passare attraverso le chiamate ai web-services esposti.

Technorati Tags:  

Send to Kindle
.NET World

Microsoft Certified Logo upated!

Venerdì scorso ho superato l’esame 70-526 acquisendo la qualifica di Microsoft Certified Technology Specialist: .NET Framework 2.0: Windows Application. Nei giorni scorsi ho provveduto ad aggiornare i loghi sia sul mio blog che sul mio sito. Dovrei farlo anche sul mio curriculum sostituendolo al “vecchio” logo MCP: ma lo farò con calma domani, perchè stasera sono davvero fuso. Ho solo tre ore di sonno nell’ultima notte causa Indiana Jones, e questa mattina ero a Milano alle 8:00.

Ho anche scoperto che grazie al Certificate Manager sull’MCP Site di Microsoft è possibile scaricare un file PDF con il certificato relativo alla nostra certificazione, così lo si può stampare a colori senza aspettare la copia originale che arriverà – dopo previa richiesta esplicita – un po’ più tardi.

E poi è anche possibile scaricare il transcript in formato XPS.

Il prossimo esame – che voglio superare nei prossimi due mesi – è il 70-548 per poter diventare Microsoft Certified Professional Developer!

Technorati Tags:   

Send to Kindle
.NET World

Esame 70-526: passato con 860!

Senza dir niente a nessuno, 15 giorni fa mi sono registrato per l’esame 70-526 il cui titolo è TS: Microsoft .NET Framework 2.0 – Windows-Based Client Development. Ho tenuto questa mattina l’esame intorno alle ore 10:00 presso Microsys a Milano. Nel corso del tempo sono stato in quattro posti diversi a fare gli esami: quello che preferisco è proprio quello di stamattina, perchè l’ambiente è professionale, accogliente e serio.

L’esame ricalca buona parte gli argomenti del vecchio 70-316, ma con in più ovviamente un sacco di tematiche. Quelli che vi consiglio di studiare per superare questo esame sono: ClickOnce e tutto quello che riguarda il setup & deployment delle vostre applicazioni .NET; Thread, BackgroundWorker, delegate, asynchronous programming model ed affini. Il resto delle domande – se davvero sviluppate applicazioni desktop per Windows – non dovrebbero essere un problema (data-binding, extended e usercontrol, etc.).

La morale è questa: il punteggio finale è di 860/1000.
Vediamo il dettaglio. Le barre del grafico finale sono 7.
3 di queste sono al massimo: meglio di così non si può fare.
3 delle altre sono, diciamo, sopra l’80% di risposte corrette.
1 sola è crollata a picco: proprio quella che dice Configuring and Deploying Applications.

Peccato, perchè studiando un po’ più ClickOnce (io non l’ho mai usato in produzione) avrei potuto ottenere un punteggio migliore. Che rabbia! Ma in fondo tutto è bene quel che finisce bene.

Technorati Tags:    

Send to Kindle
.NET World

Usability di un sito Web

Pochi minuti fa sono andato sul sito www.multiplexarcadia.com, sito Web dell’Arcadia, mitico cinema multisala di Melzo, uno dei pochi in Italia a supportare proiezioni in digitale con THX.

Mi state chiedendo perchè? Perchè sono andato su quel sito? E’ semplice: il 23 Maggio prossimo esce in contemporanea mondiale Indiana Jones ed il Regno del Teschio di Cristallo, quarto episodio della saga. Non me lo posso perdere e so già che se sarà di mio gradimento andrò a vedermelo anche più di una volta, come accadde tre anni fa con Star Wars e la Vendetta dei Sith.

Arriviamo a noi. La prenotazione non avviene sul sito dell’Arcadia, ma su www.biglietto.it.  E’ scandalosa. E’ possibile prenotare i posti usando la tessera (che non ho) oppure usando il classico nome & cognome (in pratica registrandosi). Ho usato questa seconda opzione. Peccato però che per far funzionare il tutto a dovere, bisogna seguire istruzioni a dir poco complicate. Magari non per me, ma per un utente finale direi proprio di sì.

In pratica, bisogna reimpostare alcune opzioni sotto il tab Privacy di Internet Explorer, modificando (temporaneamente) il blocco dei cookie, altrimenti non riuscite a registrarvi, venite reindirizzati su pagina sbagliate, i popup non si aprono e…buonanotte al secchio!

Fare siti Web un po’ più usabili è una cattiva idea?

Technorati Tags:    

Send to Kindle
.NET World

WPF: accelerare un’animazione per arrivare velocemente alla fine

In un’applicazione WPF che sto programmando nel tempo libero ho creato un’animazione che parte automaticamente all’apertura della Window principale dell’applicazione stessa. Essa prepara l’interfaccia utente con un po’ di “effetti speciali”:

  • il titolo dell’applicazione appare con un fade-in
  • stessa cosa per il background, ma con un leggero ritardo rispetto al titolo
  • altre scritte appaiono ruotando e spostandosi velocemente sullo schermo, posizionandosi vicino al titolo
  • poi appare il menù principale, anch’esso con un fade-in
  • il logo VivendoByte viene posizionato in basso a destra sullo schermo

Va da sè che l’animazione viene applicata a diversi elementi dell’interfaccia utente definita nello XAML ed impiega 5 secondi per il completamento. Sebbene possa essere divertente da vedere, posso capire che l’utente voglia – in certi momenti – essere più sbrigativo e saltare direttamente alla fine per avere l’interfaccia utente pronta all’uso, senza perdersi in convenevoli ed effetti speciali che magari vorrebbe evitare.

La domanda di questa sera quindi è: posso accelerare l’animazione facendo in modo che balzi alla fine senza far aspettare l’utente che sta davanti allo schermo? La risposta è ovviamente sì.

Vediamo come fare. Diamo un’occhiata al costruttore della Window:

1 public StartWindow() 2 { 3 InitializeComponent(); 4 anim = (Storyboard)this.FindResource("FadeInStoryboard"); 5 6 this.MouseUp += delegate(object sender, MouseButtonEventArgs args) 7 { 8 anim.SetSpeedRatio(this, 8.0); 9 }; 10 11 // Start the animation and make it controllable via code 12 anim.Begin(this, true); 13 }

Alla linea 4 otteniamo l’istanza di Storyboard che si chiama “FadeInStoryboard”. Come abbiamo visto, l’animazione fa molte più cose di un semplice fade-in, ma il nome è rimasto così. Poco male.

Alla linea 6 ci sottoscriviamo all’evento MouseUp della Window e ad adesso assegnamo un event handler tramite un anonymous method. In pratica…se l’utente clicca sulla finestra viene settata una nuova velocità all’animazione (metodo SetSpeedRatio). In questo caso, la velocità viene moltiplicata per un fattore 8.0. Invece di 5 secondi, il tutto termina in pochi istanti.

Cosa importante: ricordiamoci sempre che se vogliamo controllare l’animazione via codice C# dobbiamo farla partire da codice. La linea 12 fa proprio questo: la chiamata al metodo Begin della classe Storyboard ha due overloads. Il primo parametro è l’oggetto Window, il secondo è un booleano che indica se l’animazione deve poter essere controllata da codice oppure no. Se questo secondo parametro venisse omesso o valesse false, la chiamata a SetSpeedRatio non sortirebbe alcun effetto. La stessa cosa vale per tutti i metodi o proprietà che in qualche modo interagiscono sull’animazione (Seek, SkipToFill, AccelerationRatio, etc.).

Technorati Tags:     

Send to Kindle
.NET World

WPF: fare animazioni con suoni incorporati (ed usando un thread)

Windows Presentation Foundation soffre a mio avviso di una grave lacuna: nello XAML non è possibile creare animazioni (e relative storyboard) in grado di mandare in play files .wav o .mp3 in determinati momenti. Se questo assunto è sbagliato fermate la lettura di questo post, scorrete fino in fondo e lasciatemi un commento.

Introduzione
Supponiamo di avere una finestra (Window) grande 640×480. Supponiamo di avere una palla colorata in alto a sinistra e supponiamo di creare un’animazione che faccia spostare questa palla verso il basso, fino a quando essa non “rimbalza” contro il bordo inferiore della finestra tornando alla sua posizione originaria…e così via…all’infinito. Possiamo mandare in play il file boeing.wav nel momento in cui la nostra palla rimbalza? Se vogliamo fare in modo dichiarativo nello XAML, la risposta è no. Se invece siamo disposti a scrivere codice, la risposta è sì. Siccome siamo sviluppatori, prendiamo questa seconda strada e vediamo come fare.

In questo momento non ho un progetto demo pronto per essere uploadato se volete dargli un’occhiata. Se a qualcuno di voi dovesse servire, fatemelo sapere con un commento e provvederò.

Andiamo al dunque (un po’ troppo velocemente)
Spiegare da zero in solo post come usare Blend per creare una Window, come posizionare i Panel che si servono, come posizionare i controlli e come creare un’animazione è davvero troppo. Perciò supponiamo di averlo fatto.

La prima cosa da capire è che se vogliamo in qualche modo gestire una storyboard da codice, non possiamo farla partire tramite un trigger di sistema. Ad esempio, quando creiamo un’animazione con Blend, questi ci mette automaticamente un trigger sull’evento Window.Loaded per far partire la storyboard che abbiamo disegnato e che fa spostare la palla (sembra più un CD!) verso il basso. Cancelliamo dallo XAML questo trigger e mettiamo un pulsante che fa partire manualmente la storyboard. Il codice C# è molto semplice:

public Window1() { this.InitializeComponent(); // Insert code required on object creation below this point. story = (Storyboard)this.FindResource("FallCd"); }

Nel costruttore della form otteniamo l’istanza della Storyboard chiamata “FallCd”. L’oggetto story che si vede qui sopra è dichiarato privato della Window. L’evento Click del Button è questo:

private void StartAnimation_Click(object sender, RoutedEventArgs e) { story.Begin(this.cd, true); }

A questo punto possiamo fare una cosa molto semplice. Possiamo sottoscriverci nello XAML all’evento CurrentTimeInvalited dello Storyboard:

<Storyboard x:Key="FallCd" CurrentTimeInvalidated="Storyboard_CurrentTimeInvalidated"> ... ... </Storyboard>

In questo modo siamo notificati ad ogni step di avanzamento del Clock che regola l’animazione stessa. Ad esempio…supponiamo di visualizzare nel Title della Window il tempo che passa:

private void Storyboard_CurrentTimeInvalidated(object sender, EventArgs e) { TimeSpan span = story.GetCurrentTime(this.cd).GetValueOrDefault(); this.Title = span.ToString(); }

Ottengo il TimeSpan dalla storyboard e semplicemente la visualizzo. Da qui a fare il play di un file .mp3 al momento opportuno passa davvero poco:

private void Storyboard_CurrentTimeInvalidated(object sender, EventArgs e) { if (span.Seconds == 1) { player.Play(); } }

player è un’istanza della classe SoundPlayer già istanziata e caricata con un file .wav nel costruttore della form. Il codice qui sopra manda il play il file non appena siamo ad un secondo dall’inizio dell’animazione? Sì, ma c’è un grandissimo problema. Le animazioni in WPF sono regolate con un clock molto preciso. Un secondo è diviso in 1.000 millisecondi, per cui quel metodo Play() viene chiamato in realtà un’infinità di volte. La cosa è semplicemente risolvibile con una variabile booleana, in modo tale che entriamo nell’if soltanto una volta. Quindi:

private void Storyboard_CurrentTimeInvalidated(object sender, EventArgs e) { if (span.Seconds == 1 && !playing) { playing = true; player.Play(); } }

La variabile playing è dichiarata come privata dalla Window e all’inizio vale false.

L’ultimo dubbio è: ma è proprio vero che viene usato un thread secondario???

La classe SoundPlayer espone due metodi che fanno il play del file audio precedentemente caricato. Il metodo Play() ed il metodo PlaySync(). Che differenza c’è fra i due? Ve lo riporto direttamente da come lo dice MSDN.

Metodo Play

Plays the .wav file using a new thread, and loads the .wav file first if it has not been loaded.

Metodo PlaySync

Plays the .wav file using the user interface (UI) thread, and loads the .wav file first if it has not been loaded.

Noi abbiamo usato Play, per cui mi aspettavo di non avere problemi sull’animazione, cosa che invece non avviene. Quando siamo ad un secondo dall’inizio dell’animazione, il SoundPlayer parte, ma l’animazione subisce un rallentamento, uno scatto. E’ proprio vero che viene istanziato un thread per fare quel play? Supponiamo di voler creare noi il nostro thread da lanciare quando è il momento opportuno.

Creiamo un metodo privato chiamato sparo() che non fa altro che fare il play del file:

void sparo() { player.Play(); }

Dichiariamo un’istanza di Thread come privato della Window e definiamolo nel costruttore:

soundThread = new Thread(new ThreadStart(sparo)); soundThread.Priority = ThreadPriority.Highest; soundThread.IsBackground = true;

A questo punto è sufficiente chiamare soundThread.Start() per mandare in play il file:

private void Storyboard_CurrentTimeInvalidated(object sender, EventArgs e) { if (span.Seconds == 1 && !playing) { playing = true; soundThread.Start(); } }

Il Play del SoundPlayer viene invocato con il nostro thread, pronto per l’esecuzione e questa volta la nostra animazione rimane fluida e veloce anche quando si sente lo sparo! Evviva!

Sincronizzare un evento con il play del file

Chiudo questo post domenicale mattutino con una piccola osservazione. Nel mio test ho usato semplicemente il tempo – fare il play in un determinato momento temporale – ma nulla vieta di inserire nell’evento CurrentTimeInvalited tutti i controlli del caso, quindi…magari accorgersi quando la palla si sta allontanando dal bordo invece che avvicinarsi e così via.

Buona domenica a tutti!!!

Send to Kindle
.NET World

Ho installato il Windows Mobile 6.0 SDK

L’applicazione che ho sviluppato gira su un palmare con Pocket PC 2003. Venerdì pomeriggio la società fornitrice ci ha consegnato un nuovo modello, su cui invece gira Windows Mobile 5.0. Abbiamo già provato ad installare il nostro prodotto utilizzando il CAB di installazione: inutile dire che tutto è filato liscio senza problemi.

Fino ad adesso non abbiamo avuto un grosso bisogno di sfruttare la componente telefonica del palmare, cosa che invece dovremo fare in futuro. La nostra applicazione dovrà connettersi ad Internet via GPRS per scaricare e ricevere ordini da lavorare, dovrà magari in futuro utilizzare il GPS interno per comunicare la posizione, etc. Probabilmente tutto questo sarebbe molto difficile con un vecchio PPC2003, perchè le API di questo sistema operativo arrivano fino ad un certo punto. Già adesso per abilitare e disabilitare il flight mode abbiamo dovuto scrivere alcuni metodi un po’ a basso livello. Credo proprio che con Windows Mobile 5.0 le cose siano un po’ più semplici.

Ma siccome se ce la faccio mi piace essere in anticipo sui tempi, stasera mi sono installato sul portatile il Windows Mobile 6.0 SDK che per caso ho trovato in giro in camera mia.

Technorati Tags:  

Send to Kindle
.NET World

Visto che venerdì sera si parlava di donne…

Ecco un bel link con un articolo da leggere.

Domani Lunedì 31 Marzo sul sito www.webalfemminile.it ci saranno tutta una serie di eventi che fanno capo alla definizione Donne e Tecnologia – L’alleanza per un futuro migliore. Gli eventi riguardano ovviamente le donne, sulla pari opportunità nel lavoro, sul rapporto tra uomini e donne sul luogo di lavoro, sulla predisposizione delle donne verso un lavoro piuttosto che un altro, la fuga di cervelli verso gli altri Paesi, etc. etc.

Visto che venerdì sera c’è stata un’accesa discussione sulle donne e sul nostro lavoro, ecco pronta la risposta…

Send to Kindle