Technology Experience

.NET World

Programmazione, libri, snippet di codice, articoli tecnici

.NET World

VivendoByte Technorati Tags in WPF

Nei giorni scorsi ho sviluppato la versione WPF del mio plug-in per Windows Live Writer capace di raccogliere i 100 tags più utilizzati sul vostro blog. Ricordo che la suite dei miei plug-in è hostata su CodePlex qui, per cui potete unirvi a me nello sviluppo. Ho idee ambiziose che riguardano Flickr ed altre cosucce simili.
Ecco qui sotto lo screenshot della finestra principale:

Il fatto di avere due diverse interfacce utente (Windows Forms e WPF) mi ha costretto a rivedere un po’ alcune parti dell’applicazione: ho così creato un assembly che contiene la banale business logic e che quindi espone funzionalità in comune – cioè la maggior parte – tra le due interfacce: caricamento dei tags da Technorati, salvataggio in locale, etc. etc. Il codice è ovviamente mooolto più pulito e compatto, e giustamente sulla UI si vede molto poco inerente la logica applicativa.

Mi sono divertito anche a creare un filmato di attesa. Mi spiego meglio. Quando aprite il plug-in dal menù Inserisci di Windows Live Writer, il plug-in tenta di connettersi al web-service di Technorati per scaricare l’elenco dei tags. Questa operazione richiede qualche secondo: nella versione Windows Form appare una semplice form con una scritta “Please wait! Retrieving tags from Technorati!“. Nella versione WPF invece ho creato un filmato sfruttando il mio logo VivendoByte; il filmato pesa solo 3,43Mb, se volete dargli un’occhiata cliccate qua. In questo modo, l’utente aspetta e ha davanti un bel video di attesa. Figo!

I sorgenti della Vivendo Byte Windows Live Writer Suite sono disponibili su CodePlex.

Per scaricare gli eseguibili dell’ultima versione cliccate direttamente qui. ll file zip pesa 348Kb, e va decompresso nella solita directory C:Program FilesWindows LiveWriterPlugins.

Technorati Tags:    

Send to Kindle
.NET World

L’ultimo numero di MSDN Magazine…

…mi fa impazzire. E’ troppo bello ed appassionante.

Ultimamente, lo ammetto, mi ha lasciato con l’amaro in bocca, perchè gli argomenti erano incentrati su ASP.Net, AJAX e Silverlight: tutti strumenti che meritano senz’altro il loro spazio. Ma a me personalmente lasciano l’amaro in bocca. Lo dico con onestà: alcune volte ho pensato di lasciarlo lì dov’è, è quasi come quando mi capitava anni fa di prendere Computer Programming o altre riviste di programmazione e di trovare articoli su linguaggi/tecnologie verso le quali nutrivo scarsa considerazione (SmallTalk, Delphi, per citarne qualcuno). Alla fin fine non le ho prese più, perchè già faccio fatica a leggere quello che devo leggere, figurarsi qualcosa che mi interessa poco.

Invece quello di dicembre è tutta un’altra cosa: WPF, Linq, WCF, VSTO. Finalmente qualcosa di serio e, soprattutto, di utilissimo per il mio lavoro e non solo. Ben fatto!!!!

Technorati Tags:   

Send to Kindle
.NET World

WPF: L’importanza dell’evento MediaFailed

La classe MediaElement di Windows Presentation Foundation mette a disposizione l’evento MediaFailed, al quale possiamo sottoscriverci per gestire tutti i casi in cui il player di WPF non riesca per qualche motivo a renderizzare il contenuto impostato dal source, sia esso video ed audio.

Questa sera, mentre il mio amico Fabio guidava, io ero di fianco a lui con il notebook aperto e ho buttato giù due linee di XAML. Eccole qua:

1 <StackPanel Orientation="Vertical"> 2 3 <MediaElement Name="WaitingAnimation" Width="100"> 4 <MediaElement.Triggers> 5 <EventTrigger RoutedEvent="MediaElement.Loaded"> 6 <EventTrigger.Actions> 7 <BeginStoryboard> 8 <Storyboard> 9 <MediaTimeline Source="C:UsersIgorDesktopLogoVivendoByte.avi" 10 Storyboard.TargetName="WaitingAnimation" 11 RepeatBehavior="Forever" /> 12 </Storyboard> 13 </BeginStoryboard> 14 </EventTrigger.Actions> 15 </EventTrigger> 16 </MediaElement.Triggers> 17 </MediaElement> 18 19 <Label Content="Please wait! Retrieving tags from Technorati..." 20 FontSize="12" 21 Foreground="Blue" 22 VerticalContentAlignment="Center" 23 HorizontalContentAlignment="Center" /> 24 25 </StackPanel>

Per chi ha un po’ di dimestichezza con WPF, vedrà che non è nulla di trascendentale. C’è uno StackPanel che contiene un MediaElement ed una Label. Il MediaElement utilizza un file AVI sul mio PC, e fa in modo che venga ripetuto continuamente fino a quando la finestra non viene chiusa. Mentre sul mio PC a casa con Vista, tutto gira senza problemi, sul notebook proprio non riuscivo a vedere il video. Ho provato a semplificare lo XAML, ma niente. Ho provato ad aprire il file AVI con Windows Media Player e con VLC: tutto ok, il file è valido ed il filmato pure. E allora, come cacchio è che la mia Windows non renderizza nulla?

Ho provato di tutto, come settare LoadedBehavior=”Player” sul MediaElement, e altri tentativi che adesso non ricordo nemmeno più. Alla fine, ho provato un’ultima cosa: ho provato a gestire l’evento MediaFailed, dato che dopo un po’ ho cominciato ad intuire che fosse proprio WPF che, per qualche motivo, non riesce a far vedere il video.

Quindi, modifico la linea (3) del codice qui sopra con il seguente XAML…

<MediaElement Name="WaitingAnimation" Width="100" MediaFailed="WaitingAnimation_MediaFailed">

..e nel code-behind in C# vado a gestire l’event-handler con un banale:

private void WaitingAnimation_MediaFailed(object sender, ExceptionRoutedEventArgs e) { MessageBox.Show(e.ErrorException.ToString()); }

Ho scoperto l’arcano. Viene effettivamente sollevata un’exception, che mi informa che devo installare Windows Media Player 10 per visualizzare quel video!!! La cosa che non mi ha affatto convinto è che nessuno mi diceva niente: WPF semplicemente si rifiutava di farmi il video, senza avvisarmi di nulla, senza darmi errori a runtime!!!!

Dopo aver installato WMP10, tutto è andato regolarmente, ma tutto questo mi ha lasciato un pochino basito, perchè legare così tanto WPF con un player specifico, imho, non va affatto bene. Capisco bene che quando si installa WMP10 vengono installati driver, codec e chissà che altro, però bisogna rendersi conto che c’è tanta gente che si rifiuta di installare WMP10 perchè non lo userà mai e poi mai, ed è assurdo che a causa di questo motivo anche un software di terze parti come il mio potrebbe fallire in qualche modo.

Technorati Tags:    

Send to Kindle
.NET World

Visual C# 2008 Keybinding Reference Poster

A questo url è possibile scaricare uno zip contenente il PDF con tutte le shortcut disponibili in Visual Studio 2008. Il PDF è diviso in due pagine comodamente stampabili in formato A4: la prima pagina è a colori, la seconda è in bianco e nero, a seconda delle esigenze e della stampante che avete.

Gli short sono divisi nelle categorie: Editing, File, Intellisense, Navigation, Window, Refactoring, Debugging e Build. Non indispensabile, ma utile da avere sotto mano.

Technorati Tags:   

Send to Kindle
.NET World

Subtext: due post con lo stesso titolo

Esercizio. Aprire il vostro browser preferito, raggiungete www.google.com e nella casella di ricerca inserite il testo seguente:

site:blog.vivendobyte.net marco eraser

Con questa stringa di ricerca ricercate all’interno del mio blog tutti i post in cui compaiono le parole marco ed eraser. Google vi restituisce 4 collegamenti. Osservate i primi due.

I primi due collegamenti puntano a due URL diversi, ma il titolo del post è lo stesso. Due post con lo stesso nome. Il primo è stato scritto il 22 Novembre, l’altro il 27 Novembre. Riuscite a raggiungere il post più vecchio (il secondo in elenco, quello del 22), ma se provate a cliccare sul primo link (il più recente, quello del 27), Subtext vi risponde con un bel…

Missing Page Report

Details.

Sorry, that page you requested cannot be found. If the page does not show up within 24 hours, you can file a missing page report.

Il secondo post che ho scritto è stato perso, sebbene Google abbia avuto il tempo di indicizzarlo. Il risultato di tutto questo è che Marco Minerva, alla ricerca del mio Visual Studio Recent Items Eraser, non trova più il link corretto all’ultima release che ho rilasciato. Caro Marco, grazie per avermi avvisato, altrimenti non me ne sarei mai accorto. Riporto in questo post il link.

Download : VisualStudioRecentItemsEraser.zip

Technorati Tags:    

Send to Kindle
.NET World

Ripetere all’infinito un filmato con XAML

Sto preparando una Window con WPF e XAML per mettere in attesa l’utente quando il software sta facendo qualcosa di piuttosto lungo, che potrebbe annoiarlo. L’operazione prevede la connessione ad un Web services con WCF per scaricare delle informazioni: la durata può variare dai 4 secondi in su, in base ai soliti parametri…qualità della connessione, velocità, etc. etc.

Ho trovato tra i miei CD una vecchia licenza di Corel R.A.V.E., un software di animazione vettoriale: l’ho installato ed in un’oretta ho creato una piccola animazione, partendo dal logo VivendoByte che vedete in alto a sinistra sulle pagine del mio blog. Come inserirlo  in una Windows? La risposta è semplice: è sufficiente usare la classe MediaElement.

Ma non basta: se volete che l’animazione si ripeti all’infinito, bisogna passare attraverso l’utilizzo della classe MediaTimeline, inserito tra i trigger del MediaElement. Riporto lo XAML per chiarezza:

<MediaElement Name="WaitingAnimation" MediaOpened="MediaElement_BufferingEnded"> <MediaElement.Triggers> <EventTrigger RoutedEvent="MediaElement.Loaded"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <MediaTimeline Source="C:UsersIgorDesktopLogoVivendoByteAnimato.avi" Storyboard.TargetName="WaitingAnimation" RepeatBehavior="Forever" /> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </MediaElement.Triggers> </MediaElement>

Ho aggiunto un MediaElement chiamato WaitingAnimation. Notare che intercetto l’evento MediaOpened, che si scatena non appena WPF fa partire il filmato: nell’evento – non riportato – faccio partire l’esecuzione di un BackgroundWorker che in un thread separato fa tutto quello che deve fare. Poi lavoro con i trigger del MediaElement: non appena si scatena l’evento MediaElement.Loaded comincia l’esecuzione di una storyboard, che contiene un MediaTimeline che fa il play del filmato indicato nella proprietà Source. Notare l’utilizzo della proprietà RepeatBehavior – non disponibile nel MediaElement – che dice a WPF di ripartire daccapo con l’animazione quando essa arriva alla fine.

Fonte : http://msdn2.microsoft.com/en-us/library/ms741866.aspx

Technorati Tags:  

Send to Kindle
.NET World

Siete bravi con Silverlight? Dimostratelo, è il vostro momento!

Se siete grafici, web-designer, web-developer e volete dimostrare di essere tosti con Silverlight, potete farlo partecipando al 1st European Silverlight Challenge, le cui iscrizioni sono state aperte oggi. Raggiungete il sito ufficiale della sfida, iscrivetevi e datevi da fare: la finale europea potrebbe essere vostra! La sfida è organizzata da Microsoft, da INETA e da XeDotNet, la community .NET in quel di Venezia.

Se vi state chiedendo come partecipare, potete leggere il regolamento qua. La versione breve è: iscrivetevi, spedite il vostro lavoro in Silverlight entro il 28 Gennaio 2008 ed attendete i risultati entro il 12 Febbraio 2008. Tutto il materiale deve essere totalmente scritto in inglese, deve essere libero da copyright e deve essere rilasciato tutto licenza open-source. I premi sono succulenti, soprattutto se lavorate con tecnologie Microsoft: ci sono licenze MSDN, Resharper, tool di terze parti come JetBrains e ComponentOne, controlli per ASP.Net, etc. etc, oltreche – da non sottovalutare – gloria e fama.

Credo che sia una straordinaria occasione per mettersi in gioco, per dimostrare la propria bravura con l’innovativa piattaforma di sviluppo per applicazioni Web rilasciata da Microsoft, capace di portare la potenza di WPF sui nostri browser per rendere sempre più accattivante la user-experience dei navigatori. Sarà pur vero che si comincia in un ambito italiano, ma avere l’occasione di poter apparire in un contesto internazionale è allettante.

Io con Silverlight non saprei fare nulla: è vero…ok…è WPF, ma ci sono alcune limitazioni che nella versione pura per smart-client non ci sono, e quindi – come qualcuno mi ha detto – sono abituato fin troppo bene. Ma se siete più web-oriented, questa è l’occasione che fa per voi.

Grazie a Lorenzo per la segnalazione e ad Andrea per il lavoro che stanno svolgendo!

Technorati Tags:   

Send to Kindle
.NET World

Salvare in modo asincrono gli stati di un processo transazionale

Uao, che titolo altisonante che ho tirato fuori dal cilindro questo pomeriggio.
Vi illustro lo scenario.

Immaginatevi un piccola applicazione mobile (Pocket PC o Windows Mobile, non importa) composta essenzialmente da 5 form diverse: Form1, Form2, Form3, Form4 e, sorpresa, Form5. L’applicazione parte mostrando Form1. Su ciascuna form ci sono due pulsanti – Next e Previous – per poter navigare avanti ed indietro da una forma all’altra. Gli stati possibili all’interno dell’applicazione sono i seguenti, con le varie possibilità di navigazione…

Partenza=Form1, Indietro=Form1, Avanti=Form2
Partenza=Form2, Indietro=Form1, Avanti=Form3
Partenza=Form3, Indietro=Form2, Avanti=Form4
Partenza=Form4, Indietro=Form3, Avanti=Form5
Partenza=Form5, Indietro=Form4, Avanti=Form5

Vediamo un po’ di codice per capire di cosa sto parlando. Questa è la classe Form1.

1 public partial class Form1 : Form 2 { 3 TransactionManager manager = new TransactionManager(); 4 5 public Form1() 6 { 7 InitializeComponent(); 8 } 9 10 private void previousButton_Click(object sender, EventArgs e) 11 { 12 manager.CurrentForm = this; 13 manager.NextIndex = 1; 14 manager.MoveToTransaction(); 15 } 16 17 private void nextButton_Click(object sender, EventArgs e) 18 { 19 manager.CurrentForm = this; 20 manager.NextIndex = 2; 21 manager.MoveToTransaction(); 22 } 23 }

Faccio uso di quello che ho chiamato TransactionManager, ovvero una classe che ha la responsabilità di farmi navigare avanti o indietro in base alla “posizione” in cui mi trovo. Se clicco sul previousButton e mi trovo su Form1, rimango su Form1. Se clicco su nextButton e mi trovo su Form1, vado su Form2, e così via, secondo lo schema (chiamiamolo così) che ho indicato sopra. Vediamo il codice di TransactionManager per capire un po’ di cose.

1 class TransactionManager : ITransaction 2 { 3 Form _currentForm; 4 int _nextIndex; 5 6 public Form CurrentForm 7 { 8 get { return _currentForm; } 9 set { _currentForm = value; } 10 } 11 12 public int NextIndex 13 { 14 get { return _nextIndex; } 15 set { _nextIndex = value; } 16 } 17 18 public void MoveToTransaction() 19 { 20 PDAManager.ShowWaitCursor(true); 21 22 string formName = "FormsNavigator.Form" + (_nextIndex).ToString(); 23 Form newForm = (Form)Assembly.GetExecutingAssembly().CreateInstance(formName); 24 25 if (newForm != null) 26 { 27 newForm.Show(); 28 newForm.BringToFront(); 29 30 if (_currentForm.GetType() != typeof(Form1)) 31 { 32 _currentForm.Close(); 33 } 34 } 35 36 PDAManager.ShowWaitCursor(false); 37 } 38 }

Qua ci divertiamo.

La classe TransactionManager implementa l’interfaccia ITransactionManager, che prevede due proprietà pubbliche (CurrentForm e NextIndex) e l’implementazione di un metodo MoveToTransaction(). Quest’ultimo è fondamentale: visualizza la clessidra sullo schermo del palmare. Poi viene creata tramite Reflection l’istanza del nuovo form da visualizzare: mi spiego meglio. Supponiamo di essere su Form2 e supponiamo di cliccare sul pulsante Next: il flusso di esecuzione entra nel metodo MoveToTransaction() e viene calcolato il nome del nuovo form: nel nostro caso FormsNavigator.Form3 (linea 22 del codice qui sopra). Il nuovo form viene creato (linea 23) e mostrato sullo schermo. Se il vecchio form non è Form1, lo chiudo, altrimenti rimane lì dov’è: Form1 è l’entry-point di questa applicazione, se lo chiudessi chiuderei tutto, perciò lo evito. La clessidra viene tolta e l’utente si ritrova con il nuovo form davanti.

Aggiungiamo un po’ di asincronia

Il codice qui sopra è semplice: permette di navigare avanti ed indietro sulle 5 form dell’applicazione. Supponiamo adesso che il passaggio da una form all’altra implichi il salvataggio di una qualche informazione su database locale, magari un SQL Server Compact Edition. Nulla ci vieta di mettere TextBox, ComboBox o altri controlli su ciascuna delle 5 form. Va da sè che il passaggio da uno stato all’altro deve prima occuparsi del salvataggio di queste informazioni da qualche parte, magari – come dicevo prima – un database locale. Questo caso può anche essere relativamente veloce, ma se la mole di dati cresce, oppure se utilizzo un database remoto, il tempo di attesa potrebbe anche crescere. Se c’è una cosa che non mi piace, è far aspettare l’utente per una cosa di cui non gliene può fregare di meno. Mi piacerebbe che la navigazione fosse veloce, che l’utente possa viaggiare da Form1 a Form2 senza aspettare troppo, mentre qualcun’altro sta facendo il lavoro sporco senza bloccare la UI, e senza far aspettare nessuno. Ho risolto così.

Alla classe TransactionManager di prima ho aggiunto un metodo privato:

1 void saveTransactionDataAsync() 2 { 3 System.Threading.Thread.Sleep(5000); 4 string msg = string.Format("Ho finito di salvare i dati della tx {0}", _nextIndex.ToString()); 5 MessageBox.Show(msg); 6 }

L’implementazione per questo post non fa nulla di interessante: il thread corrente viene messo in pausa per 5 secondi, poi visualizzo una MessageBox all’utente che lo informa che l’operazione di salvataggio dati è stata terminata con successo. Ho poi modificato l’implementazione del metodo MoveToTransaction che abbiamo visto prima, inserendo alla linea 21 le seguenti due linee di codice:

1 Thread thread = new Thread(saveTransactionDataAsync); 2 thread.Start();

In pratica, le operazioni su database vengono effettuate in un thread separato, mentre quello principale chiude ed apre le form molto velocemente, senza che l’utente si accorga di quello che sta succedendo in modo più “nascosto”.

Ci sono molte altre cose da dire, ma penso che per dare l’idea e per fornire qualche spunto può essere più che sufficiente. I commenti sono ben accetti.

Technorati Tags:    

Send to Kindle
.NET World

VivendoByte Windows Live Writer Suite su CodePlex

Ieri sera ho attivato su CodePlex il mio nuovo ed ultimo progetto, dedicato interamente alla mia piccola suite di plug-in per Windows Live Writer. Il progetto è raggiungibile qui.

Attualmente, il progetto comprende due plug-in: quello degli emoticons e quello dei Technorati Tags.

Per quest’ultimo, il mio preferito, c’è una bella novità: il buon Fabio Cozzolino ci ha lavorato su, e ha aggiunto una meravigliosa feature che rende il mio (nostro) plug-in il migliore di tutti i tempi (modestia a parte…ROFTL). Vi racconto in breve come funziona l’ultima release. Se la connessione ad Internet è disponibile, l’elenco dei tags viene fornito direttamente da un servizio Web esposto da Technorati. In locale viene comunque mantenuta una cache dei tags, che viene utilizzata quando Internet non è disponibile e non si ha la possibilità di accedere al servizio. Al servizio bisogna passare l’url del proprio blog, cosa che viene fatta automaticamente attraverso la tecnica di cui avevo parlato qua; se avete più di un account configurato dentro WLW avrete dei problemi – se è il vostro caso, fatemelo sapere, vi prego!

Le limitazioni con questo tipo di approccio sono due: l’elenco fornito da Technorati comprende al massimo 100 tags. E, cosa più grave, sono possibili al massimo 500 richieste al giorno al servizio Web. Se il plug-in viene scaricato ed utilizzato da molti, questo limite può essere raggiunto e sfondato facilmente. Se qualcuno ha qualche idea, è ben accetta…

Siccome il caricamento dei tags via rete da Technorati può richiedere qualche secondo, ho aggiunto una WaitingForm che non fa altro che mettervi in attesa, attraverso l’utilizzo di un BackgroundWorker.

Ho inoltre risolto due piccoli bug: nel codice HTML prodotto dal plug-in, alla fine c’era sempre un &nbsp; (spazio) di troppo. Nulla di disastroso, però mi dava fastidio, tant’è che lo cancellavo sempre a manina. Il secondo bug è un po’ più subdolo: la cache locale prima veniva salvata solo alla pressione del pulsante Ok. Adesso la cache viene salvata sull’evento FormClosing – sempre ed in ogni caso. E’ importante che la cache sia sempre sincronizzata con l’elenco di tags di Technorati, così se vi capita di scrivere post in posti (ooppss, gioco di parole) non connessi, avete sempre i vostri tags lì belli pronti da utilizzare.

Tutta la suite adesso è su CodePlex, perciò potete scaricare tutto da là, potete unirvi al progetto, potete dare idee e contributi. Io qualcosa in testa da sviluppare ce l’ho, e magari ne parlerò in un altro post. Tutto all’insegna di WPF.

Per comodità, vi metto qui direttamente i download dei due assembly, nel caso in cui non ve ne frega nulla di CodePlex, ma li volete usare e basta.

Download 1 : VivendoByte Windows Live Writer Technorati Tags Plugin

Download 2 : VivendoByte Windows Live Writer Emoticons Plugin

Entrambe le dll vanno copiate in C:Program FilesWindows LiveWriterPlugins.
Eliminate i vecchi assembly perchè ho cambiato il nome di namespace e – appunto – degli assembly.

Technorati Tags:    

Send to Kindle