<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Sviluppo .NET</title>
        <link>http://blogs.ugidotnet.org/idamiani/category/Sviluppo .NET.aspx</link>
        <description>Tip di programmazione, add-on di terze parti, esempi pratici tratti dai casi reali su cui lavoro, data-binding con .NET 2.0, script MSBuild, WinFX</description>
        <language>it-IT</language>
        <copyright>Igor Damiani</copyright>
        <generator>Subtext Version 2.6.0.0</generator>
        <item>
            <title>Un nuovo plugin per WLW: pubblicazione di immagini</title>
            <link>http://blogs.ugidotnet.org/idamiani/archive/2007/04/17/75692.aspx</link>
            <description>Mi sono dato alla creazione di un altro plugin per Windows Live Writer. Mi capita spesso di creare post il cui scopo è avere solo link a n immagini che vado preventivamente ad uploadare sul mio sito www.igordamiani.it. Per esempio, date un'occhiata al post relativo all'ultimo workshop. Quali sono le caratteristiche che saltano all'occhio?E' presto detto...  C'è un breve commento all'inizio C'è un'immagine o una fotografia visibile direttamente nel post Ci sono una serie di n link, che puntano direttamente a n immagini JPG uploadate sul sito Come dicevo, mi capita spesso di scrivere post di questo tipo e anche se non sembra, è piuttosto noioso farli, perchè sono sempre operazioni ripetitive.&amp;nbsp;Scegli le immagini giuste, ridimensionale, uploadale sul sito, scrivi il post inserendo a mano una descrizione ed il link corretto e via dicendo. Ho deciso quindi di scrivere un plugin per WLW per automizzare il più possibile questa cosa, così vi posso bombardare più spesso di fotografie. :-) Perchè non farlo in WPF per renderlo più accattivante? Arrivo al dunque, altrimenti qua non finisco più. La caratteristica fondamentale: la scelta delle fotografieIl plugin, già in fase di sviluppo, permette all'utente di puntare una directory sul proprio hard-disk e poter scegliere le immagini&amp;nbsp;da pubblicare oppure no. Do per scontato che le immagini nella directory siano già ridimensionate al punto giusto, perchè non faccio fare al mio plugin cose che altri software fanno già bene (come per esempio IrfanView). Dopo aver indicato la directory, si clicca su un pulsante che fa quanto segue:  void btnRefreshLocalPath(object sender, RoutedEventArgs args)
{
    DirectoryInfo di = new DirectoryInfo(txtLocalPath.Text);
    FileInfo[] files = di.GetFiles(&amp;quot;*.jpg&amp;quot;);

    lstImages.Items.Clear();
    foreach (FileInfo f in files)
    {
        ImageElement ie = new ImageElement(f.FullName);
        lstImages.Items.Add(ie);
    }
}
Il path viene recuperato dalla TextBox, viene utilizzato il metodo GetFiles() per ottenere la lista di tutti i files JPG (to be changed?)&amp;nbsp;nella directory. In seguito, la ListBox viene svuotata e viene creato un oggetto ImageElement per ogni file esistente. La classe ImageElement&amp;nbsp;incapsula tutta la logica che serve per&amp;nbsp;gestire le immagini.&amp;nbsp;Ogni&amp;nbsp;istanza di ImageElement&amp;nbsp;infatti permette di:

selezionare/deselezionare l'immagine (usando una CheckBox)
vedere&amp;nbsp;l'immagine e decidere se la si vuole o no (usando un'Image)
inserire una breve descrizione relativa all'immagine (usando una TextBox)
La classe ImageElement è uno UserControl scritto per WPF, quindi un po' XAML ed un po' C#. La parte XAML è forse la più interessante:
&amp;lt;UserControl x:Class=&amp;quot;VivendoByte.PostSomeImages.ImageElement&amp;quot;
    xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
    xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&amp;gt;

  &amp;lt;UserControl.Resources&amp;gt;
    &amp;lt;Style x:Key=&amp;quot;normal&amp;quot; TargetType=&amp;quot;{x:Type TextBox}&amp;quot;&amp;gt;
      &amp;lt;Style.Triggers&amp;gt;
        &amp;lt;DataTrigger Binding=&amp;quot;{Binding ElementName=chkSelected, Path=IsChecked}&amp;quot; Value=&amp;quot;True&amp;quot;&amp;gt;
          &amp;lt;Setter Property=&amp;quot;IsEnabled&amp;quot; Value=&amp;quot;True&amp;quot; /&amp;gt;
        &amp;lt;/DataTrigger&amp;gt;
        &amp;lt;DataTrigger Binding=&amp;quot;{Binding ElementName=chkSelected, Path=IsChecked}&amp;quot; Value=&amp;quot;False&amp;quot;&amp;gt;
          &amp;lt;Setter Property=&amp;quot;IsEnabled&amp;quot; Value=&amp;quot;False&amp;quot; /&amp;gt;
        &amp;lt;/DataTrigger&amp;gt;
      &amp;lt;/Style.Triggers&amp;gt;
    &amp;lt;/Style&amp;gt;
  &amp;lt;/UserControl.Resources&amp;gt;
  
  &amp;lt;StackPanel Orientation=&amp;quot;Vertical&amp;quot; Name=&amp;quot;panel&amp;quot;&amp;gt;
    &amp;lt;CheckBox Content=&amp;quot;Select this image&amp;quot; IsChecked=&amp;quot;False&amp;quot; Margin=&amp;quot;0 6 6 1&amp;quot; Name=&amp;quot;chkSelected&amp;quot; /&amp;gt;
    &amp;lt;Image Name=&amp;quot;imgImage&amp;quot; Stretch=&amp;quot;UniformToFill&amp;quot; Width=&amp;quot;180&amp;quot;&amp;gt;
      &amp;lt;Image.Source&amp;gt;
        &amp;lt;BitmapImage UriSource=&amp;quot;{StaticResource image}&amp;quot; /&amp;gt;
      &amp;lt;/Image.Source&amp;gt;
    &amp;lt;/Image&amp;gt;
    &amp;lt;TextBox Name=&amp;quot;txtDescription&amp;quot; Margin=&amp;quot;0 3 6 1&amp;quot; Style=&amp;quot;{StaticResource normal}&amp;quot; /&amp;gt;
    &amp;lt;Label Height=&amp;quot;3&amp;quot; Background=&amp;quot;SkyBlue&amp;quot; /&amp;gt;
  &amp;lt;/StackPanel&amp;gt;

&amp;lt;/UserControl&amp;gt;
Il visual-tree di ogni&amp;nbsp;istanza di ImageElement contiene uno StackPanel verticale, che contiene a sua volta una CheckBox, una Image, una TextBox ed infine una Label (che funge semplicemente da separatore - to be changed). Ho inserito due triggers per rendere più divertente la cosa: quando una certa immagine non è selezionata (proprietà IsChecked della CheckBox = False), allora non ha senso che l'utente ne inserisca la descrizione, quindi setto la proprietà IsEnabled della TextBox a False. Teoricamente, avrei potuto inserire un solo trigger, con qualche giro di binding, ma sono andato in fumo e...proprio non ce la faccio: va bene così! :-)
Un piccolo screenshot è come al solito doveroso.
 
Adesso è piuttosto spartano, ma l'idea è questa. Le foto selezionate vengono uploadate sul sito indicato, usando username e password specificate, poi ne viene presa la descrizione, viene fatto il link ed il tutto viene restituito a WLW. Appena è pronto lo pubblico, credo che possa interessare un po' di gente. Stay tuned.&lt;img src="http://blogs.ugidotnet.org/idamiani/aggbug/75692.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/idamiani/archive/2007/04/17/75692.aspx</guid>
            <pubDate>Tue, 17 Apr 2007 23:16:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/idamiani/archive/2007/04/17/75692.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/idamiani/comments/commentRss/75692.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/idamiani/services/trackbacks/75692.aspx</trackback:ping>
        </item>
        <item>
            <title>Ok, vada per l'hourglass, ma ci sono altri cursori?</title>
            <link>http://blogs.ugidotnet.org/idamiani/archive/2007/04/11/75213.aspx</link>
            <description>Nel pot di prima, abbiamo visto come mostrare l'icona della clessidra sul display del palmare, nel caso in cui dobbiamo comunicare all'utente che l'applicazione sta facendo qualcosa che dura un po' di tempo. Nel codice abbiamo utilizzato una costante intera valorizzata a 32514, 0x7F02. Posso farlo?Quali altre icone abbiamo a disposizione?Che valori devo utilizzare per poterle visualizzare sullo schermo? La soluzione più rapida consiste nell'installarsi in locale sul proprio PC il Microsoft Platform Builder 5.0, per gli amici il Windows Mobile 5.0 Pocket PC SDK, che contiene tutte le informazioni necessarie allo sviluppo su mobile. Tale documentazione contiene anche info sulla funzione LoadCursor, di cui abbiamo già parlato. La pagina relativa a questa funzione ci svela alcuni dettagli interessanti, come i nomi delle costanti IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND e così via, fino a IDC_WAIT, che guarda caso è la clessidra. Non ci vengono comunicati i valori di queste costanti, ma la soluzione è dietro l'angolo. Il file header di queste funzioni è Winuser.h, è sufficiente cercarlo sul proprio hard-disk: lo troverete solo se avete installato l'SDK di cui sopra. A me è finito in queste directory: C:\Programmi\Microsoft SDKs\Windows\v6.0\IncludeC:\Programmi\Windows CE Tools\wce500\Windows Mobile 5.0 Pocket PC SDK\Include\Armv4i Indipendentemente dal file che guardate, i valori delle costanti è ovviamente sempre lo stesso, e cioè:  /*
 * Standard Cursor IDs
 */
#define IDC_ARROW           MAKEINTRESOURCE(32512)
#define IDC_IBEAM           MAKEINTRESOURCE(32513)
#define IDC_WAIT            MAKEINTRESOURCE(32514)
#define IDC_CROSS           MAKEINTRESOURCE(32515)
#define IDC_UPARROW         MAKEINTRESOURCE(32516)
#define IDC_SIZE            MAKEINTRESOURCE(32640)  /* OBSOLETE: use IDC_SIZEALL */
#define IDC_ICON            MAKEINTRESOURCE(32641)  /* OBSOLETE: use IDC_ARROW */
#define IDC_SIZENWSE        MAKEINTRESOURCE(32642)
#define IDC_SIZENESW        MAKEINTRESOURCE(32643)
#define IDC_SIZEWE          MAKEINTRESOURCE(32644)
#define IDC_SIZENS          MAKEINTRESOURCE(32645)
#define IDC_SIZEALL         MAKEINTRESOURCE(32646)
#define IDC_NO              MAKEINTRESOURCE(32648) /*not in win3.1 */
#if(WINVER &amp;gt;= 0x0500)
#define IDC_HAND            MAKEINTRESOURCE(32649)
#endif /* WINVER &amp;gt;= 0x0500 */
#define IDC_APPSTARTING     MAKEINTRESOURCE(32650) /*not in win3.1 */
#if(WINVER &amp;gt;= 0x0400)
#define IDC_HELP            MAKEINTRESOURCE(32651)
#endif /* WINVER &amp;gt;= 0x0400 */

Se invece della clessidra volete mettere un'altra icona, è sufficiente cambiare il cursorID. Consiglio spassionato? Definire un enum che contiene tutti i valori per avere codice più leggibile, più chiaro e&amp;nbsp;più semplice da tramandare ai posteri (ogni riferimento a Pier ex-collega è puramente casuale).&lt;img src="http://blogs.ugidotnet.org/idamiani/aggbug/75213.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/idamiani/archive/2007/04/11/75213.aspx</guid>
            <pubDate>Wed, 11 Apr 2007 17:12:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/idamiani/archive/2007/04/11/75213.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/idamiani/comments/commentRss/75213.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/idamiani/services/trackbacks/75213.aspx</trackback:ping>
        </item>
        <item>
            <title>Mostrare un Hourglass sul palmare con il Compact Framework</title>
            <link>http://blogs.ugidotnet.org/idamiani/archive/2007/04/11/75189.aspx</link>
            <description>Se il software che state sviluppando per un dispositivo mobile compie un'operazione lunga, potete mostrare sullo schermo una clessidra - l'Hourglass dell'oggetto di questo post. Con Windows Mobile 5.0, questa clessidra in realtà è un piccolo cerchio centrato sullo schermo, diviso in 4 settori colorati (rosso/giallo/blu/verde). Ovviamente tale clessidra non è modale, perciò il vostro codice prosegue l'esecuzione fino a quando non siete voi a decidere che la clessidra non è più necessaria. Un'altra piccola precisazione: su palmari non avete il concetto di puntatore del mouse, perciò non potete fare quello che è possibile con il .NET Framework standard, ovvero cambiare il puntatore solo su un controllo che volete voi. Difatti, la visualizzazione della clessidra è consentita solo al centro dello schermo. Come farlo nelle vostre applicazioni per palmari? Seguite la ricetta che ho preparato per voi. Ingredienti per uno sviluppatore (difficoltà bassa)Una costante di tipo intDue funzioni extern static importate dalla coredll.dllUna funzione managed con un parametro di tipo bool e ritorna void PreparazionePrendete una Windows Form, e dichiarate quanto segue:  private const int HourGlassCursorID = 32514;

[DllImport(&amp;quot;coredll.dll&amp;quot;)]
private extern static int LoadCursor(int zeroValue, int cursorID);

[DllImport(&amp;quot;coredll.dll&amp;quot;)]
private extern static int SetCursor(int cursorHandle);
Lasciar cuocere 1 minuto a fuoco lento. La costante è di tipo int e deve valere 32514, equivalente a 0x7F02. Poi vengono dichiarate due funzioni extern, tramite P/Invoke, entrambe definite nella library coredll.dll. La funzione LoadCursor carica un cursore dato un cursorID; il cursore viene ritornato da un tipo int che è un cursorHandle.Quello che manca è la funzione managed:

private void ShowWaitCursor(bool ShowCursor)
{
    int cursorHandle = 0;
    if (ShowCursor)
    {
        cursorHandle = LoadCursor(0, HourGlassCursorID);
    }
    SetCursor(cursorHandle);
}
Dare una mescolata con un cucchiaio di legno. La vostra applicazione può tranquillamente utilizzare la funzione ShowWaitCursor per visualizzare/nascondere la clessidra sul display del palmare. Attenzione, come dicevo prima, la clessidra, indipendentemente dalla forma che assume, non è modale, perciò, per esempio, potete scrivere quanto segue:

private void btnMioBottone_Click(object sender, EventArgs e)
{
    ShowWaitCursor(true);
    
    /* Faccio 1.000 cose che durano un po' */
    
    ShowWaitCursor(false);
}
Ricordatevi sempre ed in ogni caso di disattivare la clessidra, altrimenti questa rimane visibile sullo schermo anche se l'applicazione continua a funzionare regolarmente, ma disturbando notevolmente la digestione dell'utente.
Da servire freddo, magari con un buon vino del Friuli. :-)Buon appetito.&lt;img src="http://blogs.ugidotnet.org/idamiani/aggbug/75189.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/idamiani/archive/2007/04/11/75189.aspx</guid>
            <pubDate>Wed, 11 Apr 2007 13:08:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/idamiani/archive/2007/04/11/75189.aspx#feedback</comments>
            <slash:comments>7</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/idamiani/comments/commentRss/75189.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/idamiani/services/trackbacks/75189.aspx</trackback:ping>
        </item>
        <item>
            <title>Download aggiornato per il VivendoByte Emoticons plug-in</title>
            <link>http://blogs.ugidotnet.org/idamiani/archive/2007/04/07/74976.aspx</link>
            <description>Molti, molti mesi fa qualcuno di UGI mi aveva segnalato un problema sul mio plug-in in WPF per Windows Live Writer. Avevo realizzato un piccolo batch che copiava le immagini dalla directory di installazione alla directory dove poi il plug-in si aspettava di trovarle.&amp;nbsp;Il fatto era che il batch le copiava in un posto, e poi il plug-in le cercava in un altro e quindi veniva sollevata un'exception: questo mi pare di ricordare che succedesse solo su un OS non localizzato in italiano, ma non ricordo bene 'sta cosa. L'amico di UGI che mi aveva segnalato la cosa non si deve offendere se non ricordo il suo nome: dimentico un po' troppo spesso i nomi delle persone, persino degli amici che conosco da 20 anni!!!! E non è una frase fatta solo per farmi perdonare, è così sul serio. Ho appena uploadato la versione corretta dell'installer, scaricabile da qui. L'installer installa di default dentro: C:\Program Files\VivendoByte\Emoticons plug-in for Windows Live Writer Qui dentro trovate l'assembly VivendoByteEmoticons.dll che va copiato manualmente dentro C:\Program Files\Windows Live Writer\Plugins. Volendo lo si può far fare al file batch Install.bat: assicuratevi solo di farlo girare come Administrator, perchè altrimenti non ha i permessi per accedere a C:\Program Files. Anche se non vi dice nulla, al primo avvio il plug-in copia automaticamente le emoticons nella directory giusta, per cui adesso siete a posto. Sotto il mio Windows Vista English tale directory è C:\ProgramData\VivendoByte Emoticons. Volendo, potete aggiungere/rimuovere tutte le emoticons che volete, o creare tante cartelle per poterle organizzare come volete voi. Il plug-in è scaricabile gratuitamente da qui&lt;img src="http://blogs.ugidotnet.org/idamiani/aggbug/74976.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/idamiani/archive/2007/04/07/74976.aspx</guid>
            <pubDate>Sat, 07 Apr 2007 20:27:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/idamiani/archive/2007/04/07/74976.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/idamiani/comments/commentRss/74976.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/idamiani/services/trackbacks/74976.aspx</trackback:ping>
        </item>
        <item>
            <title>Connettere l'emulatore Pocket PC via ActiveSync</title>
            <link>http://blogs.ugidotnet.org/idamiani/archive/2007/04/06/74895.aspx</link>
            <description>Avrete capito dagli ultimi post che ho scritto che attualmente mi occupo dello sviluppo su dispositivi mobile, Pocket PC 2003 e Windows Mobile: questo vuol dire finalmente tanto .NET e C#, sfruttando il Compact Framework con tutti gli annessi e connessi. La cosa più affascinante è sentir parlare di classi astratte, di metodi factory e di tutti concetti che nell'azienda dove ero prima semplicemente mi sognavo. :-) Oggi ho cominciato ad ingranare sul serio. E' difficile inserirsi in un progetto già in fase di sviluppo, mi devo ritagliare il mio spazio, e soprattutto inserirmi nel team che definire vulcanico è un eufemismo. Sviluppando su palmare, è essenziale sfruttare al meglio l'emulatore offerto da Visual Studio 2005. L'emulatore è piuttosto affidabile, e segue lo stesso comportamento di un palmare vero e proprio. Ci sono ovviamente alcuni vantaggi nell'usare un emulatore piuttosto che un palmare vero e proprio:  non consumate batterie di alcun tipo  se dovete digitare qualcosa sull'emulatore, potete farlo usando la tastiera Con Visual Studio 2005 potete persino simulare la connessione tramite ActiveSync.&amp;nbsp;Ieri pomeriggio ho perso un pochino di tempo su questo. Il mio codice deve scaricare da un server Web un file zip e salvarselo in locale per dezipparlo e fare qualche lavoretto sui files contenuti nel file compresso. Il codice è simile a quanto riportato qui di seguito:  public void DownloadPackage()
{
    int byteRead = 0;
    int totalByteRead = 0;
    int offset = 0;
    int packet = 1024;
    Uri url = new Uri(@&amp;quot;http://server/download.zip&amp;quot;);

    HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
    Stream odlDownload = myReq.GetResponse().GetResponseStream();
    ...
    ...
}
Una volta ottenuto il riferimento allo stream, è possibile scaricare il file via http. Il problema è: come poter andare su Internet (o sulla propria LAN)&amp;nbsp;con l'emulatore del Pocket PC? Per default, l'emulatore non è connesso alla rete, e quindi non può accedere ad http, nemmeno se si tratta di raggiungere un sito Web hostato da IIS sul PC di sviluppo.
La risposta, una volta che la si conosce, è piuttosto semplice. Installiamo innanzitutto ActiveSync sul PC su cui stiamo sviluppando. Poi tiriamo su l'emulatore del Pocket PC premendo F5 da Visual Studio 2005:&amp;nbsp; questa operazione compila il progetto, attiva l'emulatore, fa il deploy della soluzione sul palmare e fa partire l'eseguibile. La soluzione consiste nel connettere il Pocket PC emulato all'ActiveSync sul PC: per farlo, è sufficiente andare su Tools --&amp;gt; Device Emulator Manager,&amp;nbsp;trovare l'emulatore che è in esecuzione, cliccare col destro e cliccare sulla voce Cradle. Se l'ActiveSync sul PC accetta connessioni da USB, vedrete che l'emulatore si connette normalmente come se fosse un palmare reale a tutti gli effetti. Stessa cosa per il PC: l'icona di ActiveSync nella tray-bar diventa verde e dovrebbe partire il wizard che permette la creazione di una relazione tra PC e palmare. Non fatevi troppe menate, impostate la relazione come 'ospite' e siete a posto.&lt;img src="http://blogs.ugidotnet.org/idamiani/aggbug/74895.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/idamiani/archive/2007/04/06/74895.aspx</guid>
            <pubDate>Fri, 06 Apr 2007 10:24:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/idamiani/archive/2007/04/06/74895.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/idamiani/comments/commentRss/74895.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/idamiani/services/trackbacks/74895.aspx</trackback:ping>
        </item>
        <item>
            <title>Zip/Unzip con il compact framework?</title>
            <link>http://blogs.ugidotnet.org/idamiani/archive/2007/04/04/74757.aspx</link>
            <description>Anche se fate fatica a trovare qualcosa per manipolare i files zip con il Compact Framework, sappiate che qualcosa c'è. Innanzitutto trovate le Xceed Zip for .NET CF, ma sono a pagamento, e costano la bellezza di 499,95 dollari. L'elenco delle caratteristiche è certamente interessante, ma se avete bisogno di qualcosa di più semplice (e gratuito) potete ricorrere alla libreria SharpZipLib. Essa è disponibile sotto la licenza GPL. L'ho provata in questi giorni per applicarla al progetto su cui sto lavorando. Siccome ho avuto qualche problemino, voglio segnalarlo anche a voi per evitare di perdere troppo tempo come è capitato a me. Innanzitutto, mentre sul PC Desktop l'assembly SharpZipLib deve essere installato nella GAC, questo ovviamente non vale per i Pocket PC: è sufficiente che la dll sia nella stessa directory dell'applicazione per poterla utilizzare. L'altra questione&amp;nbsp;è un po' più pesante, e&amp;nbsp;solo grazie all'aiuto del buon Marco Minerva sono arrivato alla soluzione in tempi rapidi, dato che lui&amp;nbsp;ha incontrato il mio stesso problema più o meno un mesetto fa. Se utilizzate esattamente lo stesso assembly che scaricate dal sito, al momento di comprimere/decomprimere utilizzando la classe FastZip il codice solleverà un'eccezione, che adesso purtroppo non riesco ad indicarvi in modo preciso: dovrebbe essere qualcosa del tipo MethodNotFoundException. Questo è dovuto al fatto che l'assembly di SharpZipLib tenta di accedere alla proprietà CurrentCulture esposta da System.Threading.Thread.CurrentThread. La proprietà CurrentCulture esiste nel .NET Framework, ma non nella sua versione per palmari. SharpZipLib ha bisogno di accedere a questa proprietà per poter formattare a video le date in modo opportuno in base alla vostra Culture. Se non avete bisogno di queste informazioni, ad esempio se volete semplicemente prendere uno zip e decomprimerlo da qualche parte, potete fare quello che ha fatto il buon Marco, che ha esaminato il codice, lo ha ripulito e reso "funzionante" davvero su CF.&lt;img src="http://blogs.ugidotnet.org/idamiani/aggbug/74757.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/idamiani/archive/2007/04/04/74757.aspx</guid>
            <pubDate>Wed, 04 Apr 2007 23:24:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/idamiani/archive/2007/04/04/74757.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/idamiani/comments/commentRss/74757.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/idamiani/services/trackbacks/74757.aspx</trackback:ping>
        </item>
        <item>
            <title>Bitmap vettoriali sulle Window</title>
            <link>http://blogs.ugidotnet.org/idamiani/archive/2007/03/26/73933.aspx</link>
            <description>Con WPF tutto deve (può?) essere scalabile. Basta usare le bitmap, quindi, perchè se ridimensioniamo una Window, l'immagine viene ingrandita a sua volta e potrebbe sgranare in modo spiacevole. L'ideale è quindi usare icone ed immagini vettoriali, che possano scalare in modo naturale. Il sito grafile.com mette a disposizione (a pagamento, e secondo me sono anche piuttosto cari) diverse collection di icone vettoriali, suddivise per argomenti (business, character, control, icon, database, documentation, file &amp;amp; folder, network...insomma, le solite cose). Dicevo...mi sembrano un po' cari, perchè far pagare&amp;nbsp;72 dollari un pacchetto con 56 icone mi sembra un po' esagerato. Il resto dei pacchetti non è da meno. Fate voi, io l'ho segnalato e basta.&lt;img src="http://blogs.ugidotnet.org/idamiani/aggbug/73933.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/idamiani/archive/2007/03/26/73933.aspx</guid>
            <pubDate>Mon, 26 Mar 2007 19:01:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/idamiani/archive/2007/03/26/73933.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/idamiani/comments/commentRss/73933.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/idamiani/services/trackbacks/73933.aspx</trackback:ping>
        </item>
        <item>
            <title>Le mie (personali) linee-guida per il layout con WPF</title>
            <link>http://blogs.ugidotnet.org/idamiani/archive/2007/03/26/73931.aspx</link>
            <description>WPF è un framework dalle innumerevoli caratteristiche che possono lasciare - credo - disorientato il neofita. Al di là di tante squisitezza tecnologiche, la cosa che mi ha fatto fatto più perdere tempo è l' auto-layout, ovvero la capacità di WPF di dimensionare e di posizionare i controlli sulle Windows o sulle Page in modo completamente automatico, seguendo logiche che probabilmente sono più vicine alla creazione delle pagine Web. L'auto-layout permette innanzitutto di creare interfacce utente indipendenti dalla risoluzione. Scordatevi quindi di trascinare controlli dalla ToolBox sulla Window e di posizionarli dove e come volete voi. In realtà, potete farlo ancora: è sufficiente utilizzare il Canvas per ottenere esattamente lo stesso tipo di posizionamento che avete oggi con le classiche Windows Forms. Ovvio dire che l'utilizzo del Canvas è sconsigliato. La morale è questa: qualsiasi controllo assume le dimensioni del container che lo ospita. Se avete una Window e all'interno di essa definite una Grid con una sola riga ed una sola colonna, tale Grid sarà grande esattamente come la Window:  &amp;lt;Window x:Class=&amp;quot;VivendoByte.CastingManager.TestWindow&amp;quot;
    xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
    xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;
    Title=&amp;quot;test&amp;quot; Background=&amp;quot;LightYellow&amp;quot;&amp;gt;
  &amp;lt;Grid Background=&amp;quot;LightGray&amp;quot;&amp;gt;
    &amp;lt;Grid.ColumnDefinitions&amp;gt;&amp;lt;ColumnDefinition /&amp;gt;&amp;lt;/Grid.ColumnDefinitions&amp;gt;
    &amp;lt;Grid.RowDefinitions&amp;gt;&amp;lt;RowDefinition /&amp;gt;&amp;lt;/Grid.RowDefinitions&amp;gt;
  &amp;lt;/Grid&amp;gt;
&amp;lt;/Window&amp;gt;
La Grid ha uno sfondo LightGray, mentre il colore di sfondo della Window è LightYellow. Quest'ultimo colore però non viene visto, proprio perchè la Grid assume automaticamente le stesse dimensioni della Window e ne ricopre interamente la superficie. Se alla Grid assegniamo una proprietà Margin le cose cominciano a cambiare:

&amp;lt;Grid Background=&amp;quot;LightGray&amp;quot; Margin=&amp;quot;20&amp;quot;&amp;gt;
...
&amp;lt;/Grid&amp;gt;
In questi giorni, di sera, sto sviluppando un software commerciale in WPF, convertendo un software scritto in VB6.0 alcuni anni fa. Ho dovuto quindi ripensare in parte la struttura dell'applicazione, e ho dovuto anche ridisegnare le form trasformandole in Window di WPF. Come è facile intuire, non sono form semplici e ho dovuto litigare un pochino per ottenere un layout degno di questo nome. Le mie linee-guide sono, per adesso, le seguenti:

Non assegno mai dimensioni ai controlli, lascio che esse vengano ereditate dai controlli contenitori e più in alto nel visual-tree
Per evitare di avere Window definite in un unico gigantesco (e poco leggibili)&amp;nbsp;XAML, definisco uno o più UserControl separati, che mi aiutano a disegnare poco alla volta&amp;nbsp;o a debuggare meglio lo XAML stesso.
Evito di assegnare in modo statico le dimensioni ai vari UserControl: come nel punto (1), faccio in modo che le dimensioni vengono assegnate automaticamente dal container nel quale lo UserControl viene inserito.
Gioco con i Margin (spazio tra un controllo e l'altro) ed i Padding (spazio tra il bordo di un controllo ed il suo contenuto)&amp;nbsp;per staccare i controlli l'uno dall'altro e per riempire in modo piacevole uno spazio (che sia GroupBox, un TabItem o simili).
Gli unici momenti&amp;nbsp;in cui assegno esplicitamente una Width&amp;nbsp;od una Height sono le Grid. Se una Grid possiede solo righe, assegno le altezze di queste righe. Se una Grid possiede solo colonne, assegno le larghezze di queste colonne.
Mi piace assegnare MinWidth e MinHeight alle Window. L'utente può ridimensionare finchè vuole, ma senza esagerare.
Non uso mai e poi mai unità di misura particolari (come px, cm o roba del genere).
Uso spesso l'asterisco (*) nei dimensionamenti, per indicare quando una colonna od una riga possono allargarsi o stringersi a piacere. Esempio: una Grid con&amp;nbsp;2 righe. 1° Riga : altezza fissa, contiene uno UserControl per&amp;nbsp;esprimere diversi criteri&amp;nbsp;con i quali fare ricerche. 2° Riga : altezza a piacere, contiene una ListBox che contiene i risultati della ricerca.
Non so se sono indicazioni corrette oppure no. Le ho semplicemente estratte dagli XAML e dalla mia esperienza proveniente dal mio primo vero progetto serio in WPF e mi sono state utili.&lt;img src="http://blogs.ugidotnet.org/idamiani/aggbug/73931.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/idamiani/archive/2007/03/26/73931.aspx</guid>
            <pubDate>Mon, 26 Mar 2007 18:40:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/idamiani/archive/2007/03/26/73931.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/idamiani/comments/commentRss/73931.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/idamiani/services/trackbacks/73931.aspx</trackback:ping>
        </item>
        <item>
            <title>Il TabControl di WPF</title>
            <link>http://blogs.ugidotnet.org/idamiani/archive/2007/03/23/73675.aspx</link>
            <description>Uno dei controlli che Petzold non cita nel suo libro è il TabControl, al punto che pensavo che non fosse compreso tra i controlli nativi di WPF. Ieri, sfogliando MSDN a piacimento, ho raggiunto il namespace System.Windows.Controls e mi capita sottomano proprio la classe TabControl. Quando mi capita di vedere una classe che non sapevo esistesse, mi diverto sempre a guardare la Inheritance Hierarchy, perchè&amp;nbsp;vedendo da cosa deriva una determinata classe si possono intuire caratteristiche o capacità ereditate da altri. In questo caso specifico, ho notato che TabControl eredita anche da ItemsControl, così come la ListBox, i menù, la StatusBar e così via. MSDN dà una descrizione per la classe ItemsControl, che recita così: Represents a control that can be used to present a collection of items. La collection di items per un controllo di tipo TabControl non sono nient'altro che i suoi TabItem. L'utente naviga all'interno di un TabControl selezionando il tab che gli interessa: seleziona un Item tra gli Items disponibili, esattamente come accade con una ListBox. Il TabControl è ovviamente definibile via XAML in modo molto semplice:  &amp;lt;TabControl Name=&amp;quot;tabSchede&amp;quot;&amp;gt;
    &amp;lt;TabItem Header=&amp;quot;Dati Anagrafici&amp;quot; /&amp;gt;
    &amp;lt;TabItem Header=&amp;quot;Dati Fisici&amp;quot; /&amp;gt;
    &amp;lt;TabItem Header=&amp;quot;Altre Informazioni&amp;quot; /&amp;gt;
&amp;lt;/TabControl&amp;gt;
Via codice, possiamo capire se un TabControl ha qualche Items accedendo alla proprietà HasItems. La proprietà Header di ciascun TabItem non è semplicemente string, ma può essere un qualsiasi content, esattamente come accade per tutti gli altri controlli di WPF. Ieri sera mi sono divertito a rendere un po' diverso l'header di ciascun TabItem. Per esempio, con XAML possiede utilizzare la notazione nota con property elements e scrivere una cosa simile a questa:

  &amp;lt;TabControl Margin=&amp;quot;5&amp;quot;&amp;gt;
    &amp;lt;TabItem&amp;gt;
      &amp;lt;TabItem.Header&amp;gt;
          &amp;lt;StackPanel Orientation=&amp;quot;Horizontal&amp;quot;&amp;gt;
            &amp;lt;Rectangle Stroke=&amp;quot;Black&amp;quot; Fill=&amp;quot;Red&amp;quot; Width=&amp;quot;10&amp;quot; Height=&amp;quot;10&amp;quot; /&amp;gt;
            &amp;lt;Label Margin=&amp;quot;6 2 0 0&amp;quot; Padding=&amp;quot;0&amp;quot; Content=&amp;quot;Dati Anagrafici&amp;quot; /&amp;gt;
          &amp;lt;/StackPanel&amp;gt;
      &amp;lt;/TabItem.Header&amp;gt;
    &amp;lt;/TabItem&amp;gt;
  &amp;lt;/TabControl&amp;gt;
L'header del TabItem contiene uno StackPanel orizzontale, che contiene a sua volta un piccolo rettangolo colorato ed una semplice Label con del testo. Ho giocherellato con Padding e Margin per posizionare gli elementi in modo decente. Ipotizzo che avremmo potuto usare anche la proprietà ItemTemplate, che definisce l'aspetto utilizzato per generare gli items: ci proverò, perchè questa è una cosa che ho solo in testa e non l'ho provata sul campo. La cosa interessante è che i TabItem possono anche essere generati dal runtime di WPF via data-binding, perchè è sufficiente bindare ItemsSource&amp;nbsp;così come faremmo con una ListBox.
Ovviamente, ogni TabItem ha una proprietà Content che definisce il contenuto reale di ogni tab. Il più delle volte il contenuto è organizzato con un altro Panel (la Grid, per esempio) per posizionare i vari controlli che ci interessa vedere sulla Window. La proprietà TabStripPlacement&amp;nbsp;permette di decidere dove vogliamo vedere i tab del TabControl (Top, Bottom, Left o Right). La proprietà SelectedItem&amp;nbsp;ci dà un riferimento al TabItem correntemente selezionato, mentre SelectedIndex&amp;nbsp;il suo indice.
Basta dare un'occhiata all'elenco delle public properties del TabControl per capire come sia possibile applicare diversi stili o template ad ogni elemento che compone&amp;nbsp;il controllo, fornendo un'ampia gamma di possibilità per personalizzare l'aspetto del TabControl stesso.&lt;img src="http://blogs.ugidotnet.org/idamiani/aggbug/73675.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/idamiani/archive/2007/03/23/73675.aspx</guid>
            <pubDate>Fri, 23 Mar 2007 12:15:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/idamiani/archive/2007/03/23/73675.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/idamiani/comments/commentRss/73675.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/idamiani/services/trackbacks/73675.aspx</trackback:ping>
        </item>
        <item>
            <title>Un domain model per lavorare con WPF e NHibernate</title>
            <link>http://blogs.ugidotnet.org/idamiani/archive/2007/03/19/73262.aspx</link>
            <description>Da quando ho scoperto NHibernate, ormai più di un anno fa, ho sempre disegnato il mio domain-model in modo tale che far persistere le mie entità con questo framework fosse il più naturale possibile. Dal punto di vista pratico, ciò significa che tutte le entità del domain-model derivino tutte da una classe astratta Entity, che definisce una sola proprietà ID di tipo int.  public abstract class Entity
{
    public int ID
    {
        get { return _id; }
        set { _id = value; }
    }
}
Ogni volta che una classe&amp;nbsp;del mio domain-model deve essere persistita&amp;nbsp;attraverso NHibernate, la faccio derivare da Entity. In questo modo, ogni classe espone una proprietà ID che contiene la chiave univoca dell'istanza. Ovviamente tutte le entità hanno un unsaved-value = 0, e questo permette all'engine di NHibernate di capire in che modo persistere una determinata istanza sul database.&amp;nbsp;Quando ID = 0, l'oggetto esiste solo in memoria (oggetto transiente)&amp;nbsp;e non è stato ancora persistito. Se ID != 0, l'oggetto in memoria esiste anche sul database (oggetto persistente).
Tutto deriva da Entity? Bene, un vantaggio anche per il mio DALIl fatto che tutte le mie entità derivino dalla classe astratta Entity porta anche un vantaggio all'interno del DAL. Di solito, i miei DAL utilizzano i generics. Pertanto, posso applicare un constraint, dicendo che il tipo T deve per forza rappresentare una classe derivata da Entity. La morale di tutto questo è che non posso istanziare un'istanza di DataProvider&amp;lt;int&amp;gt; o un DataProvider&amp;lt;MyAppSettings&amp;gt;, ma solo di DataProvider&amp;lt;Artista&amp;gt;, DataProvider&amp;lt;Auto&amp;gt;, DataProvider&amp;lt;Competenza&amp;gt; e così via, cioè solo di quelle classi che so che dovranno essere rese persistenti da NHibernate.
Fin qua nulla di male. Cosa succede però se devo creare un domain-model da utilizzare all'interno di un'applicazione WPF?&amp;nbsp;Con .NET 2.0, ad esempio, per poter sfruttare le potenzialità di data-binding sulle Windows Forms era opportuno creare un domain-model le cui classi implementassero l'interfaccia INotifyPropertyChanged. Questa interfaccia consente l'implementazione di un data-binding efficiente tra un oggetto ed i controlli sulla UI, e viceversa. Questo approccio funziona ancora in WPF, non è cambiato nulla da questo punto di vista, ma per tutta una serie di ragioni è opportuno ragionare in modo diverso.
Perchè utilizzare le dependency properties?Questo "modo diverso" consiste nell'utilizzare le dependency properties, che consentono di sfruttare features avanzate come data-binding serio, che con WPF va molto al di là delle potenzialità offerte da .NET 2.0. Per esempio, potremmo bindare la proprietà Eta della classe Artista con uno Shape di qualche tipo, in modo tale che a seconda dell'età&amp;nbsp;il Rectangle che abbiamo sulla Window si allunghi o si accorci. Oppure, potremmo definire un trigger sulla proprietà booleana&amp;nbsp;PossiedeAuto, in modo tale che quando vale true, appaia un'immagine da qualche parte, altrimenti no. In generale, molte delle funzionalità di WPF (stili, template, trigger, data-binding, animazioni, etc.) sfruttano proprio&amp;nbsp;le dependency properties: se sappiamo che il nostro domain-model dovrà in qualche modo interagire con l'engine di WPF, forse è&amp;nbsp;bene pensarci prima e disegnare le nostri classi in modo opportuno.
Quando un oggetto intende utilizzare le dependency properties, deve derivare dalla classe DependencyObject di WPF. Qui abbiamo un problema: le entità del nostro domain-model dovrebbero derivare da due classi, sia DependencyObject che Entity. Questo in .NET non è possibile, in quanto non è prevista ereditarietà multipla. Poco male, è sufficiente pensare diversamente e invece di aver a che fare con una classe&amp;nbsp;Entity, definiamo un'interfaccia IPersistableEntity (dal nome altisonante :-).
using System;
using System.Windows;

namespace DomainModel
{
    public interface IPersistableEntity
    {
        int ID { get; set; }
    }

    public class Artista : DependencyObject, IPersistableEntity
    {
        public static readonly DependencyProperty IDProperty;

        public int ID
        {
            get { return (int)GetValue(IDProperty); }
            set { SetValue(IDProperty, value); }
        }

        static Artista()
        {
            Type tp = typeof(Artista);

            IDProperty = DependencyProperty.Register(&amp;quot;ID&amp;quot;, typeof(int), tp);
        }
    }
}
La classe Artista qui sopra è&amp;nbsp;stata compressa/adattata/sistemata per riportare&amp;nbsp;parte&amp;nbsp;del codice. Il codice di produzione è evidentemente organizzato&amp;nbsp;un po' meglio e&amp;nbsp;migliorato sotto diversi aspetti.&amp;nbsp;Comunque sia, la classe eredita da DependencyObject ed implementa l'interfaccia IPersistableEntity. Quest'ultima in particolare richiede l'implementazione di una proprietà ID di tipo int, che è stata realizzata come dependency property. Questo implica una serie di cose che sono ben visibili dal codice: un field pubblico IDProperty di tipo DependencyProperty, un costruttore privato che registra tutte le dependency properties che mi servono.
ConclusioneImplementando il domain-model secondo questi criteri, sviluppo classi che possono&amp;nbsp;lavorare sull'interfaccia di&amp;nbsp;WPF e possono essere persistite da NHibernate passando dal DAL del progetto che sto sviluppando (progetto per una volta non freeware).&lt;img src="http://blogs.ugidotnet.org/idamiani/aggbug/73262.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Igor Damiani</dc:creator>
            <guid>http://blogs.ugidotnet.org/idamiani/archive/2007/03/19/73262.aspx</guid>
            <pubDate>Mon, 19 Mar 2007 13:54:00 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/idamiani/archive/2007/03/19/73262.aspx#feedback</comments>
            <slash:comments>11</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/idamiani/comments/commentRss/73262.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/idamiani/services/trackbacks/73262.aspx</trackback:ping>
        </item>
    </channel>
</rss>