Appena qualcuno nomina XAML, la maggior parte delle persone pensa immediatamente a complesse interfacce colme di effetti grafici mozzafiato. Certo, XAML è lo strumento principe per la loro realizzazione, però troppi dimenticano cos'è realmente XAML. Io stesso ho raggiunto una diversa consapevolezza solo chiacchierando con Raffaele Rialdi durante la WPC, e tale consapevolezza mi ha consentito di usarlo da subito anche se in realtà non è di user interface che ho bisogno. Veniamo al dunque: XAML è essenzialmente il miglior modo di serializzare un grafo di oggetti che sia mai stato inventato. Ciò lo rende uno strumento favoloso per rappresentare la gerarchia di oggetti che compone una user interface, ma se guardate la cosa da un diverso punto di vista potete intravedere una serie di possibilità interessanti che si aprono. All'interno degli assembly che costituiscono WPF ci sono un paio di classi statiche che sono in grado di prendere qualsiasi (o quasi) oggetto con tutta la sua gerarchia, serializzarlo in XAML e in seguito recuperarlo trasformando il markup nuovamente nell'oggetto di partenza. La bellezza di XamlWriter e XamlReader è che praticamente sono in grado di fare tutto ciò senza la minima traccia degli attributi di serializzazione cui siamo stati abituati da XmlSerializer.

Ora, prendete XAML, aggiungete un generosa dose di NHibernate, un poco di astuzia e avrete ottenuto un cocktail folgorante. Immaginate di avere degli oggetti mappati con NHibernate su un database, poco importa di che oggetti parliamo e che struttura hanno le tabelle, ma come spesso accade vi trovate ad avere la necessità di gestire delle proprietà dinamiche, un po' come fa Dynamics oppure WCF con IExtensibleObject. Succede talvolta che per gestire le customizzazioni sia necessario consentire alle classi di avere più proprietà di quelle definite nella loro dichiarazione. Si sa, i clienti riescono sempre ad inventare qualcosa che non avevamo previsto. Se avete una necessità di questo tipo e state lavorando con NHibernate, probabilmente avete un grosso problema. Il fatto è che se scrivete un file di mappatura dovete metterci tutte le proprietà e di certo non potete aggiungerne a runtime. Dovrete quindi gestirvi le mappature a mano generando i file XML da dare in pasto all'ORM e anche così i problemi che rimangono sono davvero tanti.

Bene, allora vi propongo una soluzione un po' diversa che ho adottato recentemente. Prendete il vostro database, qualunque esso sia e aggiungete alla opportuna tabella una campo di testo, il più grande possibile, un clob in Oracle, un ntext in SqlServer. Se avete la fortuna di usare SQL Server 2005 mettete direttamente un campo di tipo XML. In questo campo andranno a finire tutte le proprietà aggiuntive, di qualunque tipo esse siano, serializzate come un Dictionary<string, object> in XAML. Ora passate alla vostra classe che rappresenta l'oggetto di business e aggiungete una proprietà Xaml privata e associatela mediante il file di mappatura al campo di database di cui sopra. Una interessante caratteristica di NHibernate è di poter mappare anche i campi e le proprietà private. In questo caso è importante mappare una proprietà privata perchè i dati serializzati in XAML non devono mai essere raggiunti in questa forma ma al momento in cui sono assegnati dal runtime di NHibernate alla proprietà devono essere deserializzati e copiati in un field di tipo Dictionary<string, object> cui ho accennato poco fa. Questa operazione è semplice utilizzando le classi XamlWriter e XamlReader. Ecco come:

private string Xaml
{
    get { return XamlWriter.Save(dictionary); }
    set { dictionary = XamlReader.Load(value) as PropertyDictionary }
}

L'unica accortezza da seguire è quella di creare una classe PropertyDictionary che estenda Dictionary<string, object>. Questo perchè XamlWriter e XamlReader non sono in grado di operare su tipi generici, perciò bisogna ingannarli in questo modo. Ora, esponendo il Dictionary avrete ottenuto la vostra classe estensibile, perfettamente integrata con NHibernate. Mettete nelle proprietà praticamente quello che vi pare, e questo verrà automaticamente serializzato e deserializzato senza colpo ferire e naturalmente NHibernate provvederà a persistere il tutto sul database.


La notizia è un po' vecchiotta (almeno secondo i tempi della rete) ma dato che qualcuno mi aveva chiesto informazioni sul mondo 3D in Windows Presentation Foundation oggi che mi è capitato di vedere nuovamente il link ho deciso di postarlo. In effetti durante il webcast avevo dimenticato di segnalare questa libreria che è stata realizzata per consentire l'uso di controlli standard (Textbox, Buttons, Slider, etc...) in una scena tridimensionale. Il problema infatti è che tali controlli non sono usabili in tale contesto perchè il runtime li converte in una bitmap prima di effettuarne il rendering perdendo così le funzionalità. I ragazzi di hanno escogitato una tecnica interessante che consiste nel sovrapporre un controllo reale reso trasparente al controllo reso in 3D facendo coincidere le zone sensibili all'iterazione dell'utente. Dateci un'occhiata perchè è molto istruttiva.

Link: 3D Tools for the Windows Presentation Foundation


Durante il webcast di Giovedì, qualcuno mi ha chiesto a proposito della compatibilità tra il Composite Application Block e WPF. Quest'oggi leggo un post a proposito di questo argomento che giro nel mio blog nella speranza che arrivi a chi mi aveva posto la domanda cui al momento non avevo saputo dare risposta.

Link: WPF & Composite Application Block (CAB)


Giovedì prossimo mi aspetta un secondo webcast, dal titolo un po' criptico di "Creare interfacce avanzate con XAML", che in verità potrebbe dire tutto come nulla. Ad uso e consumo di chi vorrà seguirmi vi allego qui a fianco una piccola preview di quello che sarà il risultato finale del webcast.

L'applicazione "bruttina" del primo webcast migrerà un passetto alla volta fino a diventare decisamente più accettabile ed usabile grazie alle fantastiche possibilità di Windows Presentation Foundation.

La cosa curiosa, che vi invito a tenere in considerazione è che per arrivare a questo risultato non scriveremo una sola riga di codice C# per dimostrare che organizzando opportunamente il lavoro e sfruttando a fondo le possibilità di WPF, una vera separazione tra grafica e logica oltre che ausipicabile diventa anche possibile. Gli argomenti che toccheremo saranno: Layout, Risorse, Stili, Decorator, Control Templates, Brushes, Bitmap Effects, Transformazioni, Triggers e Animazioni. Si tratterà ovviamente di una overview degli argomenti che spero di poter approfondire in successive puntate.

Vi aspetto tutti quindi il prossimo 21 dicembre, numerosi come lo scorso giovedì.


Le domande a cui mi riferisco sono quelle che mi sono state poste durante il webcast che ho tenuto il 14 dicembre scorso. Pensando e ripensando a quando detto mi sono rso conto che la fretta di chiudere il webcast per la mancanza di tempo mi ha portato probabilmente ad essere un po' impreciso in alcune risposte. Ho deciso perciò di dare qualche risposta un po' pià dettagliata su queste righe nella speranza che chi le ha poste mi segua e ne possa beneficiare.

Domanda: "L'uso di WPF mi può portare dei vantaggi che mi spingano ad abbandonare WindowsForms in suo favore?"

In realtà ritengo non sia saggio "abbandonare" WindowsForms. Le due piattaforme, WindowsForms e WPF hanno entrambe dei vantaggi e degli svantaggi che devono essere attentamente soppesati prima di decidere in favore dell'una o dell'altra. Di certo molte applicazioni, soprattutto quelle dedicate ad ambiti dove la usabilità e il forte impatto grafico siano molto importanti WPF sarà irrinunciabile e garantirà di sviluppare con velocità ed efficacia. Altri ambiti, più pragmaticamente dovranno essere ancora affrontati con le tradizionali WindowsForms che ancora per molto tempo saranno le sole ad avre la completezza e l'efficacia cui siamo abituati. Il tempo comunque a mio parere dovrà spingere nella direzione di WPF, soprattutto quando il mercato si renderà pienamente conto di ciò che essa può offrire e quindi i clienti cominceranno a pretendere applicazioni scritte con queste feature.

Domanda: "Posso scomporre lo XAML?"

Confesso che di primo acchito francesca mi ha lasciato un po' interdetto, almeno fintanto che non ha chiarito cosa intendeva dire. In effetti si stava riferendo ad un concetto molto importante nella programmazione che noi tutti normalmente abbiamo molto presente. Mi riferisco al riutilizzo del codice, cioè allo "scomporre" le varie parti di un file XAML in differenti porzioni suddivise in differenti file. La mia risposta è stata in questo caso solo parziale. In effetti oltre all'uso delle risorse, è anche possibile creare degli UserControl, che al pari di quelli di ASP.NET consentono di riutilizzare differenti porzioni di codice dando loro la responsabilità di una parte dell'interfaccia riutilizzata in più punti dell'applicazione.

Domanda: "Qual'è il nome esatto dei tool di design per lo XAML?"

Stamane alcuni colleghi mi hanno dato un brivido dicendomi che secondo loro Expression Blend era stato rilasciato circa due settimane fa. Stasera sono andato a vedere se davvero mi era sfuggita una notizia di tale portata e ho avuto la conferma che non mi sbagliavo. Expression Blend, quello che fino a poco tempo fa era denominato Interactive Designer è stato rilasciato in BETA 1. La beta è scaricabile a questo indirizzo. Probabilmente i colleghi si sono confusi con Expression Web che è stato rilasciato il 4 dicembre scorso in RTM mache con XAML ha nulla a che vedere. Mi risulta che Expression Blend sia un tool abbastanza maturo ma probabilmente non ha un grande impatto per il pubblico degli sviluppatori ma soprattutto per quello dei visual design. L'altro tool cui mi riferivo nel webcast è il "Visual Studio 2005 extensions for .NET Framework 3.0 (WCF & WPF), November 2006 CTP", per gli amici "cider". Il nome così lungo è il motivo per cui non lo ricordavo. Cider purtroppo non è uno strumento attualmente utilizzabile perchè soffre di alcuni bug che impediscono di importare propri namespace.

Spero di essere stato esauriente, al limite sapete dove trovarmi.


Charles Petzold, l'autore di "Applications = Code + Markup" ha pubblicato una eccellente articolo a proposito dei ControlTemplates. Si tratta di un articolo che spiega con dovizia di particolari le caratteristiche dei controlli "lookless" di WPF e come personalizzarne l'aspetto fino a stravolgerli completamente. Per inciso questo sarà anche uno degli argomenti che tratterò nel webcast della prossima settimana quando faremo uso dei ControlTemplates per trasformare radicalmente l'aspetto di una ListBox.

Link: Using Templates to Customize WPF Controls


Incredibile, non apro il reader per una giornata e mi perdo un degli eventi più importanti. Pare che proprio stamane infatti Microsoft abbia pubblicato la prima CTP dell'attesissima (da parte mia...) WPF/e, dove "e" sta per "everywhere"... Nel blog di Lester alcune immagini significative:

Link: http://blogs.msdn.com/llobo/archive/2006/12/04/wpf-e-is-out.aspx

Ora lo installo e vedo di rendermene conto con i miei occhi, ma lo sapete qual'è la cosa più entusiasmante? C'è anche la versione per MAC!

Download:


Mentre preparavo l'applicazione per il webcast mi sono scontrato con un problema che mi ha fatto perdere un po' di tempo. Il problema in questione era che dopo aver radicalmente modificato l'aspetto di una ListBox perdendo quasi ogni riferimento all'originale, mi rimaneva ancora la selezione degli item così come la listbox tradizionale. Ho cercato quindi di risolvere tale problema perchè mi pareva impossibile che un particolare così importante rimanesse intoccabile. La soluzione che ora vi prospetto è un po' strana, ma in definitiva ha una ragione. Per comprenderla meglio bisogna capire che ogni ListBoxItem contenuto nella ListBox è a sua volta contenitore di un elemento ContentPresenter dentro al quale viene iniettato l'elemento generato dal binding. La selezione tradizionale avviene modificando il colore del ListBoxItem stesso pertanto per poter rimuovere questo effetto è necessario intercettare ogni singolo item e valorizzare con {x:Null} la proprietà FocusVisualStyle. Il problema è che l'unico modo per arrivare ad applicare questo valore alla proprietà è quello di usare uno style assegnadolo alla proprietà ItemContainerStyle della ListBox.

Ecco come fare:

<ListBox>
  <ListBox.ItemContainerStyle>
    <Style TargetType="{x:Type ListBoxItem}">
      <Setter Property="FocusVisualStyle"
        Value="{x:Null}" />
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type ListBoxItem}">
            <ContentPresenter />
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </ListBox.ItemContainerStyle>
</ListBox>

Il particolare che mi ha fatto impazzire è la necessità di definire un ControlTemplate vuoto. Infatti modificando esclusivamente la proprietà FocusVisualStyle non si ottiene alcun effetto. Non ho ancora una spiegazione valida ma non appena la trovo non mancherò di farvela sapere. Il sistema comunque non è proprio immediato, ma alla fine fa esattamente quello che serve. Gli elementi della listbox rimangono selezionabili ma nonostante questo la selezione non appare. Grazie a questo è possibile gestire in proprio la selezione degli elementi e applicare qualche effetto curioso. Ecco un esempio di codice il cui effetto è riprodotto dalla gif animata:

<Window x:Class="XeDotNet.WebCasts.AdvancedUI.Demo1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="XeDotNet.WebCasts.AdvancedUI.Demo1"
        Height="200"
        Width="200">
    <Grid>
        <ListBox Margin="20" SelectedIndex="0">
            <ListBoxItem Content="Item 1" />
            <ListBoxItem Content="Item 2" />
            <ListBoxItem Content="Item 3" />
            <ListBoxItem Content="Item 4" />
            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Setter Property="FocusVisualStyle"
                            Value="{x:Null}" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected"
                                             Value="True">
                                        <Trigger.EnterActions>
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <DoubleAnimation To="3"
                                                                     Storyboard.TargetName="scale"
                                                                     Storyboard.TargetProperty="ScaleY" />
                                                    <DoubleAnimation To="3"                                                                
                                                                     Storyboard.TargetName="scale"
                                                                     Storyboard.TargetProperty="ScaleX" />        
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </Trigger.EnterActions>
                                        <Trigger.ExitActions>
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <DoubleAnimation To="1"                                                                     
                                                                     Storyboard.TargetName="scale"
                                                                     Storyboard.TargetProperty="ScaleY" />
                                                    <DoubleAnimation To="1"
                                                                     Storyboard.TargetName="scale"
                                                                     Storyboard.TargetProperty="ScaleX" />
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </Trigger.ExitActions>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                                <ContentPresenter>
                                    <ContentPresenter.LayoutTransform>
                                        <ScaleTransform ScaleY="1"
                                                        x:Name="scale" />
                                    </ContentPresenter.LayoutTransform>
                                </ContentPresenter>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>
    </Grid>
</Window>

Certo, non si può dire che il codice sia stringato ed essenziale, ma chi ha provato XAML sa che usando un po' di astuzia si riesce a semplificare un po' usando stili e risorse.


Qualche giorno fa ha un bel tool di conversione per XAML che ha il potere di resuscitare le interfacce scritte con VB6. A parte il fare i miei complimenti per l'ottimo lavoro, devo rilavare che con questo tool Davide ha fondamentalmente lanciato l'ultimo salvagente agli sviluppatori che tutt'oggi sono fossilizzati sull'uso di Visual Basic 6.0. Credo occorra rendersi conto che davvero, se queste persone, queste aziende, perderanno anche questa occasione allora davvero non ci sarà più nulla da fare per recuperare. Il tempo non è ancora strettissimo. E' palese che passerà un po' ancora prima che il mercato arrivi a chiedere applicazioni scritte con Windows Presentation Foundation, tempo che i pionieri certamente metteranno a frutto per scrivere la storia di questo bell'esemplare di framework. Ma prima o poi succederà e ormai si può dire chiaramente che la meta è in vista e non si può più fare finta che non stia succedendo nulla. Perciò ascoltate il mio consiglio. Davide vi da l'occasione per risparmiare un po' di tempo e poter vedere dei risultati molto in fretta. Cogliete l'occasione perchè poi nessuno più si volterà indietro a guardare chi ha deciso di fermarsi...


Finalmente è arrivato! Era un po' di tempo che ci pensavo e che valutavo la possibilità di impegnarmi personalmente nell'impresa. Stamattina ho scoperto che naturalmente qualcuno lo aveva già pensato e oggi stesso ha pubblicato un utilissimo tool. , ha reso pubblico SWF2XAML, un tool che consente di scegliere una porzione di file SWF e convertirla a XAML. Certo, non è esattamente quello che mi aspettavo, ma credo che l'impresa di convertire un intero filmato in XAML sia un po' improbabile dato che flash fa un pesante uso di ActionScript per realizzare le animazioni più spinte.

Link:


Una cosa che ho sentito ripetere più e più volte durante questa WPC 2006 è che scrivere applicazione WPF con XAML è difficile perchè il codice è prolisso. Temo che questo possa diventare un luogo comune e per questo vorrei fare una piccola considerazione da sviluppatore web-oriented quale sono. Chi di voi ha mai provato per sfizio, oppure lo ha fatto sul serio per professione, sa bene che scrivere pagine web usando HTML è una'attività complessa e irta di ostacoli. HTML di suo è prolisso ma per questo nessuno mette in dubbio che si possa realizzare qualcosa di buono con esso, nonostante il problema dei differenti browser, dei css, degli standard e altre cosucce del genere.

E' vero, XAML è un po' prolisso e io per primo dico che spero al più presto esca qualcosa per semplificare, ma sono anche cosciente del fatto che fare un uso professionale di XAML, nonostante sia infinitamente più semplice e lineare di HTML richiederà spesso di abbandonare i tool e scrivere a mano. A me questo non spaventa... non capisco perchè spaventi gli altri.