<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://dotnetumbria.org/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="it"><title type="html">Articoli</title><subtitle type="html">Articoli vari degli iscritti a DotNetUmbria</subtitle><id>http://dotnetumbria.org/blogs/articoli/atom.aspx</id><link rel="alternate" type="text/html" href="http://dotnetumbria.org/blogs/articoli/default.aspx" /><link rel="self" type="application/atom+xml" href="http://dotnetumbria.org/blogs/articoli/atom.aspx" /><generator uri="http://communityserver.org" version="4.0.30417.1769">Community Server</generator><updated>2007-12-05T13:28:00Z</updated><entry><title>Un Chatbot per postare su dotnetumbria.org</title><link rel="alternate" type="text/html" href="/blogs/articoli/archive/2008/07/30/un-chatbot-per-postare-su-dotnetumbria-org.aspx" /><id>/blogs/articoli/archive/2008/07/30/un-chatbot-per-postare-su-dotnetumbria-org.aspx</id><published>2008-07-29T23:26:13Z</published><updated>2008-07-29T23:26:13Z</updated><content type="html">&lt;p&gt;Ciao a tutti, ho ripreso una idea di Lorenzo Maiorfi, quella di &amp;quot;varare&amp;quot; (cito testualmente) &lt;br /&gt;&amp;quot;una nuova iniziativa a livello di pubblicazione di contenuti che preveda la realizzazione di micro-post che in 4 righe riescano a dare un&amp;#39;idea di quello che gli stessi membri della community fanno nel loro quotidiano professionale&amp;quot;. &lt;/p&gt; &lt;p&gt;Dopo un po&amp;#39; di ragionamento su questa allettante iniziativa mi è venuta l&amp;#39;idea di creare un piccolo servizio di pubblicazione dei contenuti ultraveloce. &lt;/p&gt; &lt;p&gt;E cosa c&amp;#39;è di più veloce per raccontare se stessi di una sessione con messanger ? &lt;/p&gt; &lt;p&gt;In moltissimi utiliziamo messanger e aprire una conversazione è veramente questione di un attimo. &lt;/p&gt; &lt;p&gt;Così ho creato un piccolo account &lt;a href="mailto:dotnetumbria@live.it"&gt;dotnetumbria@live.it&lt;/a&gt; a cui è agganciato un ChatBot. Il suo scopo è fare da tramite per pubblicare tutto quello che viene scritto nella conversazione su un blog dedicato all&amp;#39;argomento &amp;quot;vita profesionale&amp;quot;. &lt;/p&gt; &lt;p&gt;Il blog, battezzato &amp;quot;My dotnet life&amp;quot;, è raggiungibile all&amp;#39;url &lt;a title="http://dotnetumbria.org/blogs/dotnetlife/default.aspx" href="http://dotnetumbria.org/blogs/dotnetlife/default.aspx"&gt;http://dotnetumbria.org/blogs/dotnetlife/default.aspx&lt;/a&gt; e conterrà tutte le conversazioni che ognuno di voi vorrà fare con l&amp;#39;account &lt;a href="mailto:dotnetumbria@live.it"&gt;dotnetumbria@live.it&lt;/a&gt;. &lt;br /&gt;Più che di conversazioni probabilmente si tratterà di veri e propri monologhi, in quanto lo scopo del chatbot è solo quello di fare da interfaccia per la pubblicazione. &lt;/p&gt; &lt;p&gt;Vediamo come utilizzare il servizio: &lt;/p&gt; &lt;ol&gt; &lt;li&gt;Se non lo avete gia fatto, registratevi come utenti nel nostro sito.  &lt;li&gt;Aggiungete il nuovo contatto (&lt;a href="mailto:dotnetumbria@live.it"&gt;dotnetumbria@live.it&lt;/a&gt;) alla vostra lista contatti. Verrete automaticamente accettati dal chatbot, senza grosse attese.  &lt;li&gt;Aprite una conversazione e scrivere qualcosa (qualsiasi cosa), il chatbot infatti non si accorge della conversazione fino a quando non inviate un messaggio  &lt;li&gt;Se è la prima volta che vi collegate al contatto, vi verranno richiesti il nome utente e la password che avete scelto per utilizzare dotnetumbria. Queste informazioni vi verranno richieste una sola volta, dopodichè verranno associate al vostro contatto MSN e le successive autenticazioni saranno completamente automatiche.  &lt;li&gt;Se i dati inseriti sono corretti, il Bot vi chiederà di inserire il titolo del post. In caso contrario si torna al punto 4.  &lt;li&gt;Successivamente potrete iniziare a scrivere il vostro post. Non avete limiti di dimensioni, ricordate che tutto quello che scrivete verrà pubblicato con il vostro account dotnetumbria e sarà esattamente come scrivere direttamente un nuovo post dentro il blog. Attualmente non sono supportate immagini ed allegati, quindi non mandateli.  &lt;li&gt;Siccome MSN è limitato nella grandezza di un singolo messaggio, i messaggi che scriverete vennanno concatenati l&amp;#39;un l&amp;#39;altro lato server. Quindi non avrete limiti di dimensioni nell&amp;#39;utilizzare questo servizio. Semplicemente scrivete più messaggi. Verranno pubblicati in un&amp;#39;unico post.&amp;nbsp; &lt;li&gt;Al termine avete 2 opzioni , pubblicare il post. buttare via tutto. &lt;br /&gt;Scrivendo &lt;strong&gt;!save &lt;/strong&gt;(punto esclamativo compreso) pubblicherete immediatamente tutto quello che avrete scritto nel blog. &lt;br /&gt;Scrivendo &lt;strong&gt;!delete&lt;/strong&gt; tutto quello che avete scritto verrà dimenticato e la sessione di chat annullata. &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Spero che la cosa vi piaccia. Se si, ho altri servizi in mente basati su questa tecnica. &lt;/p&gt; &lt;p&gt;Ciao a tutti. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnetumbria.org/aggbug.aspx?PostID=485" width="1" height="1"&gt;</content><author><name>Paolo Possanzini</name><uri>http://dotnetumbria.org/members/Paolo-Possanzini/default.aspx</uri></author></entry><entry><title>Primi passi con il .NET Microframework</title><link rel="alternate" type="text/html" href="/blogs/articoli/archive/2008/06/25/primi-passi-con-il-net-microframework.aspx" /><id>/blogs/articoli/archive/2008/06/25/primi-passi-con-il-net-microframework.aspx</id><published>2008-06-25T15:49:31Z</published><updated>2008-06-25T15:49:31Z</updated><content type="html">&lt;p&gt;Come accennavo in un mio precedente commento ad un post di Andrea, qualche tempo fa alcuni miei colleghi ed io ci siamo dilettati con alcuni primordiali esperimenti di “programmazione embedded” (le virgolette sono d’obbligo visto il livello davvero elementare dei nostri esperimenti); all’inizio è duro anche solamente scegliere cosa provare: il campo di applicazioni è vasto ma richiede competenze un po’ ad ampio spettro, comunque che vanno al di là delle sole conoscenze relative alla progettazione/realizzazione del software.&lt;/p&gt;  &lt;p&gt;Abbiamo acquistato un kit di sviluppo &lt;a href="http://devicesolutions.net/Products/Tahoe.aspx"&gt;Tahoe&lt;/a&gt;, ovvero una scheda equipaggiata con CPU &lt;a href="http://devicesolutions.net/Products/Meridian.aspx"&gt;Meridian&lt;/a&gt;, dotata di un display LCD, porta seriale, usb e una ridda di pin con passo un decimo di pollice per accedere facilmente alle porte I/O messe a disposizione dalla CPU stessa.&amp;#160; Ecco la nostra scheda (noterete che è ancora marcata ‘Embedded Fusion’…)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnetumbria.org/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/articoli/Tahoe2_5F00_1.jpg"&gt;&lt;img title="Il Tahoe Development Kit" style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;margin:10px 0px;border-right-width:0px;" height="188" alt="Il Tahoe Development Kit" src="http://dotnetumbria.org/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/articoli/Tahoe2_5F00_thumb_5F00_1.jpg" width="480" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Il passo successivo per noi è stato quello di informarci sui rudimenti dei protocolli di comunicazione I2C e SPI, supportati dal Meridian, e di procurarci i primi integrati da far interagire con la nostra scheda…&lt;/p&gt;  &lt;p&gt;abbiamo pensato ai classici sensori di temperatura e ne abbiamo scelti alcuni che implementano il bus I2C e altri che invece dialogano via SPI e, per farci veramente del male, ce li siamo procurati in versione microscopica (con package SMD tra i più piccoli, al limite della saldabilità a mano!)… per poterli ‘cablare’ in una breadboard di dimensioni umane abbiamo comprato (o in un caso realizzato in casa, con tanto di bromografo e bagni in percloruro ferrico!) piccole Printed Board che ospitano l’integrato e offrono piazzole forate per poter saldare i classici cavetti di collegamento… ed eccovi il risultato nella sua forma migliore!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnetumbria.org/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/articoli/Breadboard_5F00_2.jpg"&gt;&lt;img title="La breadboard" style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;margin:10px 0px;border-right-width:0px;" height="314" alt="La breadboard" src="http://dotnetumbria.org/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/articoli/Breadboard_5F00_thumb.jpg" width="480" border="0" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Cosa stiamo osservando? Alla scheda sono collegati: due sensori di temperatura TMP100 (I2C) e un sensore di temperatura TMP123 (SPI) di Texas Instruments, ma non solo! Abbiamo fatto piccoli esperimenti anche con un RTC DS1678 (I2C) della Maxim e, dulcis in fundo (ma ancora tutto è in stato embrionale), un ADC ADS1000 (I2C) ancora di Texas Instruments.&lt;/p&gt;  &lt;p&gt;Al di là del layout confusionario e dei singoli componenti usati quello che abbiamo messo in opera è una semplice comunicaizone con dispositivi esterni con i due protocolli citati; il risultato? Eccovi un termometro con ben tre sensori (e altre cose di contorno)! La temperatura rilevata dai primi due (identici) è quella delle prime due righe, poi abbiamo il clock; alla quarta riga la temperatura rilevata dal sensore SPI (che ha sensibilità maggiore) e in ultima riga un dato analogico (una tensione in particolare) convertito dall’ADC &lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnetumbria.org/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/articoli/DSCF3328.jpg"&gt;&lt;img title="Il display quando tutto è in funzione" style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="364" alt="Il display quando tutto è in funzione" src="http://dotnetumbria.org/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/articoli/DSCF3328_5F00_thumb.jpg" width="484" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Applicazioni pratiche? Chiaramente un termostato programmabile con rilevazione della temperatura in più punti, eccetera eccetera…&lt;/p&gt;  &lt;p&gt;Ma da un punto di vista prettamente informatico, cosa abbiamo realizzato? Per ogni dispositivo una classe driver che eredita da una opportuna classe fornita dal SDK di Embedded Fusion (una per ogni protocollo che abbiamo usato, intendo), a formare un semplice diagramma di questo tipo:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnetumbria.org/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/articoli/ClassDiagram1_5F00_2.png"&gt;&lt;img title="ClassDiagram1" style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;margin:10px 0px;border-right-width:0px;" height="258" alt="ClassDiagram1" src="http://dotnetumbria.org/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/articoli/ClassDiagram1_5F00_thumb.png" width="484" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;La routine principale del nostro software ‘prototipale’? A intervalli regolari chiediamo al processore di fare un giro di ‘transazioni’ di scrittura/lettura con i dispositivi esterni che abbiamo inizializzato e scriviamo i risultati sul display:&lt;/p&gt;  &lt;div&gt;   &lt;div style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;     &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;float&lt;/span&gt; temp_1 = Hardware.TMP100_1.Temperature;&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;float&lt;/span&gt; temp_2 = Hardware.TMP100_2.Temperature;&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;DateTime timestamp = Hardware.DS1678.TimeStamp;&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;float&lt;/span&gt; temp_spi=Hardware.TMP123.Temperature;&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;float&lt;/span&gt; data = Hardware.ADS1000.Data;&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;Dispatcher.Invoke(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; TimeSpan(1000),&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; TimerCallback(&lt;span style="color:#0000ff;"&gt;delegate&lt;/span&gt;(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; state) {&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;        _txt_1.TextContent = &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Concat(&lt;span style="color:#006080;"&gt;&amp;quot;#1 : &amp;quot;&lt;/span&gt;,&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Concat(temp_1.ToString(), &lt;span style="color:#006080;"&gt;&amp;quot; °C&amp;quot;&lt;/span&gt;));&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;        _txt_2.TextContent = &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Concat(&lt;span style="color:#006080;"&gt;&amp;quot;#2 : &amp;quot;&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Concat(temp_2.ToString(), &lt;span style="color:#006080;"&gt;&amp;quot; °C&amp;quot;&lt;/span&gt;));&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;        _txt_3.TextContent = timestamp.ToString();&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;        _txt_4.TextContent = &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Concat(&lt;span style="color:#006080;"&gt;&amp;quot;SPI : &amp;quot;&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Concat(temp_spi.ToString(), &lt;span style="color:#006080;"&gt;&amp;quot; °C&amp;quot;&lt;/span&gt;));&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;        _txt_5.TextContent = &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Concat(&lt;span style="color:#006080;"&gt;&amp;quot;Data : &amp;quot;&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Concat(data.ToString(), &lt;span style="color:#006080;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;));&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;border-bottom-style:none;"&gt;    }),&lt;/pre&gt;

    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;border-top-style:none;line-height:12pt;padding-top:0px;font-family:consolas, &amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;);&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Che ne dite? Approfondiamo? Avete idee o suggerimenti? A presto, allora!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnetumbria.org/aggbug.aspx?PostID=451" width="1" height="1"&gt;</content><author><name>Gianluca Ruta</name><uri>http://dotnetumbria.org/members/Gianluca-Ruta/default.aspx</uri></author><category term="microframework" scheme="http://dotnetumbria.org/blogs/articoli/archive/tags/microframework/default.aspx" /></entry><entry><title>Progetto NHooligans - Parte 1 - Concetti, entità e interfacce del sistema di simulazione</title><link rel="alternate" type="text/html" href="/blogs/articoli/archive/2008/06/07/progetto-nhooligans-parte-1-concetti-entit-224-e-interfacce-del-sistema-di-simulazione.aspx" /><link rel="enclosure" type="application/x-zip-compressed" length="159049" href="http://dotnetumbria.org/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.00.04.08/OpenSteerDemo_5F00_0_5F00_8_5F00_2_5F00_win32.zip" /><id>/blogs/articoli/archive/2008/06/07/progetto-nhooligans-parte-1-concetti-entit-224-e-interfacce-del-sistema-di-simulazione.aspx</id><published>2008-06-07T12:33:00Z</published><updated>2008-06-07T12:33:00Z</updated><content type="html">&lt;p&gt;In considerazione della straordinaria risposta al mio post nella sezione &amp;quot;futuri appuntamenti&amp;quot; (intendo straordinariamente scarsa), provo ad addentrarmi un po&amp;#39; pi&amp;ugrave; nel concreto del sistema di simulazione che costituir&amp;agrave; l&amp;#39;ambiente all&amp;#39;interno del quale interagiranno i vari agenti (denominati &amp;quot;hooligan&amp;quot;) comandati dai programmi &amp;quot;contendenti&amp;quot;.&lt;/p&gt;
&lt;p&gt;Facendo riferimento alla terminologia utilizzata nel framework &lt;b&gt;NSteer&lt;/b&gt;, intorno al quale verr&amp;agrave; sviluppato il sistema di simulazione, si individuano i seguenti &amp;quot;attori&amp;quot;, ciascuno con le proprie peculiarit&amp;agrave; (o, in altri termini, ciascuno caratterizzato dall&amp;#39;implementazione di una o pi&amp;ugrave; delle interfacce definite dal framework:&lt;/p&gt;
&lt;p&gt;Un oggetto di tipo &amp;quot;agente&amp;quot; (&lt;i&gt;Agent&lt;/i&gt;, in NSteer), descrive un&amp;#39;entit&amp;agrave; che vive all&amp;#39;interno del &amp;quot;mondo&amp;quot; (&lt;i&gt;World&lt;/i&gt;, in NSteer). Un agente ha un &amp;quot;corpo&amp;quot; (&lt;i&gt;Body&lt;/i&gt;, in NSteer), un sistema di &amp;quot;visione&amp;quot; (&lt;i&gt;Vision&lt;/i&gt;, in NSteer) e un &amp;quot;comportamento&amp;quot; (&lt;i&gt;Behavior&lt;/i&gt;, in NSteer).&lt;/p&gt;
&lt;p&gt;Il &amp;quot;corpo&amp;quot; di un agente definisce le propriet&amp;agrave; cinematiche dell&amp;#39;agente (posizione, velocit&amp;agrave; e accelerazione).&lt;/p&gt;
&lt;p&gt;Un sistema di &amp;quot;visione&amp;quot; definisce la regione in cui un agente pu&amp;ograve; &amp;quot;vedere&amp;quot; gli altri agenti o gli ostacoli presenti, tipicamente, nelle sue vicinanze.&lt;/p&gt;
&lt;p&gt;Il &amp;quot;comportamento&amp;quot; di un agente determina, ad ogni passo della simulazione, la forza (in senso vettoriale) cui sar&amp;agrave; sottoposto il suo &amp;quot;corpo&amp;quot;.&lt;/p&gt;
&lt;p&gt;Gli agenti sono confinati all&amp;#39;interno del &amp;quot;mondo&amp;quot;.&lt;/p&gt;
&lt;p&gt;Il &amp;quot;simulatore&amp;quot; (&lt;i&gt;Simulator&lt;/i&gt;, in NSteer) determina, ad ogni passo della simulazione, la situazione cinematica (posizione, velocit&amp;agrave; e accelerazione) di tutti gli agenti presenti nel sistema.&lt;/p&gt;
&lt;p&gt;Il sistema di simulazione implementato in NSteer definisce quattro servizi per gestire gli agenti, il mondo, gli ostacoli e la &amp;quot;prossimit&amp;agrave;&amp;quot; di un agente nei confronti degli altri rispettivamente mediante i servizi &lt;i&gt;AgentService&lt;/i&gt;, &lt;i&gt;WorldService&lt;/i&gt;, &lt;i&gt;ObstacleService &lt;/i&gt;e &lt;i&gt;NeighborhoodService&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;Per quanto concerne la visualizzazione della simulazione NSteer definisce il concetto di &lt;i&gt;Sprite&lt;/i&gt;, un oggetto 2D caratterizzato da attributi quali colori, visibilit&amp;agrave;, forma, ecc. e il concetto di &amp;quot;Scena&amp;quot; (&lt;i&gt;Scene&lt;/i&gt;, in NSteer), che astrae gli aspetti legati al rendering della simulazione.&lt;/p&gt;
&lt;p&gt;Prima che vi sloghiate la mandibola per gli sbadigli, vi incollo un&amp;#39;immagine relativa ad uno step della simulazione realizzata all&amp;#39;interno del demo che accompagna il framework NSteer.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://test.innovactive.it/shared/NSteerDemo.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Nello screenshot &amp;egrave; possibile individuare una decina di agenti (i punti contornati dal cerchietto rosa, che rappresenta lo spazio occupato dall&amp;#39;agente) ciascuno dei quali ha un proprio &amp;quot;orientamento&amp;quot; ed un proprio &amp;quot;cono visivo&amp;quot; (rappresentato dai 3 segmenti terminati da pallini che escono dal centro dell&amp;#39;agente). I comportamenti di ciascun agente sono descritti dall&amp;#39;etichetta che compare accanto a ciascun cerchietto rosa. I comportamenti definiti all&amp;#39;interno del framework NSteer sono gi&amp;agrave; parecchi, ma &amp;egrave; possibile definirne di nuovi o scrivendoli da zero o utilizzando uno dei comportamenti &amp;quot;contenitore&amp;quot; gi&amp;agrave; definiti in NSteer. I 3 cerchi viola rappresentano degli ostacoli circolari. Nell&amp;#39;immagine gli agenti al centro della finestra hanno attivato il comportamento &amp;quot;Seek&amp;quot; (ossia insegui) nei confronti del pallino verde in alto (comandato dal movimento del cursore del mouse nell&amp;#39;applicazione di esempio). Gli altri hanno attivato invece un comportamento composito caratterizzato dalla somma del comportamento &amp;quot;Confine&amp;quot; (ossia confina, argina) e del comportamento &amp;quot;Avoid&amp;quot; (ossia evita), rispettivamente per rimanere all&amp;#39;interno della regione permessa (rappresentata dal riquadro interno) e per evitare l&amp;#39;ostacolo che hanno accanto.&lt;/p&gt;
&lt;p&gt;Anche se nello step di simulazione immortalato da questo screenshot non &amp;egrave; evidente (perch&amp;eacute; in questo screenshot altri comportamenti avevano priorit&amp;agrave;), gli agenti tendono a rimanere uniti ma a non sovrapporsi grazie ad un altro comportamento: il FlockBehavior (dove flock significa &amp;quot;stormo&amp;quot;).Questo comportamento ha una valenza &amp;quot;storica&amp;quot; particolare perch&amp;eacute; &amp;egrave; proprio dalla scomposizione delle regole che guidano il comportamento di uno stormo di uccelli che Reynolds ha tratto lo spunto per il proprio lavoro. Per rendervi conto meglio di quello che Reynolds ha inventato (o forse dovrei dire &amp;quot;scoperto&amp;quot;) vi consiglio di dare un&amp;#39;occhiata ai demo allegati, ed in particolare (premento Tab si passa da un demo al successivo) al demo &amp;quot;Boids&amp;quot;.&lt;/p&gt;
&lt;p&gt;Nel prossimo post inizieremo a dare un&amp;#39;occhiata a qualche snippet di codice, per poi fare chiarezza sui &amp;quot;lotti&amp;quot; di progetto disponibili per l&amp;#39;assegnazione a chi vorr&amp;agrave; partecipare attivamente allo sviluppo di NHooligans.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnetumbria.org/aggbug.aspx?PostID=408" width="1" height="1"&gt;</content><author><name>maiorfi</name><uri>http://dotnetumbria.org/members/maiorfi/default.aspx</uri></author><category term="nhooligans behavior nsteer" scheme="http://dotnetumbria.org/blogs/articoli/archive/tags/nhooligans+behavior+nsteer/default.aspx" /></entry><entry><title>Tutorial WPF &amp; LINQ - Lezione 2 - Accesso al database tramite LINQ </title><link rel="alternate" type="text/html" href="/blogs/articoli/archive/2008/06/06/tutorial-wpf-amp-linq-lezione-2-accesso-al-database-tramite-linq.aspx" /><id>/blogs/articoli/archive/2008/06/06/tutorial-wpf-amp-linq-lezione-2-accesso-al-database-tramite-linq.aspx</id><published>2008-06-06T13:32:00Z</published><updated>2008-06-06T13:32:00Z</updated><content type="html">&lt;div class="ForumPostContentText"&gt;
&lt;p&gt;Eccoci qui con la seconda lezione!&lt;br /&gt;In questa lezione vedremo come creare in automatico delle classi di accesso al database sfruttando le potenzialit&amp;agrave; di LINQ to SQL quindi vedremo come creare una listview che prelevi i dati dalla nostra tabellina e li mostri a video. Tutto questo senza scrivere una sola riga di codice !!&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:medium;color:#000000;background-color:#ffff99;"&gt;4. Creazione di Classi LINQ to SQL&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In Visual Studio, Microsoft mette a disposizione un tipo di file (dbml) che ci consente di creare le classi in modo visuale senza complicarci troppo la vita. Quindi cliccate con il pulsante destro sul progetto nella finestra di esplorazione progetti e seguite il percorso &amp;quot;Add -&amp;gt; New Item ... &amp;quot; e vi apparir&amp;agrave; una finestra come&amp;nbsp;questa:&lt;img width="630" src="http://dotnetumbria.org/cfs-filesystemfile.ashx/__key/CommunityServer.Components.PostAttachments/00.00.00.03.78/Figura2.JPG" alt="Inserimento di LINQ to SQL" height="345" /&gt;&lt;br /&gt;dove selezionate &amp;quot;LINQ to SQL Classes&amp;quot; quindi date un nome al vostro file considerando che tutti i riferimenti poi sfrutteranno questo nome. Io ho messo &amp;quot;&lt;span style="color:#008000;font-family:courier new,courier;"&gt;&lt;strong&gt;MyLinqToSQL.dbml&lt;/strong&gt;&lt;/span&gt;&amp;quot;.&lt;/p&gt;
&lt;p&gt;Questa operazione aggiunge tutte le dipendenze necessarie per lavorare con LINQ to SQL se controllate sulle risorse infatti dovreste avere tra gli Assembly:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:courier new,courier;"&gt;System.Data.LINQ&lt;br /&gt;System.Xml.LINQ&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Ora trascinate la vostra tabella &amp;quot;TIPI&amp;quot;&amp;nbsp;dal &amp;quot;Server Explorer&amp;quot; all&amp;#39;area di lavoro (dovreste infatti avere il file MyLinqToSQL.dbml aperto in modalit&amp;agrave; Design). Se avete fatto tutto bene vi apparir&amp;agrave; la vostra tabella nell&amp;#39;area di lavoro. Questa tabella &amp;egrave; la rappresentazione grafica della classe &amp;quot;Tipi&amp;quot; creata in automatico da VS.&lt;br /&gt;Ora salvate il file e chiudetelo visto che per il momento non ci serve pi&amp;ugrave;. L&amp;#39;area di lavoro torna al design della finestra Window1 del progetto.&lt;/p&gt;
&lt;div class="ForumPostContentText"&gt;
&lt;p&gt;&lt;span style="font-size:medium;background-color:#ffff99;"&gt;5. Creazione della LISTVIEW&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Per inserire controlli in una form WPF il mio consiglio &amp;egrave; di utilizzare Expression Blend. Aprite Expression Blend (senza chiudere il progetto VS) e caricate il progetto &lt;span style="color:#008000;font-family:Courier New;"&gt;&lt;strong&gt;TestWPFLinqToSql. &lt;/strong&gt;&lt;/span&gt;Vi comparir&amp;agrave; la vostra window1. Cercate il controllo ListView nella toolbar a sinistra (probabilmente dovrete aprire l&amp;#39;Asset Library cliccando sul pulsante &amp;quot;&amp;gt;&amp;gt;&amp;quot; quindi cercate ListView e fateci Click, verr&amp;agrave; aggiunto alla toolbar) quindi fate doppio click su di esso e vedrete che vi si posizioner&amp;agrave; in alto a sinistra. impostate i margini a 0,0,0,40 cos&amp;igrave; da lasciare lo spazio per i futuri bottoni.&lt;/p&gt;
&lt;p&gt;A questo punto andate nel pannello delle propriet&amp;agrave; (sempre di expression studio) e se non vi da problemi di refresh potete scorrerlo fino a trovare &amp;quot;&lt;span style="color:#008000;"&gt;miscellaneous&lt;/span&gt;&amp;quot; che &amp;egrave; una sezione compattata. &lt;br /&gt;Cliccate su di essa e, sempre se non avete problemi di refresh, potete scorrerla fino a trovare &amp;quot;&lt;span style="color:#008000;"&gt;View&lt;/span&gt;&amp;quot; che &amp;egrave; anch&amp;#39;essa una sezione compattata, sempre cliccandoci sopra la aprite e scorrete fino a trovare la voce &amp;quot;&lt;span style="color:#008000;"&gt;columns&lt;/span&gt;&amp;quot; che invece &amp;egrave; una collezione per cui avrete un pulsantino con &amp;quot;...&amp;quot; scritto sopra.&lt;br /&gt;Cliccateci e se tutto va bene dovrebbe comparirvi il &amp;quot;Collection Editor&amp;quot; delle colonne.&lt;br /&gt;Create 1 colonna (l&amp;#39;altra gi&amp;agrave; c&amp;#39;&amp;egrave;) poi selezionate la prima e impostate la Propriet&amp;agrave; &amp;quot;&lt;span style="color:#008000;"&gt;Header&lt;/span&gt;&amp;quot; in &amp;quot;Codice&amp;quot;&lt;br /&gt;Selezionate la seconda e impostate la propriet&amp;agrave; &amp;quot;&lt;span style="color:#008000;"&gt;Header&lt;/span&gt;&amp;quot; a &amp;quot;Descrizione&amp;quot;.&lt;br /&gt;Ora chiudete premendo OK.&lt;br /&gt;Visto che probabilmente avrete problemi di refresh anche qui, vi consiglio di chiudere la finestra di design della Window1 e riaprirla dal pannello &amp;quot;Project&amp;quot;.&lt;br /&gt;otterrete una cosa simile a questa:&lt;br /&gt;&lt;img src="http://dotnetumbria.org/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.00.03.79/Figura3.GIF" alt="" /&gt;&lt;/p&gt;
&lt;div style="CLEAR:both;"&gt;
&lt;p class="ForumPostContentText"&gt;&lt;span style="font-size:medium;background-color:#ffff99;"&gt;6. Associare i dati alla ListView&lt;/span&gt;&lt;/p&gt;
&lt;p class="ForumPostContentText"&gt;Ora comincia il bello.&lt;br /&gt;Premete F5 e magicamente il programma si avvier&amp;agrave;, correggete errori se ce ne sono ma credo che non ve ne siano.&lt;br /&gt;Ora chiudete l&amp;#39;applicazione appena eseguita e selezionate il controllo ListView facendo doppioclick su esso&amp;nbsp;dal pannello &amp;quot;&lt;span style="color:#008000;"&gt;Object&amp;nbsp;and TimeLine&lt;/span&gt;&amp;quot; in modo tale che vi si evidenzi in giallo.&lt;br /&gt;A questo punto cliccate con il pulsante destro sul controllo nel form e scegliete la voce &amp;quot;&lt;span style="color:#008000;"&gt;BindItemSourceToData&lt;/span&gt;&amp;quot; dal menu contestuale.&lt;br /&gt;Premete sul pulsante &lt;span style="color:#008000;"&gt;&amp;quot;+ CLR&lt;/span&gt;&amp;quot; che trovate nella finestra che si &amp;egrave; appena aperta e cliccate su &amp;quot;&lt;span style="color:#008000;"&gt;MyLinqToSQLDataContext&lt;/span&gt;&amp;quot; che dovreste avere nella lista (io avevo chiamato il file delle classi linq cos&amp;igrave;:&amp;nbsp;MyLinqToSQL.dmbl per cui il mio datacontext si chiama MyLinqToSQLDataContext)&lt;br /&gt;Premete su &amp;quot;OK&amp;quot; e il datacontext verr&amp;agrave; aggiunto alle connessioni &amp;quot;&lt;span style="color:#008000;"&gt;Data Sources&lt;/span&gt;&amp;quot;, cliccateci sopra e vi apparir&amp;agrave; nella colonna di destra, l&amp;#39;elenco degli oggetti che implementano l&amp;#39;interfaccia IObservableCollection (e qui non sono proprio sicuro, quindi la butto l&amp;agrave; cos&amp;igrave; come mi viene e prendetela con beneficio di inventario) tra cui la classe &amp;quot;&lt;span style="color:#008000;"&gt;Tipis (Array):(Table Tipi)&lt;/span&gt;&amp;quot;&lt;br /&gt;Selezionatela e premete Finish.&lt;br /&gt;Sembra che non sia cambiato niente ma in realt&amp;agrave; abbiamo appena detto che il compilatore XAML deve creare un&amp;#39;istanza di Tipis perch&amp;eacute; la ListView la deve usare come DataSource ed abbiamo detto alla ListView di usare quell&amp;#39;istanza come DataSource per i suoi DataItem.&lt;br /&gt;passate dalla visualizzazione Design a quella XML, il Codice XAML ora &amp;egrave; il seguente:&lt;/p&gt;
&lt;div style="BORDER-RIGHT:#000000 1px solid;BORDER-TOP:#000000 1px solid;BORDER-LEFT:#000000 1px solid;BORDER-BOTTOM:#000000 1px solid;BACKGROUND-COLOR:#fae09d;" class="ForumPostContentText"&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;lt;&lt;font color="#800000"&gt;Window&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#ff0000"&gt;xmlns&lt;/font&gt;=&amp;quot;&lt;/span&gt;&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&gt;&lt;span style="font-family:courier new,courier;"&gt;http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#ff0000"&gt;xmlns:x&lt;/font&gt;=&amp;quot;&lt;/span&gt;&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml"&gt;&lt;span style="font-family:courier new,courier;"&gt;http://schemas.microsoft.com/winfx/2006/xaml&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#ff0000"&gt;x:Class&lt;/font&gt;=&amp;quot;&lt;font color="#0000ff"&gt;Window1&lt;/font&gt;&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#ff0000"&gt;Title&lt;/font&gt;=&amp;quot;&lt;font color="#0000ff"&gt;Window1&lt;/font&gt;&amp;quot; Height=&amp;quot;&lt;font color="#0000ff"&gt;300&lt;/font&gt;&amp;quot; Width=&amp;quot;&lt;font color="#0000ff"&gt;300&lt;/font&gt;&amp;quot; &lt;font color="#ff0000"&gt;xmlns:d&lt;/font&gt;=&amp;quot;&lt;/span&gt;&lt;a href="http://schemas.microsoft.com/expression/blend/2008"&gt;&lt;span style="font-family:courier new,courier;"&gt;http://schemas.microsoft.com/expression/blend/2008&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;quot; &lt;font color="#ff0000"&gt;xmlns:mc&lt;/font&gt;=&amp;quot;&lt;/span&gt;&lt;a href="http://schemas.openxmlformats.org/markup-compatibility/2006"&gt;&lt;span style="font-family:courier new,courier;"&gt;http://schemas.openxmlformats.org/markup-compatibility/2006&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;quot; &lt;font color="#ff0000"&gt;mc:Ignorable&lt;/font&gt;=&amp;quot;&lt;font color="#0000ff"&gt;d&lt;/font&gt;&amp;quot; &lt;font color="#ff0000"&gt;xmlns:TestWPFLinqToSql&lt;/font&gt;=&amp;quot;&lt;font color="#0000ff"&gt;clr-namespace:TestWPFLinqToSql&lt;/font&gt;&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;&lt;font color="#800000"&gt;Window.Resources&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;font color="#800000"&gt;ObjectDataProvider&lt;/font&gt; &lt;font color="#ff0000"&gt;x:Key&lt;/font&gt;=&amp;quot;&lt;font color="#0000ff"&gt;MyLinqToSQLDataContextDS&lt;/font&gt;&amp;quot; &lt;font color="#ff0000"&gt;d:IsDataSource&lt;/font&gt;=&amp;quot;&lt;font color="#0000ff"&gt;True&lt;/font&gt;&amp;quot; &lt;font color="#ff0000"&gt;ObjectType&lt;/font&gt;&lt;font color="#0000ff"&gt;=&amp;quot;{x:Type TestWPFLinqToSql:MyLinqToSQLDataContext}&lt;/font&gt;&amp;quot;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;lt;/&lt;font color="#800000"&gt;Window.Resources&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;font color="#800000"&gt;Grid&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;&lt;font color="#800000"&gt;ListView&lt;/font&gt; &lt;font color="#ff0000"&gt;IsSynchronizedWithCurrentItem&lt;/font&gt;=&amp;quot;&lt;font color="#0000ff"&gt;True&lt;/font&gt;&amp;quot; &lt;font color="#ff0000"&gt;Margin&lt;/font&gt;=&amp;quot;&lt;font color="#0000ff"&gt;0,0,0,40&lt;/font&gt;&amp;quot; &lt;font color="#ff0000"&gt;ItemsSource&lt;/font&gt;=&amp;quot;{&lt;font color="#ff0000"&gt;Binding&lt;/font&gt; &lt;font color="#ff0000"&gt;Path&lt;/font&gt;=&lt;font color="#0000ff"&gt;Tipis&lt;/font&gt;, &lt;font color="#ff0000"&gt;Mode&lt;/font&gt;=&lt;font color="#0000ff"&gt;Default&lt;/font&gt;, &lt;font color="#ff0000"&gt;Source&lt;/font&gt;={&lt;font color="#ff0000"&gt;StaticResource&lt;/font&gt; &lt;font color="#0000ff"&gt;MyLinqToSQLDataContextDS&lt;/font&gt;}}&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;lt;&lt;font color="#800000"&gt;ListView.View&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;font color="#800000"&gt;GridView&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;font color="#800000"&gt;GridViewColumn&lt;/font&gt; &lt;font color="#ff0000"&gt;Header&lt;/font&gt;=&amp;quot;&lt;font color="#0000ff"&gt;Codice&lt;/font&gt;&amp;quot;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;font color="#800000"&gt;GridViewColumn&lt;/font&gt; &lt;font color="#ff0000"&gt;Header&lt;/font&gt;=&amp;quot;&lt;font color="#0000ff"&gt;Descrizione&lt;/font&gt;&amp;quot;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;font color="#800000"&gt;GridView&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;lt;/&lt;font color="#800000"&gt;ListView.View&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;lt;/&lt;font color="#800000"&gt;ListView&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;font color="#800000"&gt;Grid&lt;/font&gt;&amp;gt;&lt;br /&gt;&amp;lt;/&lt;font color="#800000"&gt;Window&lt;/font&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="ForumPostContentText"&gt;&lt;br /&gt;Ora bisogna dire alle colonne quale valore prendere:&lt;br /&gt;Qui il mio consiglio &amp;egrave; di farlo a mano:&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div style="BORDER-RIGHT:#000000 1px solid;BORDER-TOP:#000000 1px solid;BORDER-LEFT:#000000 1px solid;BORDER-BOTTOM:#000000 1px solid;BACKGROUND-COLOR:#fae09d;" class="ForumPostContentText"&gt;&lt;span style="font-family:courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;font color="#800000"&gt;GridViewColumn&lt;/font&gt; &lt;font color="#ff0000"&gt;Header&lt;/font&gt;=&amp;quot;&lt;font color="#0000ff"&gt;Codice&lt;/font&gt;&amp;quot; &lt;font color="#ff0000"&gt;DisplayMemberBinding&lt;/font&gt;=&amp;quot;{&lt;font color="#ff0000"&gt;Binding&lt;/font&gt; &lt;font color="#ff0000"&gt;Path&lt;/font&gt;=&lt;font color="#0000ff"&gt;TipoCodice&lt;/font&gt;}&amp;quot;/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;font color="#800000"&gt;GridViewColumn&lt;/font&gt; &lt;font color="#ff0000"&gt;Header&lt;/font&gt;=&amp;quot;&lt;font color="#0000ff"&gt;Descrizione&lt;/font&gt;&amp;quot; &lt;font color="#ff0000"&gt;DisplayMemberBinding&lt;/font&gt;=&amp;quot;{&lt;font color="#ff0000"&gt;Binding&lt;/font&gt; &lt;font color="#ff0000"&gt;Path&lt;/font&gt;=&lt;font color="#0000ff"&gt;TipoDescrizione&lt;/font&gt;}&amp;quot;/&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="ForumPostContentText"&gt;&lt;br /&gt;Purtroppo Expression Blend non ha intellisense e quello di VS si spegne proprio nel Binding per cui dovete sapere come si chiamano le colonne della tabella, le mie si chiamano TipoCodice e TipoDescrizione.&lt;br /&gt;ora compilate ed eseguite premendo F5. se avete messo dei valori di prova nella tabella dovreste vederli nella listview.&lt;br /&gt;Tutto questo ancora una volta senza scrivere nessuna riga di codice se non per effettuare il Binding alle colonne. spero che questa limitazione venga al piu presto sorpassata (io sto utilizzando VS2008 SP1 e Blend 2.5 March CTP).&lt;br /&gt;&lt;br /&gt;Con questo abbiamo chiuso la Lezione 2, arrivederci alla prossima lezione dove vedremo come permettere la modifica dei valori direttamente da listview.&lt;br /&gt;Vi lascio in allegato lo screenshot di quello che &amp;egrave; venuto fuori.&lt;/div&gt;
&lt;div class="ForumPostContentText"&gt;&lt;/div&gt;
&lt;div style="CLEAR:both;" class="ForumPostContentText"&gt;&lt;img src="http://dotnetumbria.org/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.00.03.80/figura4.GIF" alt="" /&gt;&lt;/div&gt;
&lt;div style="CLEAR:both;" class="ForumPostContentText"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnetumbria.org/aggbug.aspx?PostID=405" width="1" height="1"&gt;</content><author><name>dardino</name><uri>http://dotnetumbria.org/members/dardino/default.aspx</uri></author></entry><entry><title>Tutorial WPF &amp; LINQ - Lezione 1 - Preparazione dell'ambiente di lavoro </title><link rel="alternate" type="text/html" href="/blogs/articoli/archive/2008/06/06/tutorial-wpf-amp-linq-lezione-1-preparazione-dell-ambiente-di-lavoro.aspx" /><id>/blogs/articoli/archive/2008/06/06/tutorial-wpf-amp-linq-lezione-1-preparazione-dell-ambiente-di-lavoro.aspx</id><published>2008-06-06T13:27:00Z</published><updated>2008-06-06T13:27:00Z</updated><content type="html">&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="ForumPostContentText"&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;Come promesso eccomi qua per creare un mini-tutorial sulla creazione di una piccola applicazione WPF che legga e scriva dati in una tabella di un database SQL sfruttando LINQ.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:medium;background-color:#ffff99;"&gt;1. Creazione del database in SQL&amp;nbsp;EXPRESS&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;Per prima cosa occorre creare un database, io utilizzo SQL Management Studio Express per gestire i database.&lt;br /&gt;posto la query per la creazione del database cos&amp;igrave; come me la propone SQL Management Studio Express:&lt;/span&gt;&lt;/p&gt;
&lt;div style="background-color:#ffe2c5;border:#000000 1px solid;"&gt;&lt;span style="font-family:courier new,courier;"&gt;USE [master]&lt;br /&gt;GO&lt;br /&gt;/****** Oggetto:&amp;nbsp; Database [MySampleDB]&amp;nbsp;&amp;nbsp;&amp;nbsp; Data script: 05/22/2008 13:36:33 ******/&lt;br /&gt;CREATE DATABASE [MySampleDB] ON&amp;nbsp; PRIMARY &lt;br /&gt;( NAME = N&amp;#39;MySampleDB&amp;#39;, FILENAME = N&amp;#39;c:\Programmi\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\MySampleDB.mdf&amp;#39; , SIZE = 2240KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )&lt;br /&gt;&amp;nbsp;LOG ON &lt;br /&gt;( NAME = N&amp;#39;MySampleDB_log&amp;#39;, FILENAME = N&amp;#39;c:\Programmi\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\MySampleDB_log.LDF&amp;#39; , SIZE = 560KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)&lt;br /&gt;GO&lt;br /&gt;EXEC dbo.sp_dbcmptlevel @dbname=N&amp;#39;MySampleDB&amp;#39;, @new_cmptlevel=90&lt;br /&gt;GO&lt;br /&gt;IF (1 = FULLTEXTSERVICEPROPERTY(&amp;#39;IsFullTextInstalled&amp;#39;))&lt;br /&gt;begin&lt;br /&gt;EXEC [MySampleDB].[dbo].[sp_fulltext_database] @action = &amp;#39;enable&amp;#39;&lt;br /&gt;end&lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET ANSI_NULL_DEFAULT OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET ANSI_NULLS OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET ANSI_PADDING OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET ANSI_WARNINGS OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET ARITHABORT OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET AUTO_CLOSE ON &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET AUTO_CREATE_STATISTICS ON &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET AUTO_SHRINK OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET AUTO_UPDATE_STATISTICS ON &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET CURSOR_CLOSE_ON_COMMIT OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET CURSOR_DEFAULT&amp;nbsp; GLOBAL &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET CONCAT_NULL_YIELDS_NULL OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET NUMERIC_ROUNDABORT OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET QUOTED_IDENTIFIER OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET RECURSIVE_TRIGGERS OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET&amp;nbsp; ENABLE_BROKER &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET AUTO_UPDATE_STATISTICS_ASYNC OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET DATE_CORRELATION_OPTIMIZATION OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET TRUSTWORTHY OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET ALLOW_SNAPSHOT_ISOLATION OFF &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET PARAMETERIZATION SIMPLE &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET&amp;nbsp; READ_WRITE &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET RECOVERY SIMPLE &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET&amp;nbsp; MULTI_USER &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET PAGE_VERIFY CHECKSUM&amp;nbsp; &lt;br /&gt;GO&lt;br /&gt;ALTER DATABASE [MySampleDB] SET DB_CHAINING OFF&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;una volta creato il database &amp;egrave; necessario creare la tabella:&lt;br /&gt;anche qui posto il codice cos&amp;igrave; come me lo propone SQLMSE:&lt;/p&gt;
&lt;div style="background-color:#ffe2c5;border:#000000 1px solid;"&gt;&lt;span style="font-family:courier new,courier;"&gt;USE [MySampleDB]&lt;br /&gt;GO&lt;br /&gt;/****** Oggetto:&amp;nbsp; Table [dbo].[Tipi]&amp;nbsp;&amp;nbsp;&amp;nbsp; Data script: 05/22/2008 13:40:07 ******/&lt;br /&gt;SET ANSI_NULLS ON&lt;br /&gt;GO&lt;br /&gt;SET QUOTED_IDENTIFIER ON&lt;br /&gt;GO&lt;br /&gt;CREATE TABLE [dbo].[Tipi](&lt;br /&gt;&amp;nbsp;[TipoCodice] [bigint] NOT NULL,&lt;br /&gt;&amp;nbsp;[TipoDescrizione] [nvarchar](100) NULL,&lt;br /&gt;&amp;nbsp;CONSTRAINT [PK_Tipi] PRIMARY KEY CLUSTERED &lt;br /&gt;(&lt;br /&gt;&amp;nbsp;[TipoCodice] ASC&lt;br /&gt;)WITH (PAD_INDEX&amp;nbsp; = OFF, STATISTICS_NORECOMPUTE&amp;nbsp; = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS&amp;nbsp; = ON, ALLOW_PAGE_LOCKS&amp;nbsp; = ON) ON [PRIMARY]&lt;br /&gt;) ON [PRIMARY]&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;La nostra tabella sar&amp;agrave; quindi una tabellina di 2 soli campi: &lt;strong&gt;&lt;span style="color:#008000;font-family:courier new,courier;"&gt;TipoCodice&lt;/span&gt;&lt;/strong&gt; e &lt;strong&gt;&lt;span style="color:#008000;font-family:courier new,courier;"&gt;TipoDescrizione&lt;/span&gt;&lt;/strong&gt;. la tabella si chiama &lt;strong&gt;&lt;span style="color:#008000;font-family:courier new,courier;"&gt;Tipi&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:medium;background-color:#ffff99;"&gt;2. Creazione del un progetto con VISUAL STUDIO 2008&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Apriamo ora Visual Studio 2008 e creiamo un nuovo progetto di tipo &amp;quot;&lt;strong&gt;&lt;span style="color:#008000;font-family:courier new,courier;"&gt;WPF Application&lt;/span&gt;&lt;/strong&gt;&amp;quot; e lo chiamiamo&amp;nbsp;&amp;quot;&lt;strong&gt;&lt;span style="color:#008000;font-family:courier new,courier;"&gt;TestWPFLinqToSql&lt;/span&gt;&lt;/strong&gt;&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:medium;background-color:#ffff99;"&gt;3. Creazione di una connessione dati in Visual Studio 2008&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Dalla finestra &amp;quot;Server Explorer&amp;quot; premete il pulsante &amp;quot;Connect To Database&amp;quot; (quello con il cilindretto giallo ed il + verde) vi comparir&amp;agrave; la finestra &amp;quot;Add Connection&amp;quot; dove andrete a selezionare il server (es. NOMEPC/SQLEXPRESS) dove avete creato il database e quindi impostate, se necessario, le credenziali e selezionate il database &lt;span style="color:#008000;font-family:Courier New;"&gt;&lt;strong&gt;MySampleDB&lt;/strong&gt;&lt;/span&gt; quindi date ok e vi comparir&amp;agrave; nella finestra &amp;quot;Server Explorer&amp;quot; il vostro collegamento al database.&lt;/p&gt;
&lt;p&gt;Ora abbiamo preparato tutto il necessario per poter lavorare. Salvate tutto il progetto e proseguite con la Lezione 2&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnetumbria.org/aggbug.aspx?PostID=404" width="1" height="1"&gt;</content><author><name>dardino</name><uri>http://dotnetumbria.org/members/dardino/default.aspx</uri></author></entry><entry><title>Come scrivere un articolo</title><link rel="alternate" type="text/html" href="/blogs/articoli/archive/2008/06/06/come-scrivere-un-articolo.aspx" /><id>/blogs/articoli/archive/2008/06/06/come-scrivere-un-articolo.aspx</id><published>2008-06-05T22:07:02Z</published><updated>2008-06-05T22:07:02Z</updated><content type="html">&lt;p&gt;Ecco a voi alcune nozioni tecniche, per chi volesse cimentarsi nella scrittura di un articolo per il nostro portale.&lt;/p&gt; &lt;p&gt;La seziona articoli è un blog e il suo url è &lt;a href="http://dotnetumbria.org/blogs/articoli"&gt;http://dotnetumbria.org/blogs/articoli&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Una volta aperta la pagina del blog, e dopo avere fatto login, in alto a destra trovate il link &amp;quot;Control Panel&amp;quot;. &lt;/p&gt; &lt;p&gt;All&amp;#39;interno del Link è presente il comando &amp;quot;Write a Blog Post&amp;quot;, che apre l&amp;#39;editor che vi permette la scrittura direttamente dal WEB del vostro nuovo articolo; ovviamente potete inserire allegati all&amp;#39;articolo e Tag di&amp;nbsp; ricerca. &lt;/p&gt; &lt;p&gt;Se scrivete molti articoli nello stesso giorno potete decidere di pubblicarli un po&amp;#39; alla volta cambiando la data di pubblicazione nel Tab &amp;quot;Publication Settings&amp;quot;. &lt;/p&gt; &lt;p&gt;Essendo il nostro un portale tecnico, abbiamo inserito un piccolo plugin che ci permette di formattare il codice in modo agevole. &lt;/p&gt; &lt;p&gt;Tutto il codice che volete formattare va inserito all&amp;#39;interno dei tag [code language=&amp;quot;&amp;quot;] [/code], dove language è il linguaggio di programmazione che state utilizzando. Il plugin si occuperà di colorare le keywords e i riferimenti sintattici in modo coerente con il linguaggio scelto. I linguaggi supportati sono i più disparati e vanno dall&amp;#39;XML semplice al VB.Net passando per C# ed altri. Unico consiglio, se state scrivendo XAML utilizzate XML come linguaggio, e in linea generale utilizzate il tag XML per tutto quello che può essere riferito a tale standard. &lt;/p&gt; &lt;p&gt;Se preferite utlizzare uno strumento Offline, un&amp;#39;ottima scelta secondo me è Windows Live Writer. &lt;/p&gt; &lt;p&gt;L&amp;#39;url per la configurazione del blog è sempre la stessa e il login è il vostro account. &lt;/p&gt; &lt;p&gt;Buon lavoro a tutti. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnetumbria.org/aggbug.aspx?PostID=400" width="1" height="1"&gt;</content><author><name>Paolo Possanzini</name><uri>http://dotnetumbria.org/members/Paolo-Possanzini/default.aspx</uri></author></entry><entry><title>Wpf - Animazioni (2D e 3D) con DoubleAnimation</title><link rel="alternate" type="text/html" href="/blogs/articoli/archive/2008/05/05/wpf-animazioni-2d-e-3d-con-doubleanimation.aspx" /><id>/blogs/articoli/archive/2008/05/05/wpf-animazioni-2d-e-3d-con-doubleanimation.aspx</id><published>2008-05-05T14:11:00Z</published><updated>2008-05-05T14:11:00Z</updated><content type="html">&lt;p&gt;Sviluppando un progetto, mi sono trovato a dover implementare una animazione. Semplicemente, il mio oggetto 3D alla pressione di una determinata combinazione di tasti deve allontanarsi dal punto di vista dell&amp;#39;utente e quindi scorrere negativamente sull&amp;#39;asse z, ricordiamoci la regola della mano destra:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnetumbria.org/blogs/articoli/WindowsLiveWriter/WpfAnimazioni2De3DconDoubleAnimation_E299/righthand_2.jpg"&gt;&lt;img src="http://dotnetumbria.org/blogs/articoli/WindowsLiveWriter/WpfAnimazioni2De3DconDoubleAnimation_E299/righthand_thumb.jpg" style="border:0px none;" alt="righthand" border="0" height="244" width="178" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Per far questo ho creato un oggetto DoubleAnimation che non è altro che un semplice interpolatore. Basta definire pochi valori per avere un&amp;#39;animazione semplice ma funzionale.&lt;/p&gt;  &lt;p&gt;[code language=&amp;quot;xml&amp;quot;]&lt;/p&gt;  &lt;p&gt;DoubleAnimation animazione= new DoubleAnimation();&lt;/p&gt;  &lt;p&gt;...&lt;/p&gt;  &lt;p&gt;animazione.To = -100; //valore di fine interpolazione   &lt;br /&gt;animazione.Duration = new Duration(TimeSpan.Parse(&amp;quot;0:0:0.5&amp;quot;)); //durata dell&amp;#39;animazione    &lt;br /&gt;Oggetto3D.BeginAnimation(TranslateTransform3D.OffsetZProperty, animazione); //applico l&amp;#39;interpolatore alla proprietà dell&amp;#39;oggetto 3D&lt;/p&gt;  &lt;p&gt;[/code]&lt;/p&gt;  &lt;p&gt;Come vedete, non ho impostato il valore di inizio interpolazione perché, come per l&amp;#39;&lt;a href="http://dotnetumbria.org/blogs/articoli/archive/2008/04/18/timeline-ed-interpolazione-con-wpf.aspx"&gt;altro mio post&lt;/a&gt;, anche qui l&amp;#39;interpolatore prende in automatico, come punto di partenza, il valore attuale (in questo caso la posizione attuale sull&amp;#39;asse Z).&lt;/p&gt;  &lt;p&gt;Fin qui tutto ok. Quando però successivamente, in un altra parte del programma, ho tentato di cambiare ulteriormente la distanza del mio oggetto, questa volta senza animazione &lt;/p&gt;  &lt;p&gt;[code language=&amp;quot;xml&amp;quot;]&lt;/p&gt;  &lt;p&gt;Oggetto3D.OffsetZ = -50;&lt;/p&gt;  &lt;p&gt;[/code]&lt;/p&gt;  &lt;p&gt;questo mi è risultato impossibile. Mettendo un breakpoint sull&amp;#39;assegnazione, vedevo chiaramente che l&amp;#39;operazione avveniva ma che, apparentemente almeno, era totalmente ignorata e che quindi la traslazione sull&amp;#39;asse Z del mio oggetto restava -100.&lt;/p&gt;  &lt;p&gt;Dopo un discreto tempo passato su &lt;a href="http://msdn.microsoft.com/it-it/default.aspx"&gt;msdn&lt;/a&gt; ho trovato motivo e soluzione al mio problema.&lt;/p&gt;  &lt;p&gt;L&amp;#39;interpolatore, anche se arrivato a fine &amp;quot;ciclo&amp;quot; rimane comunque attivo, continuando a impostare a -100 il valore della mia traslazione.&lt;/p&gt;  &lt;p&gt;Per ovviare al problema, basta &amp;quot;scollegare&amp;quot; l&amp;#39;oggetto DoubleAnimation dalla proprietà OffsetZProperty&lt;/p&gt;  &lt;p&gt;[code language=&amp;quot;xml&amp;quot;]&lt;/p&gt;  &lt;p&gt;Oggetto3D.BeginAnimation(TranslateTransform3D.OffsetZProperty, null);   &lt;br /&gt;Oggetto3D.OffsetZ = -50;&lt;/p&gt;  &lt;p&gt;[/code]&lt;/p&gt;  &lt;p&gt;impostando come &amp;quot;null&amp;quot; l&amp;#39;interpolatore addetto alla modifica della property.&lt;/p&gt;  &lt;p&gt;Spero di essere stato d&amp;#39;aiuto.&lt;/p&gt;  &lt;p&gt;Un saluto a tutta la community.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnetumbria.org/aggbug.aspx?PostID=349" width="1" height="1"&gt;</content><author><name>Daniele Balbini</name><uri>http://dotnetumbria.org/members/Daniele-Balbini/default.aspx</uri></author><category term="WPF" scheme="http://dotnetumbria.org/blogs/articoli/archive/tags/WPF/default.aspx" /></entry><entry><title>Timeline ed interpolazione con WPF</title><link rel="alternate" type="text/html" href="/blogs/articoli/archive/2008/04/18/timeline-ed-interpolazione-con-wpf.aspx" /><id>/blogs/articoli/archive/2008/04/18/timeline-ed-interpolazione-con-wpf.aspx</id><published>2008-04-18T16:37:00Z</published><updated>2008-04-18T16:37:00Z</updated><content type="html">&lt;p&gt;Come la maggior parte di coloro che per la prima volta si avvicinano a WPF mi sono trovato a gestire le animazioni attraverso le Timeline.&lt;/p&gt;
&lt;p&gt;Un animazione gradevole e didatticamente interessante consiste nel far ingrandire un oggetto qualsiasi (button, image, o qualsiasi altro) al passaggio del mouse.&lt;/p&gt;
&lt;p&gt;Ottenere quest’effetto è molto semplice, basta andare a modificare i valori dei due moltiplicatori X e Y (scale orizzontale e scale verticale). Di default entrambi i valori sono impostati a 1, che è come dire 100%&lt;/p&gt;
&lt;p&gt;Cosa significa questo: che se il nostro button (ad esempio) è alto 10 pixel, con il valore di scale Y a 1, diventa 10 x 1 = 10 pixel quindi dimensione originale. Modificando il moltiplicatore e impostandolo a 2 (200%), è banalmente ovvio che il nostro button diventerà alto 20.&lt;/p&gt;
&lt;p&gt;Torniamo a noi. Volendo creare un animazione, che al passaggio del mouse ingrandisca il nostro oggetto raddoppiandone le dimensioni, ci basta agganciarne l’evento OnMouseEnter e, impostando nella timeline un arco di tempo a piacere (diciamo mezzo secondo) e successivamente cambiare i valori, da 1 a 2, dei campi X e Y nel campo scale del LayoutTransform .&lt;/p&gt;
&lt;p&gt;Volendo fare l’operazione opposta, e cioè agganciando all’oggetto l’evento OnMouseLeave per far si che all’uscita del mouse, il nostro oggetto torni alle dimensioni originali, ho incontrato un problema. Ho ovviamente creato una nuova timeline, impostato lo scale a 2 del LayoutTransform per indicare, ovviamente, i valori di inizio interpolazione, e poi, a mezzo secondo di distanza nella timeline, ho impostato di nuovo i valori dello scale a 1.&lt;/p&gt;
&lt;p&gt;[code language=&amp;quot;xml&amp;quot;]&lt;/p&gt;
&lt;p&gt;&amp;lt;DoubleAnimationUsingKeyFrames BeginTime=&amp;quot;00:00:00&amp;quot; Storyboard.TargetName=&amp;quot;prova&amp;quot; Storyboard.TargetProperty=&amp;quot;(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)&amp;quot;&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;SplineDoubleKeyFrame KeyTime=&amp;quot;00:00:00&amp;quot; Value=&amp;quot;2&amp;quot;/&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;SplineDoubleKeyFrame KeyTime=&amp;quot;00:00:00.5000000&amp;quot; Value=&amp;quot;1&amp;quot;/&amp;gt; &lt;br /&gt;&amp;lt;/DoubleAnimationUsingKeyFrames&amp;gt; &lt;br /&gt;&amp;lt;DoubleAnimationUsingKeyFrames BeginTime=&amp;quot;00:00:00&amp;quot; Storyboard.TargetName=&amp;quot;prova&amp;quot; Storyboard.TargetProperty=&amp;quot;(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)&amp;quot;&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;SplineDoubleKeyFrame KeyTime=&amp;quot;00:00:00&amp;quot; Value=&amp;quot;2&amp;quot;/&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;SplineDoubleKeyFrame KeyTime=&amp;quot;00:00:00.5000000&amp;quot; Value=&amp;quot;1&amp;quot;/&amp;gt; &lt;br /&gt;&amp;lt;/DoubleAnimationUsingKeyFrames&amp;gt;&lt;/p&gt;
&lt;p&gt;[/code]&lt;/p&gt;
&lt;p&gt;Mandando in esecuzione l’applicazione, dopo pochissime prove, ho notato un insolito e alquanto poco gradito comportamento: facendo uscire il mouse dal mio oggetto prima del termine dell’animazione (in pratica scatenando l’evento OnMouseLeave quando il mio oggetto non era ancora completamente ingrandito), questo “scattava” alla dimensione raddoppiata per poi proseguire correttamente con la seconda animazione e quindi tornando fluidamente alle dimensioni originali.&lt;/p&gt;
&lt;p&gt;Facendo un paio di prove ho scoperto che la cosa è di una semplicità disarmante ma, soprattutto per chi come me ha avuto già a che fare in precedenza con animazioni, timeline e interpolatori vari, non molto ovvia.&lt;/p&gt;
&lt;p&gt;L’errore da me commesso è stato di settare lo scale a 2 per indicare i valori di inizio interpolazione per l’animazione di “restringimento”. Non impostandoli, ma impostando solo i valori di fine interpolazione, WPF fa partire l’interpolazione dai valori attuali dello scale, qualsiasi essi siano.&lt;/p&gt;
&lt;p&gt;[code language=&amp;quot;xml&amp;quot;]&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;lt;DoubleAnimationUsingKeyFrames BeginTime=&amp;quot;00:00:00&amp;quot; Storyboard.TargetName=&amp;quot;prova&amp;quot; Storyboard.TargetProperty=&amp;quot;(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)&amp;quot;&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;SplineDoubleKeyFrame KeyTime=&amp;quot;00:00:00.5000000&amp;quot; Value=&amp;quot;1&amp;quot;/&amp;gt; &lt;br /&gt;&amp;lt;/DoubleAnimationUsingKeyFrames&amp;gt; &lt;br /&gt;&amp;lt;DoubleAnimationUsingKeyFrames BeginTime=&amp;quot;00:00:00&amp;quot; Storyboard.TargetName=&amp;quot;prova&amp;quot; Storyboard.TargetProperty=&amp;quot;(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)&amp;quot;&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;SplineDoubleKeyFrame KeyTime=&amp;quot;00:00:00.5000000&amp;quot; Value=&amp;quot;1&amp;quot;/&amp;gt; &lt;br /&gt;&amp;lt;/DoubleAnimationUsingKeyFrames&amp;gt;&lt;/p&gt;
&lt;p&gt;[/code]&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Lanciando la nostra applicazione, possiamo vedere che, l’effetto voluto è gradevole e fluido.&lt;/p&gt;
&lt;p&gt;Sperando di avervi risparmiato quei 5 minuti di prove, saluto tutti.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnetumbria.org/aggbug.aspx?PostID=332" width="1" height="1"&gt;</content><author><name>Daniele Balbini</name><uri>http://dotnetumbria.org/members/Daniele-Balbini/default.aspx</uri></author><category term="WPF" scheme="http://dotnetumbria.org/blogs/articoli/archive/tags/WPF/default.aspx" /></entry><entry><title>Inserisci il tuo articolo !!</title><link rel="alternate" type="text/html" href="/blogs/articoli/archive/2008/04/11/inserisci-il-tuo-articolo.aspx" /><id>/blogs/articoli/archive/2008/04/11/inserisci-il-tuo-articolo.aspx</id><published>2008-04-11T21:29:43Z</published><updated>2008-04-11T21:29:43Z</updated><content type="html">&lt;p&gt;Ogni utente registrato può inserire liberamente i propri articoli nella sezione &amp;quot;Articoli&amp;quot;.&lt;br /&gt;Potete scrivere l&amp;#39;articolo direttamente dal sito oppure utilizzare Windows Live Writer indicando il seguente url come url del blog:&lt;/p&gt; &lt;p&gt;&lt;a title="http://dotnetumbria.org/blogs/articoli/" href="http://dotnetumbria.org/blogs/articoli/"&gt;http://dotnetumbria.org/blogs/articoli/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Aspettiamo numerosi vostri contenuti. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnetumbria.org/aggbug.aspx?PostID=318" width="1" height="1"&gt;</content><author><name>Paolo Possanzini</name><uri>http://dotnetumbria.org/members/Paolo-Possanzini/default.aspx</uri></author></entry><entry><title>WPF Invalidate Binding</title><link rel="alternate" type="text/html" href="/blogs/articoli/archive/2008/04/10/wpf-invalidate-binding.aspx" /><id>/blogs/articoli/archive/2008/04/10/wpf-invalidate-binding.aspx</id><published>2008-04-10T14:18:49Z</published><updated>2008-04-10T14:18:49Z</updated><content type="html">&lt;p&gt;Il binding di WPF è molto reattivo grazie a tutta la struttura di DependencyObjects e DependencyProperties a cui si appoggia. Per questo motivo lavorando con WPF molto spesso non ci dobbiamo preoccupare di fare un refresh dell&amp;#39;interfaccia utente per visualizzare i dati aggiornati. &lt;/p&gt; &lt;p&gt;Può capitare tuttavia di dover mettere in binding alcune sorgenti dati che non utilizzano DependencyProperties e che nella loro struttura non implementano l&amp;#39;interfaccia &lt;b&gt;INotifyPropertyChanged&lt;/b&gt; . In questi rari casi accade che l&amp;#39;interfaccia utente non è aggiornata con i dati perchè non è in grado di capire che i dati sono stati modificati in qualche modo. Dobbiamo essere quindi noi a forzare il refresh. &lt;/p&gt; &lt;p&gt;Vediamo quali strumetni abbiamo a disposizione. Viene sicuramente in nostro aiuto la classe statica &lt;strong&gt;BindingOperations&lt;/strong&gt;, la quale ci permette di interrogare la struttura ad oggetti dell&amp;#39;interfaccia utente e capire se le proprietà degli oggetti stessi sono in binding oppure no. &lt;/p&gt; &lt;p&gt;&lt;a href="http://dotnetumbria.org/blogs/articoli/WindowsLiveWriter/WPFInvalidateBinding_E563/image_4.png"&gt;&lt;img height="328" alt="image" src="http://dotnetumbria.org/blogs/articoli/WindowsLiveWriter/WPFInvalidateBinding_E563/image_thumb_1.png" width="259" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;BindingOperations ci restituisce oggetti di tipo &lt;strong&gt;BindingExpression&lt;/strong&gt; che sono di fatto il collegamento tra il target e la sorgente dati. &lt;/p&gt; &lt;p&gt;&lt;a href="http://dotnetumbria.org/blogs/articoli/WindowsLiveWriter/WPFInvalidateBinding_E563/image_6.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="241" alt="image" src="http://dotnetumbria.org/blogs/articoli/WindowsLiveWriter/WPFInvalidateBinding_E563/image_thumb_2.png" width="211" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Possiamo utilizzare il metodo UpdateTarget per forzare la lettura dei dati ed un refresh dell&amp;#39;interfaccia utente. &lt;/p&gt; &lt;p&gt;&lt;br /&gt;&lt;em&gt;&lt;u&gt;Come facciamo tuttavia da codice a utilizzare questo metodo senza vincolare la grafica a delle strutture fisse di binding ?&lt;/u&gt; &lt;/em&gt;&lt;br /&gt;Mi spiego meglio: Se utilizziamo questo metodo, dobbiamo conoscere esattamente quali sono i campi bindati per poter sollevare il binding e quindi vincoliamo lo sviluppo della parte grafica impedendo la modifica di template e di datatemplate. &lt;/p&gt; &lt;p&gt;Ci viene in aiuto un&amp;#39;altra classe molto importante: &lt;strong&gt;VisualTreeHelper.&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://dotnetumbria.org/blogs/articoli/WindowsLiveWriter/WPFInvalidateBinding_E563/image_8.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="420" alt="image" src="http://dotnetumbria.org/blogs/articoli/WindowsLiveWriter/WPFInvalidateBinding_E563/image_thumb_3.png" width="307" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Questa classe ci permette di navigare all&amp;#39;interno della VisualTree, ovvero all&amp;#39;interno degli oggetti renderizzati nell&amp;#39;interfaccia utente. Con un po&amp;#39; di reflection , e con l&amp;#39;aiuto di BidingOperations possiamo estrarre dalla VisualTree tutte le BindingExpressions ed invocare il metodo UpdateTarget. &lt;/p&gt; &lt;p&gt;Ecco il codice :&lt;/p&gt; &lt;p&gt;[code language=&amp;quot;c#&amp;quot;]&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;private static void InvalidateBinding(DependencyObject objectbase)&lt;br /&gt;{&lt;/p&gt; &lt;p&gt;&amp;nbsp; // Per ogni oggetto all&amp;#39;interno del ramo di visualtree&lt;br /&gt;&amp;nbsp; for (int x = 0; x &amp;lt; VisualTreeHelper.GetChildrenCount(objectbase); x++)&lt;br /&gt;&amp;nbsp; {&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Leggo l&amp;#39;oggetto nodo &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DependencyObject obj = VisualTreeHelper.GetChild(ww, x) as DependencyObject;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Se è un DependencyObject&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (obj != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Cerco tutti i fields di&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (FieldInfo finfo in obj.GetType().GetFields())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Se il field trovato è una DependencyProperty allora può essere sottoposta a binding&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (finfo.FieldType.Equals(typeof(DependencyProperty)))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Verifico se è sottoposta a binding&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DependencyProperty dpvalue = (DependencyProperty)finfo.GetValue(obj);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (BindingOperations.IsDataBound(obj, dpvalue))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Estraggo la BindingExpression&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BindingExpression expr = BindingOperations.GetBindingExpression(obj, dpvalue);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Sollevo il metodo di aggiornamento del binding.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; expr.UpdateTarget();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Se il contenuto della DependencyProperty è un DependencyObject allora devo controllare anche tutte DP dell&amp;#39;oggetto contenuto nella DP corrente&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DependencyObject subdpobject = obj.GetValue(dpvalue) as DependencyObject;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (subdpobject != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!(subdpobject is Visual))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (FieldInfo subfinfo in subdpobject.GetType().GetFields())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DependencyProperty subdpvalue = (DependencyProperty)subfinfo.GetValue(subdpobject);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (BindingOperations.IsDataBound(subdpobject, subdpvalue))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BindingExpression subexpr = BindingOperations.GetBindingExpression(subdpobject, subdpvalue);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; subexpr.UpdateTarget();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Rendo la funzione ricorsiva in modo da esplorare tutta la VisualTree&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InvalidateBinding(obj);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;[/code]&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnetumbria.org/aggbug.aspx?PostID=315" width="1" height="1"&gt;</content><author><name>Paolo Possanzini</name><uri>http://dotnetumbria.org/members/Paolo-Possanzini/default.aspx</uri></author></entry><entry><title>ObjectDataProvider e databinding su WPF</title><link rel="alternate" type="text/html" href="/blogs/articoli/archive/2008/02/20/objectdataprovider-e-databinding-su-wpf.aspx" /><link rel="enclosure" type="application/x-zip-compressed" length="47136" href="http://dotnetumbria.org/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.00.02.46/ODPDemo.zip" /><id>/blogs/articoli/archive/2008/02/20/objectdataprovider-e-databinding-su-wpf.aspx</id><published>2008-02-20T21:54:00Z</published><updated>2008-02-20T21:54:00Z</updated><content type="html">&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:&amp;#39;Times New Roman&amp;#39;,&amp;#39;serif&amp;#39;;"&gt;&lt;font face="arial,helvetica,sans-serif"&gt;Tramite WPF è possibile istanziare in diversi modi un oggetto da utilizzare come sorgente dati per il databinding.&lt;br /&gt;Nel precedente post &lt;a class="" href="http://dotnetumbria.org/blogs/possanzini/archive/2007/11/24/ancora-databinding-su-wpf.aspx"&gt;&amp;quot;Ancora databinding su WPF&amp;quot;&lt;/a&gt; si è visto come (attraverso le risorse della classe Window - Window.Resources) è possibile&amp;nbsp; dichiarare un oggetto come risorsa statica, e, grazie al tag x:key, qualsiasi controllo è in grado di referenziarlo come sorgente dati, permettendo all&amp;#39;engine di WPF di istanziare l&amp;#39;oggetto richiamando il suo costruttore base.&lt;/font&gt; 
&lt;p&gt;&lt;font face="arial,helvetica,sans-serif"&gt;In alcuni scenari, nei quali non si vuole perdere l&amp;#39;approccio dichiarativo messo a disposizione da XAML, ma che richiedono comportamenti particolari, come il richiamo di costruttori specializzati o metodi con parametri dell&amp;#39;oggetto, WPF fornice la classe ObjectDataProvider.Questa Classe non fa altro che incapsulare la risorsa statica e fornire gli strumenti per interoperare con essa.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="arial,helvetica,sans-serif"&gt;Riprendiamo la configurazione precedente della risorsa statica mySource che referenziava la classe mySource scritta in c#&lt;/font&gt;&lt;/p&gt;&lt;pre style="OVERFLOW:scroll;FONT-FAMILY:courier new,courier;"&gt;&lt;p&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#993300"&gt;Window.Resources&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;
&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#993300"&gt;local:mySource &lt;/font&gt;&lt;font color="#ff0000"&gt;x&lt;font color="#0000ff"&gt;:&lt;/font&gt;Key&lt;/font&gt;&lt;font color="#0000ff"&gt;=&amp;quot;mySource&amp;quot;&lt;/font&gt;&lt;font color="#0000ff"&gt;/&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;
&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#0000ff"&gt;/&lt;/font&gt;&lt;font color="#993300"&gt;Window.Resources&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;&lt;font face="arial,helvetica,sans-serif"&gt;Per incapsulare la risorsa basta aggiungere&lt;/font&gt; &lt;/p&gt;&lt;pre style="OVERFLOW:scroll;FONT-FAMILY:Courier New;"&gt;&lt;p&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#993300"&gt;Window.Resources&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#993300"&gt;local:mySource&lt;/font&gt; &lt;font color="#ff0000"&gt;x&lt;font color="#0000ff"&gt;:&lt;/font&gt;Key&lt;/font&gt;&lt;font color="#0000ff"&gt;=&amp;quot;mySource&amp;quot;/&amp;gt;&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#993300"&gt;ObjectDataProvider&lt;/font&gt; &lt;font color="#ff0000"&gt;x&lt;font color="#0000ff"&gt;:&lt;/font&gt;Key&lt;/font&gt;&lt;font color="#0000ff"&gt;=&amp;quot;dataProvider&amp;quot;&lt;/font&gt; &amp;nbsp;&lt;font color="#ff0000"&gt;ObjectType&lt;/font&gt;&lt;font color="#0000ff"&gt;=&amp;quot;{&lt;/font&gt;&lt;font color="#993300"&gt;x&lt;font color="#0000ff"&gt;:&lt;/font&gt;Type&lt;/font&gt; &lt;font color="#ff0000"&gt;local&lt;font color="#0000ff"&gt;:&lt;/font&gt;mySource&lt;/font&gt;&lt;font color="#0000ff"&gt;}&amp;quot;/&amp;gt;&lt;/font&gt;
&lt;/p&gt;&lt;p&gt;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#993300"&gt;Window.Resources&lt;/font&gt;&amp;gt;&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;&lt;font face="arial,helvetica,sans-serif"&gt;Dal codice precedente si vede subito che anche l&amp;#39;ObjectDataProvaider è stato definito come risorsa statica, e che può essere referenziato grazie alla sua chiave &lt;font color="#993300"&gt;dataProvider&lt;/font&gt;, definita attraverso il tag x:Key.&lt;br /&gt;A questo punto &amp;nbsp;si può effettuare il binding attraverso l&amp;#39;ObjectDataProvider, che si occuperà di istanziare la risorsa mySource che sta incapsulando.&lt;br /&gt;L&amp;#39;esempio del precedente post diventa così&lt;/font&gt;&lt;/p&gt;&lt;pre style="OVERFLOW:scroll;FONT-FAMILY:Courier New;"&gt;&lt;p&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#993300"&gt;ListView&lt;/font&gt; &lt;font color="#ff0000"&gt;ItemsSource&lt;/font&gt;&lt;font color="#0000ff"&gt;=&amp;quot;{&lt;/font&gt;&lt;font color="#993300"&gt;Binding&lt;/font&gt; &lt;font color="#ff0000"&gt;Source&lt;/font&gt;&lt;font color="#0000ff"&gt;={&lt;/font&gt;&lt;font color="#993300"&gt;StaticResource&lt;/font&gt; &lt;font color="#ff0000"&gt;dataProvider&lt;/font&gt;&lt;font color="#0000ff"&gt;}}&amp;quot;&amp;gt;&lt;/font&gt;&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;&lt;font face="arial,helvetica,sans-serif"&gt;Da notare che l&amp;#39;applicazione continua a funzionare come in precedenza.&lt;br /&gt;Fino ad ora non abbiamo visto nulla di interessante, infatti per vedere le potenzialità di questo oggetto dobbiamo fare qualche modifica alla nostra classe sorgente dati, aggiungendo un secondo costruttore che accetta un parametro di tipo int e un metodo che accetta anche&amp;#39;esso un parametro di tipo int.&lt;/font&gt;&lt;/p&gt;&lt;pre style="OVERFLOW:scroll;FONT-FAMILY:Courier New;"&gt;&lt;p&gt;&lt;font color="#0000ff"&gt;public class&lt;/font&gt; mySource : ObservableCollection&amp;lt;mySourceItem&amp;gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public&lt;/font&gt; mySource()&lt;br /&gt;&amp;nbsp;&amp;nbsp;  {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#339966"&gt;//Nuovo costruttore che accetta un parametro int, rappresentante il numero di item da construire&lt;br /&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public&lt;/font&gt; mySource(&lt;font color="#0000ff"&gt;int&lt;/font&gt; param)&lt;br /&gt;&amp;nbsp;&amp;nbsp;  {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;for&lt;/font&gt; (&lt;font color="#0000ff"&gt;int&lt;/font&gt; i = 0; i &amp;lt;= param; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;this&lt;/font&gt;.Add(&lt;font color="#0000ff"&gt;new&lt;/font&gt; &lt;font color="#008080"&gt;mySourceItem&lt;/font&gt;(&lt;font color="#993300"&gt;&amp;quot;Customer&amp;quot;&lt;/font&gt;+i.ToString(), &lt;font color="#993300"&gt;&amp;quot;Customer&amp;quot;&lt;/font&gt;+i.ToString()+&lt;font color="#993300"&gt;&amp;quot; Description&amp;quot;&lt;/font&gt;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;  &amp;nbsp; &lt;font color="#339966"&gt;//Metodo che inizializza una nuova classe mySource con un numero di item definito dal paramtro param&lt;br /&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;public&lt;/font&gt; &lt;font color="#008080"&gt;mySource&lt;/font&gt; GetItems(&lt;font color="#0000ff"&gt;int&lt;/font&gt; param)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#008080"&gt;mySource&lt;/font&gt; _mySourse = &lt;font color="#0000ff"&gt;new&lt;/font&gt; &lt;font color="#008080"&gt;mySource&lt;/font&gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;for&lt;/font&gt; (&lt;font color="#0000ff"&gt;int&lt;/font&gt; i = 0; i &amp;lt;= param; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_mySourse.Add(&lt;font color="#0000ff"&gt;new&lt;/font&gt; &lt;font color="#008080"&gt;mySourceItem&lt;/font&gt;&lt;font color="#993300"&gt;(&amp;quot;Customer&amp;quot;&lt;/font&gt; + i.ToString(),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;                 &lt;font color="#993300"&gt;&amp;quot;Customer&amp;quot;&lt;/font&gt; + i.ToString() + &lt;font color="#993300"&gt;&amp;quot; Description&amp;quot;&lt;/font&gt;));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;return&lt;/font&gt; _mySourse;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;&lt;font face="arial,helvetica,sans-serif"&gt;Benché non ha molto senso creare un metodo che realizzi una nuova istanza della stessa classe, è stato aggiunto solo per facilitare questo esempio&lt;/font&gt;.&lt;/p&gt;
&lt;p&gt;&lt;font face="arial,helvetica,sans-serif"&gt;Utilizzando la proprietà CostructorParameters dell&amp;#39; ObjectDataProvider &amp;nbsp;che accetta una collezione di oggetti, possiamo stabilire quale costruttore prendere attraverso la firma dei suo parametri.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="arial,helvetica,sans-serif"&gt;L&amp;#39;esempio diventa:&lt;/font&gt; &lt;/p&gt;&lt;pre style="OVERFLOW:scroll;FONT-FAMILY:Courier New;"&gt;&lt;p&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#993300"&gt;Window.Resources&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;br /&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#993300"&gt;ObjectDataProvider&lt;/font&gt; &lt;font color="#ff0000"&gt;x&lt;font color="#0000ff"&gt;:&lt;/font&gt;Key&lt;/font&gt;&lt;font color="#0000ff"&gt;=&amp;quot;dataProvider&amp;quot;&lt;/font&gt; &lt;font color="#ff0000"&gt;ObjectType&lt;/font&gt;&lt;font color="#0000ff"&gt;=&amp;quot;{&lt;/font&gt;&lt;font color="#993300"&gt;x&lt;font color="#0000ff"&gt;:&lt;/font&gt;Type&lt;/font&gt; &lt;font color="#ff0000"&gt;local&lt;font color="#0000ff"&gt;:&lt;/font&gt;mySource&lt;/font&gt;&lt;font color="#0000ff"&gt;}&amp;quot;&amp;gt;&lt;br /&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#993300"&gt;ObjectDataProvider.ConstructorParameters&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#993300"&gt;sys&lt;font color="#0000ff"&gt;:&lt;/font&gt;Int32&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#993300"&gt;4&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#993300"&gt;sys&lt;font color="#0000ff"&gt;:&lt;/font&gt;Int32&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;br /&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#993300"&gt;ObjectDataProvider.ConstructorParameters&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;br /&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#993300"&gt;ObjectDataProvider&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#993300"&gt;Window.Resources&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;&lt;font face="arial,helvetica,sans-serif"&gt;Ogni parametro è referenziato con il suo tipo, in questo caso Int32, perciò sul nodo root di Window bisogna aggiungere il namespace dei tipi base del Framework; nota che la chiave sys è puramente arbitraria e può essere cambiata a proprio piacimento.&lt;/font&gt; &lt;/p&gt;&lt;pre style="OVERFLOW:scroll;FONT-FAMILY:Courier New;"&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;xmlns&lt;/font&gt;&lt;font color="#0000ff"&gt;:&lt;/font&gt;&lt;font color="#ff0000"&gt;sys&lt;/font&gt;&lt;font color="#0000ff"&gt;=&amp;quot;clr-namespace:System;assembly=mscorlib&amp;quot;&lt;/font&gt;&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;&lt;font face="arial,helvetica,sans-serif"&gt;Se mandiamo in esecuzione il programma si noterà che il nostro ListView è costituito da quattro Item, proprio perché ha utilizzato il costruttore custom, seguendo la sequenza dei parametri, passandogli il numero 4.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="arial,helvetica,sans-serif"&gt;Analogamente l&amp;#39;ObjectDataProvider ci fornisce la possibilità di chiamare un metodo della classe che incapsula al suo interno , utilizzando la proprietà MethodName e passandogli &amp;nbsp;i propri parametri grazie alla proprietà MethodParameters&amp;nbsp; che accetta una collezione di oggetti.&lt;br /&gt;L&amp;#39;esempio precedente diventa&lt;/font&gt;&lt;/p&gt;&lt;pre style="OVERFLOW:scroll;FONT-FAMILY:Courier New;"&gt;&lt;p&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#993300"&gt;Window.Resources&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;br /&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#993300"&gt;ObjectDataProvider&lt;/font&gt; &lt;font color="#ff0000"&gt;x&lt;font color="#0000ff"&gt;:&lt;/font&gt;Key&lt;/font&gt;&lt;font color="#0000ff"&gt;=&amp;quot;dataProvider&amp;quot;&lt;/font&gt; &lt;font color="#ff0000"&gt;ObjectType&lt;/font&gt;&lt;font color="#0000ff"&gt;=&amp;quot;{&lt;/font&gt;&lt;font color="#993300"&gt;x&lt;font color="#0000ff"&gt;:&lt;/font&gt;Type&lt;/font&gt; &lt;font color="#ff0000"&gt;local&lt;font color="#0000ff"&gt;:&lt;/font&gt;mySource&lt;/font&gt;&lt;font color="#0000ff"&gt;}&amp;quot;&lt;/font&gt; &lt;font color="#ff0000"&gt;MethodName&lt;/font&gt;&lt;font color="#0000ff"&gt;=&amp;quot;GetItems&amp;quot;&amp;gt;&lt;br /&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#993300"&gt;ObjectDataProvider.MethodParameters&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;br /&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#993300"&gt;sys&lt;font color="#0000ff"&gt;:&lt;/font&gt;Int32&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#993300"&gt;4&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#993300"&gt;sys&lt;font color="#0000ff"&gt;:&lt;/font&gt;Int32&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;br /&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#993300"&gt;ObjectDataProvider.MethodParameters&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;br /&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#993300"&gt;ObjectDataProvider&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;font color="#993300"&gt;Window.Resources&lt;/font&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;&lt;font face="arial,helvetica,sans-serif"&gt;Potete scaricare la soluzione d&amp;#39;esempio realizzata con Visual Studio 2008&lt;/font&gt; :&lt;br /&gt;&lt;a href="http://dotnetumbria.org/blogs/articoli/WPF/Databinding/ODPDemo.zip"&gt;&lt;font face="arial,helvetica,sans-serif" color="#339966"&gt;ODPDemo.zip&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/span&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://dotnetumbria.org/aggbug.aspx?PostID=246" width="1" height="1"&gt;</content><author><name>matteo</name><uri>http://dotnetumbria.org/members/matteo/default.aspx</uri></author><category term="WPF" scheme="http://dotnetumbria.org/blogs/articoli/archive/tags/WPF/default.aspx" /><category term="Databinding" scheme="http://dotnetumbria.org/blogs/articoli/archive/tags/Databinding/default.aspx" /></entry><entry><title>Un metodo per generare le chiavi di licenze delle nostre applicazioni.</title><link rel="alternate" type="text/html" href="/blogs/articoli/archive/2007/12/28/un-metodo-per-generare-le-chiavi-di-licenze-delle-nostre-applicazioni.aspx" /><id>/blogs/articoli/archive/2007/12/28/un-metodo-per-generare-le-chiavi-di-licenze-delle-nostre-applicazioni.aspx</id><published>2007-12-28T14:38:11Z</published><updated>2007-12-28T14:38:11Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;&lt;em&gt;Premessina&lt;/em&gt;&lt;/strong&gt; &lt;br /&gt;&lt;br /&gt;Come programmatori dotnet, ci troviamo a volte ad affrontare il problema di proteggere le nostre applicazioni da occhi indiscreti che potrebbero curiosare troppo nel nostro codice. &lt;br /&gt;Il problema che mi sono trovato ad affrontare più volte è quello di proteggere il codice che gestisce la licenza che concedo per le mie applicazioni. Una soluzione potrebbe essere quella di offuscare il codice, oppure potrei appoggiarmi a codice unmanaged, tuttavia sono soluzioni che non mi hanno mai attirato più di tanto e che di fatto non garantiscono un elevato grado di protezione a sguardi esperti. &lt;/p&gt; &lt;p&gt;La soluzione che mi è venuta in mente è ben diversa dalle soluzioni che &amp;quot;nascondono&amp;quot; il codice per fare sicurezza, al contrario la mia soluzione prevede assoluta trasparenza. Ed è anche il motivo per cui scrivo questo post. Spero che possiate aiutarmi a trovare le falle e rendere ancora più sicuro il tutto. &lt;/p&gt; &lt;p&gt;&lt;br /&gt;&lt;strong&gt;&lt;em&gt;Come fare (la teoria)&lt;/em&gt;&lt;/strong&gt; &lt;br /&gt;&lt;br /&gt;Visto che nascondere il codice o criptare licenza e altro è una strada che ho scartato, la cosa più naturare è scrivere il codice di licenza, con tutte le informazioni che sono ad esso legate (come ad esempio:data di attivazione, data di scadenza, numero di utenti, licenziatario, productkey e altro), all interno di un file xml nel path di installazione. (Evitiamo allo smanettone di turno la fatica di doversi cercare il file di licenza) &lt;br /&gt;Lo scriviamo anche il chiaro in modo da poterlo consultare tranquillamente senza dover ricorrere a tools particolari. &lt;br /&gt;Inseriamo all interno del file stesso un tag che identifica in modo univoco la macchina per la quale la licenza è stata rilasciata (vedremo in seguito come ottenere queste informazioni)&lt;/p&gt; &lt;p&gt;Nella nostra applicazione quindi quello che dobbiamo fare è leggere il file di licenza, fare le verifiche del caso per accertarci che il productkey sia valido e che le informazioni all interno della licenza siano corrette, verificare il codice che lega la licenza alla macchina ed eseguire la nostra applicazione. &lt;/p&gt; &lt;p&gt;&lt;em&gt;Rimane un problema: evitare che qualcuno modifichi a piacimento il file di licenza.&lt;/em&gt; &lt;/p&gt; &lt;p&gt;La soluzione viene quasi da sola. E sufficiente firmare il file XML con una chiave RSA. Chiunque modificherà il file di licenza, corromperà la firma e il file risulterà non più valido. &lt;br /&gt;Abbiamo sempre a disposizione una chiave RSA che viene gia distribuita all interno dei nostri assembly: la stessa chiave che utilizzamo per firmare i nostri assembly. &lt;br /&gt;Viene generata da VisualStudio, e ne viene distribuita solo la parte pubblica insieme alla nostra applicazione, la parte privata rimane di nostra esclusiva proprietà.&lt;/p&gt; &lt;p&gt;Quindi riassumendo quello che dobbiamo fare è:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Creare un file di licenza in fomato XML  &lt;li&gt;Generare un file snk (che contiene sia chiave pubblica che privata)  &lt;li&gt;Firmare i nostri assembly con il file snk  &lt;li&gt;Firmare il file di licenza con il file snk  &lt;li&gt;Distribuire applicazione e file di licenza  &lt;li&gt;Prima di eseguire l applicazione verificare che la firma del file di licenza sia ancora valida. &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;em&gt;Come fare (la pratica)&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Per prima cosa ci serve una struttura per scrivere il file di licenza, quindi creiamo una classe serializzabile per contenere tutte quest informazioni. &lt;/p&gt; &lt;p&gt;[code language=&amp;quot;c#&amp;quot;]&lt;/p&gt; &lt;p&gt;[Serializable] &lt;br /&gt;&amp;nbsp; internal class BaseLicense &lt;br /&gt;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private string _name; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private object _value; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public object Value &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return _value; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set { _value = value; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public virtual string ObjectName &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return _name; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set { _name = value; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp; } &lt;/p&gt; &lt;p&gt;&amp;nbsp; [Serializable] &lt;br /&gt;&amp;nbsp; internal class PCInfo : BaseLicense &lt;br /&gt;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private string _signature; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string PCSignature &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return _signature; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set { _signature = value; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp; } &lt;/p&gt; &lt;p&gt;&amp;nbsp; [Serializable] &lt;br /&gt;&amp;nbsp; internal class LicenseArchive &lt;br /&gt;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Dictionary&amp;lt;string, BaseLicense&amp;gt; _licenses = new Dictionary&amp;lt;string, BaseLicense&amp;gt;(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private byte[] _signature = new byte[0]; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public byte[] Signature &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return _signature; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set { _signature = value; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Dictionary&amp;lt;string, BaseLicense&amp;gt; Licenses &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return _licenses; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set { _licenses = value; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp; }&lt;/p&gt; &lt;p&gt;[/code]&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;La classe LicenseArchive è il nostro file di licenza, contiene un dictionary e una proprietà pubblica &amp;quot;Signature&amp;quot; che conterrà la firma del file xml stesso. Il dictionary esposto con la proprietà Licenses conterrà tutte le informazioni della licenza. &lt;br /&gt;La classe LicenseBase è un contenitore che contiene una coppia di informazioni &amp;quot;Chiave-Valore&amp;quot; della licenza. La classe PCInfo arricchisce queste informazioni con una stringa che contiene l identificativo del PC per il quale è stata rilasciata la licenza. &lt;br /&gt;Vediamo come leggere le informazioni per identificare in modo univoco il PC. &lt;/p&gt; &lt;p&gt;Possiamo utilizzare WMI (Windows Management Instrumentation) per ottenere le informazioni che ci servono. &lt;br /&gt;&lt;/p&gt; &lt;p&gt;[code language=&amp;quot;c#&amp;quot;] &lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;internal static class MachineInfo &lt;br /&gt;{ &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;summary&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// return Volume Serial Number from hard drive &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;param name=&amp;quot;strDriveLetter&amp;quot;&amp;gt;[optional] Drive letter&amp;lt;/param&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;returns&amp;gt;[string] VolumeSerialNumber&amp;lt;/returns&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static string GetVolumeSerial(string strDriveLetter) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (strDriveLetter == &amp;quot;&amp;quot; || strDriveLetter == null) strDriveLetter = &amp;quot;C&amp;quot;; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ManagementObject disk = &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new ManagementObject(&amp;quot;win32_logicaldisk.deviceid=\&amp;quot;&amp;quot; + strDriveLetter + &amp;quot;:\&amp;quot;&amp;quot;); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; disk.Get(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return disk[&amp;quot;VolumeSerialNumber&amp;quot;].ToString(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;summary&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// Returns MAC Address from first Network Card in Computer &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;returns&amp;gt;[string] MAC Address&amp;lt;/returns&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static string GetMACAddress() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ManagementClass mc = new ManagementClass(&amp;quot;Win32_NetworkAdapterConfiguration&amp;quot;); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ManagementObjectCollection moc = mc.GetInstances(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string MACAddress = String.Empty; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (ManagementObject mo in moc) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (MACAddress == String.Empty)&amp;nbsp; // only return MAC Address from first card &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((bool)mo[&amp;quot;IPEnabled&amp;quot;] == true) MACAddress = mo[&amp;quot;MacAddress&amp;quot;].ToString(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mo.Dispose(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MACAddress = MACAddress.Replace(&amp;quot;:&amp;quot;, &amp;quot;&amp;quot;); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return MACAddress; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;summary&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// Return processorId from first CPU in machine &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;/summary&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; /// &amp;lt;returns&amp;gt;[string] ProcessorId&amp;lt;/returns&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static string GetCPUId() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string cpuInfo = String.Empty; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string temp = String.Empty; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ManagementClass mc = new ManagementClass(&amp;quot;Win32_Processor&amp;quot;); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ManagementObjectCollection moc = mc.GetInstances(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (ManagementObject mo in moc) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (cpuInfo == String.Empty) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {// only return cpuInfo from first CPU &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cpuInfo = mo.Properties[&amp;quot;ProcessorId&amp;quot;].Value.ToString(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return cpuInfo; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;[/code]&lt;/p&gt; &lt;p&gt;Ci siamo, abbiamo tutto il necessario per generare il nostro file di licenza. &lt;/p&gt; &lt;p&gt;Vediamo cosa ci serve per firmarlo. &lt;br /&gt;Ho trovato questa classettina che ci permette di ottenere le chiavi RSA da un file snk e dalla parte dell snk che si trova all interno dell assembly. &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;[code language=&amp;quot;C#&amp;quot;]&lt;/p&gt; &lt;p&gt;/// &lt;br /&gt;/// One static method to get an RSACryptoServiceProvider from a *.snk file.&lt;br /&gt;/// NOTE: These methods assume 1024 bit keys, the same as exported from sn.exe.&lt;br /&gt;/// See also: CryptExportKey() Win32 API.&lt;br /&gt;/// &lt;br /&gt;public sealed class SnkUtil&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; private const int magic_priv_idx = 0x08;&lt;br /&gt;&amp;nbsp; private const int magic_pub_idx = 0x14;&lt;br /&gt;&amp;nbsp; private const int magic_size = 4;  &lt;p&gt;&amp;nbsp; private SnkUtil()&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp; }  &lt;p&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; /// Returns RSA object from *.snk key file.&lt;br /&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; /// Path to snk file.&lt;br /&gt;&amp;nbsp; /// RSACryptoServiceProvider&lt;br /&gt;&amp;nbsp; public static RSACryptoServiceProvider GetRSAFromSnkFile(string path)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (path == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new ArgumentNullException(&amp;quot;path&amp;quot;);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] snkBytes = GetFileBytes(path);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (snkBytes == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new Exception(&amp;quot;Invalid SNK file.&amp;quot;);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; RSACryptoServiceProvider rsa = GetRSAFromSnkBytes(snkBytes);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return rsa;&lt;br /&gt;&amp;nbsp; }  &lt;p&gt;&amp;nbsp; private static byte[] GetFileBytes(string path)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (BinaryReader br = new BinaryReader(fs))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] bytes = br.ReadBytes((int)fs.Length);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return bytes;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; }  &lt;p&gt;&amp;nbsp; public static RSACryptoServiceProvider GetRSAFromSnkBytes(byte[] snkBytes)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (snkBytes == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new ArgumentNullException(&amp;quot;snkBytes&amp;quot;);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; RSAParameters param = FigureParams(snkBytes);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Must set KeyNumber to AT_SIGNATURE for strong&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // name keypair to be correctly imported. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CspParameters cp = new CspParameters();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cp.KeyNumber = 2; // AT_SIGNATURE  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024, cp);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rsa.ImportParameters(param);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return rsa;&lt;br /&gt;&amp;nbsp; }  &lt;p&gt;&amp;nbsp; private static byte[] BlockCopy(byte[] source, int idx, int size)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((source == null) || (source.Length &amp;lt; (idx + size)))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] ret = new byte[size];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Buffer.BlockCopy(source, idx, ret, 0, size);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ret;&lt;br /&gt;&amp;nbsp; }  &lt;p&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; /// Returns true if buffer length is public key size.&lt;br /&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; private static bool SnkBufIsPubLength(byte[] keypair)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (keypair == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (keypair.Length == 160);&lt;br /&gt;&amp;nbsp; }  &lt;p&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; /// Check that RSA1 is in header (public key only).&lt;br /&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; private static bool CheckRSA1(byte[] pubkey)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Check that RSA1 is in header.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // R S A 1 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] check = new byte[] { 0x52, 0x53, 0x41, 0x31 };&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return CheckMagic(pubkey, check, magic_pub_idx);&lt;br /&gt;&amp;nbsp; }  &lt;p&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; /// Check that RSA2 is in header (public and private key).&lt;br /&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; private static bool CheckRSA2(byte[] pubkey)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Check that RSA2 is in header.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // R S A 2 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] check = new byte[] { 0x52, 0x53, 0x41, 0x32 };&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return CheckMagic(pubkey, check, magic_priv_idx);&lt;br /&gt;&amp;nbsp; }  &lt;p&gt;&amp;nbsp; private static bool CheckMagic(byte[] keypair, byte[] check, int idx)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] magic = BlockCopy(keypair, idx, magic_size);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (magic == null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = 0; i &amp;lt; magic_size; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (check&lt;img src="http://dotnetumbria.org/emoticons/emotion-55.gif" alt="Idea" /&gt; != magic&lt;img src="http://dotnetumbria.org/emoticons/emotion-55.gif" alt="Idea" /&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;&amp;nbsp; }  &lt;p&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; /// Returns RSAParameters from byte[].&lt;br /&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; /// &lt;br /&gt;&amp;nbsp; private static RSAParameters FigureParams(byte[] keypair)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; RSAParameters ret = new RSAParameters();  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((keypair == null) || (keypair.Length &amp;lt; 1))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ret;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool pubonly = SnkBufIsPubLength(keypair);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((pubonly) &amp;amp;&amp;amp; (!CheckRSA1(keypair)))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ret;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((!pubonly) &amp;amp;&amp;amp; (!CheckRSA2(keypair)))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ret;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int magic_idx = pubonly ? magic_pub_idx : magic_priv_idx;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Bitlen is stored here, but note this &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // class is only set up for 1024 bit length keys &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int bitlen_idx = magic_idx + magic_size;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int bitlen_size = 4; // DWORD  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Exponent &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // In read file, will usually be { 1, 0, 1, 0 } or 65537&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int exp_idx = bitlen_idx + bitlen_size;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int exp_size = 4;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //BYTE modulus[rsapubkey.bitlen/8]; == MOD; Size 128 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int mod_idx = exp_idx + exp_size;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int mod_size = 128;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //BYTE prime1[rsapubkey.bitlen/16]; == P; Size 64 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int p_idx = mod_idx + mod_size;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int p_size = 64;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //BYTE prime2[rsapubkey.bitlen/16]; == Q; Size 64 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int q_idx = p_idx + p_size;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int q_size = 64;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //BYTE exponent1[rsapubkey.bitlen/16]; == DP; Size 64&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int dp_idx = q_idx + q_size;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int dp_size = 64;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //BYTE exponent2[rsapubkey.bitlen/16]; == DQ; Size 64 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int dq_idx = dp_idx + dp_size;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int dq_size = 64;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //BYTE coefficient[rsapubkey.bitlen/16]; == InverseQ; Size 64&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int invq_idx = dq_idx + dq_size;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int invq_size = 64;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //BYTE privateExponent[rsapubkey.bitlen/8]; == D; Size 128 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int d_idx = invq_idx + invq_size;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int d_size = 128;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Figure public params &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Must reverse order (little vs. big endian issue)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret.Exponent = BlockCopy(keypair, exp_idx, exp_size);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Array.Reverse(ret.Exponent);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret.Modulus = BlockCopy(keypair, mod_idx, mod_size);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Array.Reverse(ret.Modulus);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (pubonly) return ret;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Figure private params &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Must reverse order (little vs. big endian issue)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret.P = BlockCopy(keypair, p_idx, p_size);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Array.Reverse(ret.P);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret.Q = BlockCopy(keypair, q_idx, q_size);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Array.Reverse(ret.Q);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret.DP = BlockCopy(keypair, dp_idx, dp_size);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Array.Reverse(ret.DP);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret.DQ = BlockCopy(keypair, dq_idx, dq_size);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Array.Reverse(ret.DQ);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret.InverseQ = BlockCopy(keypair, invq_idx, invq_size);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Array.Reverse(ret.InverseQ);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret.D = BlockCopy(keypair, d_idx, d_size);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Array.Reverse(ret.D);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ret;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;} &lt;p&gt;[/code]&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Quando avremo ottenuto le chiavi RSA dovremo semplicemente passarle ad un Crypto service provider per fare la firma. &lt;br /&gt;Daremo in pasto al metodo SignData di RSACryptoServiceProvider i dati xml da firmare. &lt;br /&gt;In questo caso utilizzeremo il file snk che abbiamo generato per firmare il nostro assembly. &lt;/p&gt; &lt;p&gt;[code language=&amp;quot;C#&amp;quot;]&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp; RSACryptoServiceProvider rsa = SnkUtil.GetRSAFromSnkFile(snkfilepath);&lt;br /&gt;&amp;nbsp;&amp;nbsp; byte[] signature;&lt;br /&gt;&amp;nbsp;&amp;nbsp; signature = rsa.SignData(datatoSign, new SHA1CryptoServiceProvider()); &lt;p&gt;[/code]&lt;/p&gt; &lt;p&gt;Per verificare la firma abbiamo solo bisogno della chiave pubblica e non dell intero snk. possiamo ottenere la chiave pubblica direttamente dall assembly. &lt;/p&gt; &lt;p&gt;[code language=&amp;quot;C#&amp;quot;]&lt;/p&gt; &lt;p&gt;byte[] publickey = Assembly.GetExecutingAssembly().GetName().GetPublicKey();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (publickey == null || publickey.Length == 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new LicenseException(null, null, &amp;quot;This assembly cannot be licensed because is not strongly named&amp;quot;);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RSACryptoServiceProvider rsa = SnkUtil.GetRSAFromSnkBytes(publickey);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return rsa.VerifyData(datatoverify, new SHA1CryptoServiceProvider(), signature); &lt;p&gt;[/code]&lt;br /&gt;&lt;br /&gt;Questo è tutto. Vi riporto per intero anche le classi che ho scritto per serializzare&amp;nbsp; e firmare la licenza ( da utilizzare nel nostro license manager), e la classe LicenseReader che inseriremo all interno del nostro client. &lt;br /&gt;&lt;/p&gt; &lt;p&gt;[code language=&amp;quot;c#&amp;quot;]&lt;br /&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;internal class LicenseReader&lt;br /&gt; {&lt;br /&gt;&amp;nbsp;&amp;nbsp; private LicenseArchive _licenses = new LicenseArchive();  &lt;p&gt;&amp;nbsp;&amp;nbsp; protected LicenseArchive LicensesArchive&lt;br /&gt;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return _licenses; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp; public LicenseReader()&lt;br /&gt;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.LoadLicenses();&lt;br /&gt;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp; private bool VerifyObjectSign(byte[] datatoverify, byte[] signature)&lt;br /&gt;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] publickey = Assembly.GetExecutingAssembly().GetName().GetPublicKey();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (publickey == null || publickey.Length == 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new LicenseException(null, null, &amp;quot;This assembly cannot be licensed because is not strongly named&amp;quot;);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RSACryptoServiceProvider rsa = SnkUtil.GetRSAFromSnkBytes(publickey);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return rsa.VerifyData(datatoverify, new SHA1CryptoServiceProvider(), signature);&lt;br /&gt;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp; protected void LoadLicenses()&lt;br /&gt;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BinaryFormatter bf = new BinaryFormatter();  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Get license file path&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string licensepath = Application.StartupPath + @&amp;quot;\&amp;quot; + &amp;quot;TeamDev.Licenses.lic&amp;quot;;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Search for License File&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!File.Exists(licensepath)) return;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FileStream fs = File.OpenRead(licensepath);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Deserialize the license file &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _licenses = (LicenseArchive)bf.Deserialize(fs);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fs.Close();  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // serialize in a bytestream the Licenses for validation purposes&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MemoryStream ms = new MemoryStream();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bf.Serialize(ms, _licenses.Licenses);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] buffer = new byte[ms.Length];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ms.Position = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ms.Read(buffer, 0, (int)ms.Length);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Check the PC Signature &amp;amp; LicenseFile Signature.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string pcinfo = string.Empty;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try { pcinfo += MachineInfo.GetCPUId(); }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch { }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try { pcinfo += MachineInfo.GetVolumeSerial(&amp;quot;C&amp;quot;); }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch { }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Il PCInfo non può essere vuoto. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (pcinfo == string.Empty)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new Exception(&amp;quot;Invalid License File&amp;quot;);  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((((PCInfo)_licenses.Licenses[&amp;quot;PCINFO&amp;quot;]).PCSignature != pcinfo) ||&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (!VerifyObjectSign(buffer, _licenses.Signature)))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _licenses.Licenses.Clear();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _licenses.Signature = new byte[0];  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new Exception(&amp;quot;Invalid License File&amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (Exception ex)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new Exception(&amp;quot;Invalid License File&amp;quot;, ex);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt; } &lt;p&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;internal class LicenseProvider : LicenseReader&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private string _snkFilePath = string.Empty;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public LicenseArchive Archive&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return base.LicensesArchive; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string SnkFilePath&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get { return _snkFilePath; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set { _snkFilePath = value; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Override Default Constructor because i don&amp;#39;t like to load license&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // at startup. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public LicenseProvider()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.ClearLicenses();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void ClearLicenses()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.LicensesArchive.Licenses.Clear();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.LicensesArchive.Signature = new byte[0];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void SaveLicenseFile(string filename)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BinaryFormatter bf = new BinaryForma