Technology Experience

.NET World

Programmazione, libri, snippet di codice, articoli tecnici

.NET World

SQL Server Management Studio e SQL Server Mobile

SQL Server Management Studio permette di lavorare anche con database SQL Server Mobile. Quest’ultimo è un piccolo motore di database che gira su device Pocket PC e Windows Mobile, le cui capacità sono ovviamente ridotte rispetto al classico SQL Server che conosciamo. E’ comunque un’ottima soluzione per avere un database relazionale

I database SQL Server Mobile sono semplici files .sdf. Tramite SQL Server Management Studio possiamo aprire e lavorare questi files, indipendentemente dal fatto che essi si trovino sul nostro PC fisico, su un palmare o addirittura su un emulatore di palmare. Vediamo tutti e tre i casi, perchè ci sono alcuni aspetti che meritano di essere discussi.

Apertura di un database su un PC fisico
Nelle prime fasi di sviluppo è comodo cominciare a lavorare su un nuovo database, senza aver per forza un palmare fisico. Questo significa che possiamo creare un file .sdf sul PC di sviluppo, magari nella directory della solution. Con SQL Server Management Studio possiamo aprire il file dalla finestra Connect To Server e specificare il file con il suo path locale. Ricordiamoci di selezionare la voce SQL Server Mobile nella casella Server Type.

Nulla di che, giusto?

Apertura di un database su Pocket PC/Windows Mobile
Per aprire un file .sdf presente su un device mobile è necessario che quest’ultimo sia connesso via ActiveSync oppure via Windows Mobile Device Center (questo dipende dall’OS che usate: Windows XP oppure Windows Vista). Dalla finestra Connect To Server è necessario specificare il path che punti innanzitutto al device e poi via via specifichi il percorso corretto:

Nell’immagine qui sopra si vede che il path è Mobile DeviceSDMMC Diskdatabase.sdf. Se non conoscete il percorso giusto basta aprire la casella e cliccare su <Browse for more…>. Nel caso che ho preso io come esempio, il file .sdf è stato salvato sulla SD interna del palmare: questo chiaramente non è sempre così. Dipende dalla lingua e dal tipo di supporto che usate.

Apertura di un database su un emulatore
Il pacchetto Visual Studio 2005/2008 mette a disposizione un emulatore su cui possono girare sistemi operativi come Pocket PC e Windows Mobile. Se non avete esigenze particolari questo emulatore è l’ideale per cominciare a sviluppare qualcosa, soprattutto se non avete a disposizione un palmare reale.

Per aprire il manager degli emulatori basta andare sul menù Tools –> Device Emulator Manager di Visual Studio. Apparirà una finestra con l’elenco di tutte le immagini di palmari che avete installato. Cliccate con il destro su una qualsiasi voce e poi cliccate Connect: in pochi secondi verrà avviato sullo schermo un vero e proprio palmare, su cui potete fare tutte le installazioni che volete, come se fosse un palmare fisico vero e proprio.

A questo punto la domanda è: come faccio ad aprire un file .sdf che sta su un emulatore? Torniamo al passo precedente: abbiamo visto come SQL Server Management Studio possa collegarsi al dispositivo connesso via ActiveSync. E’ possibile collegare l’emulatore ad ActiveSync, così da far credere a quest’ultimo di aver a che fare con un vero palmare? Certamente sì! Cosa starei qui a parlare, se no?

Per farlo, avviate un emulatore qualsiasi dal Device Emulator Manager. Una volta che l’emulatore è partito, cliccateci sopra con il destro e cliccate sulla voce Cradle. Ricordatevi di aver selezionato la voce DMA nelle connessioni consentite da ActiveSync.

Se tutto è andato a buon fine, vedrete ActiveSync che rileva il dispositivo e si connette, esattamente come farebbe con un palmare vero. A questo punto, è sufficiente seguire la stessa procedura che abbiamo visto prima.

Send to Kindle
.NET World

Se ActiveSync non vi parte, date un’occhiata al firewall

Questa mattina mi è successa una cosa strana e mai accaduta prima. Ho dovuto installare sul notebook della mia collega Raffaela (non è un errore di battitura: due effe ed una erre sola) ActiveSync 4.5, perchè aveva bisogno di copiare certi files all’interno della SD. Scarichiamo l’installer, lo lanciamo e riavviamo il PC.

Al riavvio, non c’è alcuna icona di ActiveSync nella tray-bar di Windows XP. Strano, non mi è mai successo. Proviamo a connettere comunque il palmare via USB, andiamo in Risorse del Computer, facciamo doppio-click sull’icona Dispositivo Portatile. Appare un messaggio di errore che adesso non sono in grado di dirvi. Diceva qualcosa del tipo: “Impossibile avviare la comunicazione a causa della mancanza di servizi essenziali“.

Ho fatto qualche ricerca su Google durante la mattinata e ho scoperto che l’installer di ActiveSync si occupa di configurare il firewall di Windows nel modo seguente:

Effettivamente sul mio PC di sviluppo è così, idem a casa e su tutti gli altri PC su cui ho installato ActiveSync.

A volte invece (devo capire quando, probabilmente quando qualche servizio di sistema è spento/disattivato) questo non accade: l’exe di ActiveSync non parte nemmeno e la connessione al palmare non avviene. Non ho provato ad impostare manualmente il firewall – la giornata è stata presa da altre attività.

La quattro voci evidenziate qui sopra fanno riferimento a questi tre eseguibili ed alla porta:

  • ActiveSync Application
    C:ProgrammiMicrosoft ActiveSyncWCESMgr.exe
  • ActiveSync Connection Manager
    C:ProgrammiMicrosoft ActiveSyncwcescomm.exe
  • ActiveSync RAPI Manager
    C:ProgrammiMicrosoft ActiveSync
    apimgr.exe
  • ActiveSync Service
    Porta 26675

Se dovesse capitare anche a voi, quindi, sapete dove andare a guardare.

Send to Kindle
.NET World

Ok, son migrato ufficialmente a Subtext 2.0!

Introduzione 
Sono circa due settimane che il mio blog gira con Subtext 2.0, la nuova ed ultima release del noto blog engine, che annovera fra i suoi creatori anche il buon Simone Chiaretta.

Decido di dare oggi l’ufficialità di questa cosa, perchè la migrazione è stata sì indolore, ma un po’ preoccupante per alcuni sintomi.

  1. Parecchi di voi mi hanno detto via mail e via messenger che ogni tanto il mio blog si apriva senza skin. Urgh!
  2. Nella parte Admin del blog ogni tanto avevo una strana exception, che veniva tracciato correttamente nell’ErrorLog. Questo errore mi impediva di salvare dalla pagina Options –> Configure. In pratica, dove ci sono le impostazioni generali del blog: titolo del blog, skin da utilizzare, timezone e via dicendo. Urgh!

Primi passi per la risoluzione
Ho deciso di indagare, perchè il mio blog engine deve girare al meglio.
Dopo essermi consultato con Simone, ho operato nel modo seguente:

  1. Ho scaricato i sorgenti di Subtext 2.0 da SourceForge.net
  2. Ho fatto un backup del database SQL Server dal mio hosting
  3. Ho ripristinato il backup del punto (2) sul mio database SQL Server locale
  4. Ho aperto i sorgenti di Subtext 2.0 con Visual Studio 2008 con il file .sln dedicato
  5. Ho configurato la stringa di connessione nel file web.config, così da far usare il mio database locale

La comodità di tutto questo è che non c’è bisogno di avere un web-server installato: è sufficiente quello integrato di Visual Studio. Basta impostare il progetto Subtext.Web come StartUp Project ed il gioco è fatto.

Debug
Non sto qui a raccontarvi tutti i giri di debug che mi sono fatto: non sono nemmeno da lontano la persona più adatta a parlarvene, giusto? Partiamo solo dallo StackTrace che mi veniva segnalato dall’ErrorLog di Subtext 2.0. Lo StrackTrace diceva quanto segue:

System.ArgumentException: An item with the same key has already been added. at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) at Subtext.Framework.UI.Skinning.SkinTemplateCollection.GetTemplate(String skinKey) at Subtext.Framework.UI.Skinning.StyleSheetElementCollectionRenderer.GetStylesToBeMerged(String skinName, String media, String title, String conditional) at Subtext.Framework.Web.Handlers.CssHandler.HandleRequest(HttpContext context) at Subtext.Extensibility.Web.BaseHttpHandler.ProcessRequest(HttpContext context) at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

L’Exception veniva sollevata dal metodo GetTemplate() della classe SkinTemplateCollection. Li ho marcati in rosso qui sopra per evidenziarli meglio. Pare che in questo metodo ci sia un .Add() su un Dictionary, e che tale .Add() tenti di inserire per due volte la stessa key. Perchè? Perchè? Perchè?

Sono andato a beccarmi il codice incriminato. La classe SkinTemplateCollection è implementata nel namespace Subtext.Framework.UI.Skinning, nell’assembly Subtext.Framework. Ecco il metodo:

1 public SkinTemplate GetTemplate(string skinKey) 2 { 3 if (_ht == null) 4 { 5 _ht = new Dictionary<string, SkinTemplate>(); 6 for (int i = 0; i < this.Count; i++) 7 { 8 _ht.Add(this[i].SkinKey, this[i]); 9 } 10 } 11 12 if (_ht.ContainsKey(skinKey.ToUpper(System.Globalization.CultureInfo.InvariantCulture))) 13 { 14 return _ht[skinKey.ToUpper(System.Globalization.CultureInfo.InvariantCulture)]; 15 } 16 return null; 17 }

Riga 8 : all’interno del ciclo for c’è la chiamata .Add() incriminata, che cerca di aggiungere al Dictionary _ht, definito come privato di classe, una chiave doppia. Non sono stato lì a farmi troppe paturnie mentali. So solo che se quel ciclo for viene interrotto per qualche motivo, la return di riga (14) non verrà mai eseguita – semmai verrà restituito al chiamante un bell null. Quindi…Mi sono chiesto semplicemente: non è che all’interno dei files .config ho referenziato due volte lo stesso skin?

Dove devono essere referenziati gli skin di Subtext 2.0 ?

Io non lo sapevo: me lo sono fatto spiegare da Simone – e chi da chi altri sennò?

Gli skins vengono installati dentro la directory Skins di una normale installazione Subtext. Ogni skin viene installato in un folder separato: AnotherEnd001, DayDreaming, Gradient, KeyWest, Lightz e così via. Ma non basta, perchè bisogna gestire due files .config: uno è /Admin/Skins.config, l’altro è /Admin/Skins.user.config. Li ho scaricati in locale e li esaminati a mano, se non altro perchè hanno strutture differenti.

Mi sono quindi accorto che effettivamente lo skin GlossyBlue era referenziato due volte, puntando alla stessa directory ma scritta in modo diverso (“GlossyBlue” e “glossyblue”). Che sia questo il problema? Ho semplicemente cancellato il file /Admin/Skins.user.config, ho cancellato l’ErrorLog di Subtext e…stiamo a vedere. Adesso tutto sembra girare bene.

Intanto i problemi segnalati prima non li ho più: lo skin appare sempre, e posso salvare le impostazioni.

Forse, sì, dai…fra qualche lustro potrò anche fare lo sviluppare Web (cit.).

Technorati Tags:      

Send to Kindle
.NET World

Certo che MSDN Magazine non lo capisco proprio!

Non parlo dei contenuti, anche se afferrare fino in fondo certi articoli richiede parecchia materia grigia, ma delle modalità che regolano il rinnovo dell’abbonamento annuale. Ne ho già parlato in passato, ma la situazione peggiora.

Dunque, lasciate che vi racconti brevemente questa mia vicenda.

Il mio abbonamento doveva scadere a Maggio 2008. Dopo aver protestato lievemente per aver perso alcuni numeri (mi pare intorno a gennaio-febbraio), hanno deciso di allungarmi la durata dell’abbonamento per altri due mesi, in modo tale da coprire i mesi persi. Ottima iniziativa, devo dire. Quindi, ho calcolato la data di scadenza a Luglio 2008.

Mentre ero in vacanza mi sono ricordato di questa cosa: sono andato sul sito MSDN e ho cominciato la procedura per il rinnovo.

Se uso l’account number, il mio abbonamento non viene trovato. Vi dirò di più: questo qui sotto è l’esempio di label che il sito MSDN Magazine mette on-line per aiutare il povero utente a capire qual è esattamente il suo account number.
La label è questa:

Le parti evidenziate in azzurrino compongono il famigerato account number che dovrei inserire.
Peccato che il layout della label qui sopra sia completamente diverso da quello che ricevo io.

Lo so, forse invece di bloggare dovrei scrivere o contattare qualcuno per risolvere il problema. L’ho già fatto: ho contattato la chat MSDN di assistenza, ho scritto e-mail a Microsoft e direttamente alla rivista. Niente: nessuno sa darmi l’account number che mi serve.

Finisco: non so bene per quale motivo, ma ieri ho ricevuto il numero di Settembre 2008 della rivista.
Ma…l’abbonamento non doveva concludersi a Luglio 2008??? Boh!…finchè dura, me la godo, poi si vedrà.

Technorati Tags:

Send to Kindle
.NET World

Disponibile XamlPad 4.0

A questo url è possibile scaricare la versione 4.0 di XamlPad, un tool freeware che permette di editare codice XAML e di vederne subito la preview. Non ho letto esattamente le novità: superficialmente ho notato solo un avvio estremamente più rapido e la toolbar graficamente rinnovata.

Usandolo per 5 minuti di più e dando un’occhiata alle funzioni disponibili sulla toolbar, si scopre che adesso è possibile esaminare il visual tree della classe Page o della classe Windows che si sta editando, ed è anche possibile dare un’occhiata agli stili predefiniti per ciascun controllo nativo di WPF (ricordo gli esempi di Charles Petzold sul suo libro che facevano praticamente la stessa cosa).

E’ vero, forse manca l’Intellisense, ma per me sinceramente è essenziale, perchè è leggero ed è diventato nel mio cuore il ‘notepad’ XAML-oriented, anche se è utilizzabile solo per files piccoli e facilmente gestibili.

Download : http://blogs.msdn.com/llobo/archive/2008/08/25/xamlpadx-4-0.aspx

Technorati Tags:    

Send to Kindle
.NET World

‘Sto spamming va seriamente debellato!!!

Ok, lo spamming sappiamo tutti cos’è. Ogni giorno riceviamo e-mail e messaggi di ogni tipo, che ci consigliamo acquisti di ogni tipo. Spesso di tratta di prodotti che nemmeno vogliamo e che mai ci sogneremmo di acquistare.

E’ il caso del libro Beginning ASP.NET MVC. Il suo autore, un certo Simone Chiaretta, ha pensato bene di farmi spamming sul mio messenger e di avvisarmi che il suo primo libro, rigorosamente in lingua inglese, è in fase di pre-sale su Amazon UK. Se siete interessati, cliccate sul link di prima ed ordinatelo. Simone è una brava persona, un caro amico delle community ed in diverse occasioni è stato anche un mio compagno di viaggio nelle scorribande UGIdotNET. E poi, chiaramente, è anche un ottimo professionista, competente e preparato. Se state leggendo il mio blog, e quello di tanti altri in giro per il mondo, lo dovete anche a lui, dal momento che è uno degli sviluppatori ufficiali del blog engine Subtext.

Perciò state sicuri: se ha scritto un libro, merita sicuramente.
A patto che lavoriate con ASP.NET. Mi sento escluso.

Link : http://www.amazon.co.uk/Beginning-ASP-NET-MVC-Simone-Chiaretta/dp/047043399X

Oggi lo spamming di Simone è perdonato. 🙂
Comunque…va proprio debellato. Adesso pure di libri su ASP.Net mi tocca leggere.
Spero che non mi accada mai più! 🙂

Technorati Tags:     

Send to Kindle
.NET World

Piccole istruzioni Linq per semplificare un po’ il codice

Supponiamo l’esistenza di una classe Player che tra le altre proprietà ne esponga una di tipo intero denominata Strength.

Supponiamo l’esistenza di una classe Team che tra le altre proprietà ne esponga una di tipo List<Player> denominata AcquiredPlayers.

Supponiamo l’esistenza di una classe Match che calcola l’incontro tra due Team diversi e ne calcola l’esito.

Un match viene vinto dal Team che raggiunge il punteggio più alto.
Tale punteggio è la somma dei valori della proprietà Strength dei giocatori appartenenti ad un Team (semplificando, chiaramente).
Es: l’istanza team1 ha acquisito 3 Players. Il primo ha Strength = 20, il secondo 45 ed il terzo = 56. Team1 ottiene un punteggio pari a 121. Per vincere un match, l’altro team deve ottenere un punteggio maggiore di 121.

Dopo questo piccolo preambolo per illustrare lo scenario, passiamo a qualcosa di tecnico e di divertente.

Come ottenere con una sola riga di C#, sfruttando Linq, il punteggio totalizzato da un team? Così:

int ScoreTeam1 = base._playersTeam1.Sum(s => s.Player.Strength);

Semplice da leggere, efficiente e molto compatto. Se c’è una cosa bella di Linq, così come qualsiasi altra tecnologia ben congegnata, è che essa può essere sfruttata fin da subito, in progetti già avviati ed in produzione, senza bisogno di grossi stravolgimenti alla nostra applicazione o agli strumenti di sviluppo. L’unica cosa richiesta è la compilazione con il .NET Framework 3.5 ed un referenziamento all’assembly System.Core.dll.

Technorati Tags:   

Send to Kindle
.NET World

Download iso del Visual Studio 2008 SP1

Se cercate su Google l’indirizzo dal quale scaricare il Service Pack 1 di Visual Studio 2008, probabilmente capiterete qua.

Siccome so di non essere l’unico a cui non piacciono gli installer da 536Kb che poi scaricano il resto dalla Rete, ecco per voi l’indirizzo dello stesso download, ma in formato ISO. L’ISO, lo ricordo per i pochi che non lo sapessero, è un formato che può essere utilizzato in due modi: o lo masterizzate su un CD/DVD, oppure – più semplicemente – utilizzate tools come Daemon Tools per creare un’unità CD/DVD virtuale.

Il download del VS2008SP1 in formato ISO è di circa 831Mb.
Buon download!

P.S. : grazie ad Alessandro Del Sole per il suo post di qualche giorno fa! 🙂

Send to Kindle
.NET World

Quiz: perchè NullReferenceException ?

Questo metodo NetworkingSettings() viene eseguito all’avvio di un’applicazione su Pocket PC 2003 su cui è installato il Compact Framework 2.0. Lo scopo, come si vede dal codice che ho scritto, è quello di creare nel registro di configurazione del dispositivo una certa chiave dentro HKLMCommTcpIphosts. Purtroppo ho inserito queste righe nella versione finale del software, versione che è stata distribuita su una ventina di palmati Pocket PC, con il risultato di scatenare un’eccezione NullReferenceException non gestita.

1 public void NetworkingSettings() 2 { 3 RegistryKey key = Registry.LocalMachine.OpenSubKey(@"CommTcpIphosts ome_server"); 4 5 if (key == null) 6 { 7 key = Registry.LocalMachine.OpenSubKey(@"CommTcpIphosts", true); 8 key = key.CreateSubKey("nome_server"); 9 10 byte[] ip = new byte[4] 11 { 12 150, 80, 10, 196 13 }; 14 15 key.SetValue("ipaddr", ip, RegistryValueKind.Binary); 16 key.Close(); 17 } 18 }

Rispetto al codice in produzione ho cambiato alcune cose minimali: innanzitutto nome_server è un dominio valido; seconda cosa, i quattro bytes del byte[] hanno valori differenti. La mia domanda è: secondo voi, dove si scatena l’eccezione di cui sopra? Una volta individuato il punto (che io già conosco), la domanda successiva è: perchè?

Technorati Tags:  

Send to Kindle
.NET World

Usare in un DataTemplateSelector un ResourceDictionary definito in un file XAML

Ok, il titolo di questo post è più confuso che altro. Amen.

Nei giorni scorsi ho creato una class library per .NET Framework 3.5, all’interno del quale ci sono Windows in XAML, ResourceDictionary, immagini e video. C’è anche una bella classe TagDataTemplateSelector, che eredita da DataTemplateSelector.

Come ben sa chi sviluppa in WPF, una classe figlia di DataTemplateSelector ha un metodo pubblico SelectTemplate, che restituisce un DataTemplate piuttosto che un altro, in base alla logica che implementiamo nel metodo stesso. Questo serve ad esempio se avete una ListBox e volete applicare un template differente per ogni elemento: supponiamo di avere una classe Person che espone una proprietà Sex, che può valere Sex.Male o Sex.Female usando un’enum. Se un’istanza ha Sex == Sex.Male, vogliamo uno sfondo azzurro, mentre se Sex == Sex.Female, vogliamo uno sfondo rosa. I DataTemplateSelector servono proprio a questo.

Manco a farlo apposta, il mio esempio è un po’ più complesso di così.

All’interno di questa class library ho creato un ResourceDictionary in un file TagStyle.xaml. In questo ResourceDictionary ho definito due stili: InternetTag e LocalTag. Questi sono due stili praticamente identici, se non per un’immagine PNG che cambia. Ecco lo XAML che definisce lo stile InternetTag.

<Style x:Key="InternetTag" TargetType="{x:Type ListBox}"> <Setter Property="ItemTemplate"> <Setter.Value> <DataTemplate> <StackPanel Orientation="Horizontal"> <Image Margin="4" Source="ImagesInternetTagLogo.png" /> <Label VerticalContentAlignment="Center" Content="{Binding Path=Identifier}" FontSize="10pt" Padding="4" Width="110"> </Label> </StackPanel> </DataTemplate> </Setter.Value> </Setter> </Style>

Il mio problema è che non riuscivo a restituire i due stili dalla classe TagDataTemplateSelector. Di solito, infatti, riesco a raggiungere l’istanza dello stile tramite l’applicazione corrente. In questo caso, invece, il codice gira dentro una class library, e quindi non ho un’applicazione istanziata. L’unico modo che ho trovato è quello di caricare il ResourceDictionary via codice, reperire gli stili definiti.

Il costruttore del DataTemplateSelector è diventato quindi il seguente:

1 public TagDataTemplateSelector() 2 { 3 ResourceDictionary dict = new ResourceDictionary(); 4 dict.Source = 5 new Uri("pack://application:,,,/VivendoByte.WindowsLiveWriterPlugins.TechnoratiTagsWPF;component/TagStyle.xaml"); 6 7 Style s = (Style)dict["InternetTag"]; 8 Setter st = (Setter)s.Setters[0]; 9 internetDataTemplate = (DataTemplate)st.Value; 10 11 s = (Style)dict["LocalTag"]; 12 st = (Setter)s.Setters[0]; 13 localDiskDataTemplate = (DataTemplate)st.Value; 14 }

Alla riga 1 istanzio un ResourceDictionary, che viene riempito alla riga 2 specificando un Uri adeguato. In pratica, specifico l’assembly nel quale è contenuto il ResourceDictionary, e specifico anche il nome del file XAML. Le righe 7-9 e 11-14 hanno la stessa logica: nel primo blocco recupero lo style InternetTag, poi il suo setter (riga 8) e salvo in un membro privato della classe il Value di quel setter. Tale membro privato è internetDataTemplate. La stessa cosa accade per l’altro stile LocalTag, che viene salvato in localDiskDataTemplate.

Tutto questo accade nel costruttore. Il metodo SelectTemplate diventa a questo punto un semplice switch:

1 public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container) 2 { 3 if (item != null && item is TechnoratiTag) 4 { 5 TechnoratiTag tag = item as TechnoratiTag; 6 7 switch (tag.Source) 8 { 9 case TagSource.Internet: 10 { 11 return internetDataTemplate; 12 } 13 case TagSource.LocalDisk: 14 { 15 return localDiskDataTemplate; 16 } 17 } 18 } 19 20 return null; 21 }

Il DataTemplate da restituire dipende come dicevamo da un valore della proprietà dell’oggetto item, che viene quindi castato a TechnoratiTag. In base alla sua proprietà Source restituisco alla ListBox un DataTemplate piuttosto che un altro.

La particolarità di questa soluzione sta nel fatto che non passiamo da un’istanza di Application.Current, perchè quest’ultima non esiste e di conseguenza vale null. Se potessimo accederci, invece, potremmo usare il metodo FindResource per recuperare le risorse definite dentro App.xaml. Oppure potremmo usare la collection Windows[], ma neppure questo è fattibile. L’unica tecnica possibile, come mostrato dal codice, è quello di caricare a run-time un ResourceDictionary e cercare al suo interno i DataTemplate voluti.

Technorati Tags:   

Send to Kindle