Introduzione a Windows Presentation Foundation (prima parte)
a cura di Alessandro Del Sole (requisiti: conoscenza del .NET Framework 2.0)

Premessa - Il .NET Framework 3.0
Con il rilascio del .NET Framework 3.0, Microsoft ha introdotto nel mondo dello sviluppo nuove importanti tecnologie: Windows Presentation Foundation, Windows Communication Foundation, Windows Workflow Foundation e Windows CardSpace. Queste importanti tecnologie costituiscono parte integrante del nuovo sistema operativo Windows Vista, che basa gran parte del proprio funzionamento su di esse. Infatti, il .NET Framework 3.0 è già incluso in questo sistema operativo, mentre deve essere installato separatamente sugli altri.

E' fondamentale capire che .NET Framework 3.0 (precedentemente noto col nome di WinFX) non è la versione successiva alla 2.0, bensì una estensione di quest'ultima, di cui necessita per il proprio funzionamento. Pertanto, con il rilascio di .NET 3.0, le tecnologie che eravamo abituati ad utilizzare (Windows Forms, ADO.NET, ASP.NET) rimangono invariate, ma abbiamo la possibilità di sfruttare le novità managed per realizzare applicazioni ancora più performanti. Per una versione effettivamente nuova del .NET Framework, dovremo attendere il rilascio della v. 3.5, che attualmente è in fase Beta, e che verrà resa disponibile con l'uscita di Visual Studio 2008. .NET Framework 3.0 amplia, inoltre, la libreria di classi base con nuovi namespace e nuove classi, specifici per interfacciarsi alle nuove tecnologie.

Per sviluppare applicazioni basate su .NET Framework 3.0, come vedremo meglio tra breve, è ancora possibile utilizzare Visual Studio 2005 (e le relative edizioni Express). In questa serie di articoli, pertanto, impareremo le nozioni di base per utilizzare Visual Studio 2005 nel realizzare applicazioni basate su Windows Presentation Foundation (d'ora in poi definito anche WPF per brevità), la tecnologia di .NET 3.0 dedicata allo sviluppo di applicazioni dall'interfaccia grafica accattivante e dalle grandi potenzialità multimediali. L'argomento WPF è particolarmente vasto, pertanto con questi articoli ci proponiamo di imparare a muovere i primi passi in questo mondo, imparando anche i riferimenti alla documentazione per poter proseguire lo studio dell'argomento stesso.

Cosa occorre
Per lavorare con Windows Presentation Foundation, e più in generale con .NET Framework 3.0, occorre scaricare e installare i seguenti strumenti:

  1. .NET Framework 3.0 (non serve con Windows Vista);
  2. Windows SDK (contiene tutta la documentazione Microsoft su .NET Framework 3.0, esempi di codice, più alcuni utili strumenti eseguibili). Durante l'installazione, potete decidere di escludere la documentazione e gli strumenti per architettura Win32, se il vostro interesse è solo quello verso .NET Framework 3.0;
  3. Estensioni di .NET 3.0 per Visual Studio 2005, che vengono automaticamente installate anche per le edizioni Express e consentono di creare applicazioni WPF in maniera analoga a tutti gli altri tipi di progetto dall'IDE di Visual Studio.

Tutti i prerequisiti sopra citati sono gratuiti. Ciò significa che, se disponete delle edizioni Express di Visual Studio, avete a disposizione un ambiente di sviluppo estremamente potente e completamente gratuito. Non male, vero?

Windows Presentation Foundation
Windows Presentation Foundation è la nuova tecnologia realizzata da Microsoft, basata su .NET Framework 3.0, che permette la realizzazione di applicazioni dall'interfaccia grafica estremamente avanzata ed in grado di fare largo uso di elementi multimediali. WPF basa il suo intero funzionamento sulle librerie grafiche DirectX(r) di Microsoft, grazie alle quali è in grado di fornire allo sviluppatore anche il supporto per la grafica 3D e la grafica vettoriale. WPF costituisce il cuore della grafica in Windows Vista, pertanto potete ben immaginare quali siano le potenzialità offerte. La documentazione inclusa in Windows SDK è veramente completa al riguardo di WPF, oltre alla documentazione MSDN on-line. Inoltre, inclusi nella documentazione, ci sono numerosi esempi di codice che vi aiuteranno ad imparare questa fantastica tecnologia. In questa breve serie di articoli non potremo esplorare tutte le funzionalità e le caratteristiche di WPF, ma cercheremo di focalizzare l'attenzione sugli aspetti più importanti, in modo che possiate poi approfondire gli argomenti in maniera autonoma.

I nuovi modelli di progetto
Una volta installati tutti i prerequisiti sopra elencati, si può aprire Visual Studio 2005 e iniziare la creazione di nuovo progetto, mediante il comando Nuovo|Progetto del menu File. Come potete vedere, nella finestra Nuovo progetto sono presenti nuovi modelli, contenuti nella cartella .NET Framework 3.0:

Come potete notare, ci sono tre modelli di progetto per Windows Presentation Foundation e uno per Windows Communication Foundation. In particolare, i modelli di progetto per WPF sono i seguenti:

Iniziamo ad addentrarci in WPF, selezionando il modello Windows Application (WPF) e facendo clic su OK (il nome del progetto non ha importanza). Nell'esempio proposto ho utilizzato un progetto per Visual Basic, ma il linguaggio, in questo particolare frangente, non fa alcuna differenza. Dopo qualche secondo, l'IDE di Visual Studio 2005 si presenta come in figura:

L'aspetto dell'IDE è diverso in alcuni elementi, rispetto a quello cui siamo abituati nel realizzare applicazioni Windows Forms. Sulla sinistra abbiamo ancora la toolbox, che contiene i controlli utente utilizzabili in WPF e che è ancora possibile trascinare sulla finestra. Come vedremo nella seconda parte di questa serie di articoli, l'utilizzo dei controlli in WPF cambia rispetto a Windows Forms. Sul lato destro abbiamo la finestra Esplora soluzioni. Al suo interno, noterete due file, App.Xaml e Window1.Xaml. Come vedremo tra breve introducendo il linguaggio XAML, i file con estensione .Xaml rappresentano la parte grafica delle finestre (App.Xaml rappresenta alcune proprietà grafiche a livello globale di applicazione). La parte centrale dell'IDE è quella più importante. Nell'area superiore c'è il designer vero e proprio, ove è presente la finestra principale del nuovo progetto. E' ancora possibile ridimensionare la finestra utilizzando il mouse e, come detto, trascinarvi i controlli dalla toolbox. Si tratta di una versione avanzata del designer, rispetto a quello classico di Windows Forms.

Nell'area sottostante, una delle più importanti novità: l'editor di codice XAML, il nuovo linguaggio di markup di cui parliamo nel prossimo paragrafo.

Separazione tra designer e sviluppatore: il linguaggio XAML
Come abbiamo accennato all'inizio dell'articolo, uno degli scopi per i quali è stato progettato Windows Presentation Foundation è quello di consentire la realizzazione di applicazioni multimediali dall'interfaccia grafica accattivante, anche tramite grafica tridimensionale. Con Windows Forms, ogni aspetto dell'applicazione è gestito dallo sviluppatore tramite codice, anche quelli relativi alla parte grafica (immagini, video, grafica vettoriale), spesso con grandi sforzi.

In questa ottica, Microsoft ha proposto un'alternativa importante: la separazione tra la fase del design di tutta la parte grafica dell'applicazione e quello della sua gestione tramite codice. Il classico esempio didattico che si fa in questi casi, è quello del designer professionista che realizza l'aspetto estetico del programma e del programmatore, che interagisce con l'applicazione scrivendone il codice. E' con questo scopo che nasce un nuovo linguaggio di markup chiamato XAML (eXtensible Application Markup Language), un linguaggio di tipica derivazione XML, il cui scopo è quello di gestire esclusivamente l'aspetto grafico dell'applicazione. In questo modo, un grafico può utilizzare il programma di elaborazione immagini che preferisce e nel modo in cui è abituato, esportare il suo lavoro sotto forma di codice XAML e passare questo codice allo sviluppatore, il quale non dovrà fare altro che occuparsi di scrivere codice gestito che interagisca con l'applicazione vera e propria.

Sebbene in WPF sia ancora possibile trascinare i controlli dalla toolbox oppure crearli ed aggiungerli all'applicazione via codice, XAML è sicuramente il modo migliore per gestire la parte grafica, poiché consente, come vedremo negli esempi di codice, di impostare le proprietà dei controlli in maniera molto più approfondita, consentendo un controllo molto più sicuro su di essi. XAML ha struttura prettamente gerarchica. E' possibile, ad esempio, implementare un contenitore di controlli, al cui interno risieda un pulsante, al cui interno sia incapsulato un elemento multimediale per visualizzare un video, al cui interno siano dichiarati attributi per il disegno di un bordo intorno al video stesso. Per default, quando viene creato un nuovo progetto WPF, Visual Studio aggiunge automaticamente un contenitore Grid all'interno del codice XAML. WPF mette a disposizione una nutrita serie di contenitori (StackPanel, DockPanel, Viewbox, Canvas) e quello che utilizzeremo maggiormente negli esempi è lo StackPanel, che consente di visualizzare oggetti affiancati.

Quando si scrive codice XAML, il designer riceve le direttive e visualizza a video il risultato del codice. Nella pratica, però, questo non sempre avviene in tempo reale. Può essere necessario, dopo aver scritto codice XAML, fare clic sulla finestra (o sul controllo) visualizzata nel designer. In altri casi, qualora questo non sia sufficiente, è necessario avviare l'applicazione e poi chiuderla. Può anche capitare che, avviando l'applicazione, vengano visualizzati degli errori in fase di generazione nonostante non ci siano errori. Si tratta di piccole imperfezioni del designer integrato per WPF (nome in codice Cider) che verranno definitivamente risolte con il rilascio di Visual Studio 2008.

Come potete notare, Visual Studio propone un nome per la classe Window1, tramite la dichiarazione x:Class, e richiama alcuni schemi XML predisposti da Microsoft per la scrittura di codice XAML. A differenza di quanto avveniva in Windows Forms, in cui una finestra è un oggetto di tipo System.Windows.Forms.Control, in WPF ogni finestra è una classe che deriva da System.Windows.Window.

Poiché la pratica (e sbatterci la testa) è sempre il sistema migliore per imparare, iniziamo subito a vedere un po' di codice XAML, per capire meglio perché sia così importante (e preferibile) usarlo al posto del drag'n'drop dalla toolbox o impostando le proprietà dei controlli tramite la Finestra delle proprietà. Nell'editor di codice XAML, eliminate i tag e scrivete il seguente codice (sostituendo il nome del file logovbtt.gif con un'immagine che avete sul vostro pc):

<StackPanel>
  <Button Margin="46,75,47,81" Name="Button1">
    <Border BorderThickness="5" Height="70" Width="120" BorderBrush="Salmon" HorizontalAlignment="Center"
            VerticalAlignment="Center">
      <Border.LayoutTransform>
        <RotateTransform Angle="15" />
      </Border.LayoutTransform>
      <Image Source="logovbtt.gif" Height="60" Width="110" Stretch="Fill"\u160 ?=""/>
    </Border>
  </Button>
</StackPanel>

Il codice appena scritto, che commenteremo a breve, produce il seguente risultato:

Poiché XAML segue la sintassi tipica di XML, si possono paragonare gli elementi XML ai controlli e gli attributi XML alle proprietà dei controlli.
In questo esempio abbiamo inserito un contenitore di controlli nella finestra (StackPanel). Seguendo la logica gerarchica di XAML, all'interno del contenitore abbiamo inserito un pulsante per il quale le proprietà Margin e Name assegnano rispettivamente la posizione e un nome.
All'interno dell'elemento Button, abbiamo inserito un elemento Border.
Al suo interno, abbiamo inserito una immagine (elemento Image, la cui proprietà Source specifica il percorso del file). Le proprietà BorderThickness e BorderBrush permettono rispettivamente di specificare lo spessore e il colore del bordo. La posizione all'interno del pulsante viene specificata tramite le proprietà HorizontalAlignment e VerticalAlignment, i cui attributi Center stabiliscono la posizione al centro del controllo.
All'interno dell'elemento Border, l'elemento Border.LayoutTransform permette di specificare alcune impostazioni grafiche per il contenuto, in questo caso abbiamo specificato una rotazione di 15 gradi in senso orario (col segno "-" davanti si ottiene una rotazione antioraria).

Se provate a disegnare un controllo Button sulla finestra, trascinandolo dalla toolbox, vi renderete conto che è praticamente impossibile ottenere lo stesso risultato solo tramite mouse, perché la Finestra delle proprietà non vi consente di avere un controllo su tutti gli elementi che fanno capo al pulsante e che, via codice XAML, abbiamo inserito a livello gerarchico. Inoltre, l'utilizzo della toolbox non consente l'aggiunta di contenitori di controlli, che invece si rivelano molto utili. Un risultato del genere, nella fase di design con Windows Forms, è praticamente impensabile.

Anche se quello che abbiamo scritto è vero e proprio codice, è importante non confondersi le idee in questa fase. Il codice XAML scritto, infatti, non gestisce il funzionamento del pulsante ma ne cura l'aspetto grafico. Ecco, quindi, come XAML sia uno strumento fondamentale nel design di un'applicazione e dei suoi controlli. Molti programmi professionali di computer graphics sono già in grado di esportare il risultato delle proprie elaborazioni in formato XAML, onde consentirne il riutilizzo in Visual Studio. E questo, come detto, è il principale scopo che ha portato Microsoft a progettare XAML. Il pulsante così disegnato può essere poi gestito da codice, come vedremo in un prossimo articolo.

Vediamo ancora qualche code snippet. Questo:

<StackPanel>
  <TextBox Name="TextBox1" BorderBrush="Salmon" FontStyle="Italic" FontWeight="UltraBlack"
           BorderThickness="2" Text="Questa \u232 ? una TextBox in WPF" FontFamily="Courier New"
           FontSize="14" Foreground="White" Margin="10,10,10,10">
    <TextBox.Background>
      <RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
        <RadialGradientBrush.GradientStops>
          <GradientStop Color="Green" Offset="0" />
          <GradientStop Color="Blue" Offset="0.25" />
          <GradientStop Color="Yellow" Offset="0.75" />
          <GradientStop Color="Red" Offset="1" />
        </RadialGradientBrush.GradientStops>
      </RadialGradientBrush>
    </TextBox.Background>
  </TextBox>
</StackPanel>

produce il seguente output:

In pratica, abbiamo disegnato un bordo (BorderBrush e BorderThickness) intorno al controllo TextBox. Le proprietà del font sono impostate mediante gli attributi FontFamily (che corrisponde al nome del font), FontSize, FontStyle e FontWeight (quest'ultimo consente molte impostazioni sulla modalità grassetto del testo).
Il colore del testo si imposta mediante l'attributo ForeGround.
L'oggetto RadialGradientBrush consente di applicare un gradiente all'oggetto che lo racchiude all'interno dei propri tag, specificando le coordinate (GradientOrigin e Center) e lo spessore del raggio. I vari elementi GradientStop specificano il colore che assume la porzione di gradiente a partire dal punto percentuale specificato (Offset).

Il seguente code snippet:

<StackPanel>
  <Button Margin="10,50,10,50" Content="Clicca qui!" Foreground="White">
    <Button.Background>
      <LinearGradientBrush>
        <GradientStop Color="Yellow" Offset="0"/>
        <GradientStop Color="Red" Offset="0.5"/>
        <GradientStop Color="Blue" Offset="1"/>
      </LinearGradientBrush>
    </Button.Background>
  </Button>
</StackPanel>

produce il seguente output:

Tenete ancora nella dovuta considerazione la struttura gerarchica di XAML. In questo caso, abbiamo disegnato un pulsante di cui abbiamo impostato il testo (attributo Content) e il colore di primo piano (attributo ForeGround).
L'elemento Button.BackGround consente di specificare lo sfondo del controllo, pertanto al suo interno abbiamo utilizzato un elemento LinearGradientBrush che applica un gradiente al controllo con le modalità viste in precedenza.

Questi esempi non devono spaventarvi, poiché la documentazione MSDN fornita con Windows SDK è veramente esaustiva e comprende numerosi esempi di codice per il disegno dei controlli. Pertanto, in questa documentazione, troverete sempre un valido supporto allo sviluppo su WPF.

Con riferimento a XAML, invece, inizialmente il suo utilizzo può apparire macchinoso, soprattutto per chi è abituato a gestire tutti i controlli di un'applicazione tramite il consueto designer di Visual Studio per le applicazioni Windows Forms. Tuttavia, anche grazie all'inesauribile Intellisense di Visual Studio, che semplifica la scrittura di codice XAML, quando si prende più confidenza con questo linguaggio si riesce ad apprezzarne in pieno le funzionalità di disegno.

Modalità dichiarativa, modalità imperativa e i file di code-behind
L'introduzione di XAML, ha portato alla definizione di due modalità per la creazione di controlli. La modalità dichiarativa e la modalità imperativa. La modalità dichiarativa è quella in cui si scrive esclusivamente codice XAML, che definisce l'aspetto esteriore dei controlli ma che non ne gestisce il comportamento. La modalità imperativa, al contrario, è quella che si ottiene scrivendo codice managed in grado da un lato di disegnare i controlli (ove necessario), dall'altro di gestirne il comportamento.

Per scrivere il codice gestito di supporto, Visual Studio segue la logica dei file di code-behind. Per ogni oggetto di tipo Window, viene generato un file con estensione .Xaml. Per ognuno di questi file, Visual Studio genera "nell'ombra" un altro file con lo stesso nome, ma con estensione .vb o .cs a seconda del linguaggio prescelto. Se consideriamo il progetto creato all'inizio, per il file Window1.Xaml esisterà un corrispondente file chiamato Window1.Xaml.vb (o Window1.Xaml.cs). All'interno di questo file va implementato il codice necessario per interagire con l'applicazione e con i controlli. In questo articolo non faremo uso dei file di code-behind, ma inizieremo a vederli nella seconda parte. Intanto, però, impariamo come raggiungerli. Per visualizzare i file di code-behind, è possibile fare clic sul pulsante Mostra tutti i file della finestra Esplora soluzioni. Quando la struttura ad albero viene espansa, facendo clic sul segno "+" vicino a Window1.Xaml vedrete apparire anche il dipendente file Window1.Xaml.vb. Facendo doppio clic su questo file, sarete in grado di accedere al consueto editor di codice di Visual Studio e di digitare il codice di gestione vero e proprio.

XAML in anteprima: lo strumento XAMLPad
All'interno di Windows SDK è presente uno strumento molto utile, chiamato XAMLPad, raggiungibile dall'apposito collegamento nel menu Start|Programmi|Microsoft Windows SDK|Tools. XAMLPad consente di digitare codice XAML e di vederne l'anteprima in tempo reale, senza la necessità di avere Visual Studio in esecuzione. E' uno strumento molto valido per prendere confidenza con XAML, sebbene abbia il difetto (ma non si poteva pretendere troppo!) di non avere un intellisense integrato, pertanto tutto deve essere digitato manualmente, facendo attenzione al fatto che XAML è case-sensitive. A livello didattico, XAMLPad presenta un'altra importante funzionalità, che è quella di mostrare il cosiddetto Visual Tree. In WPF, il Visual Tree è la rappresentazione grafica della struttura gerarchica delle finestre (classi derivate da Window) e dei controlli che implementano (con relative proprietà e layout). La seguente figura mostra il risultato del primo code snippet scritto in XAML:

Ovviamente, potrete fare copia-incolla sul codice digitato in XAMLPad e riportarlo in Visual Studio, facendo attenzione al fatto che XAMLPad utilizza un oggetto Page al posto di Window. L'oggetto Page è tipico delle applicazioni XAML Browser Applications, che possono essere eseguite in un browser web.

Conclusioni
In questo articolo abbiamo visto cos'è WPF e abbiamo introdotto i rudimenti per utilizzare XAML, un linguaggio di markup molto potente e versatile. Avete appreso le conoscenze necessarie per poter sperimentare in maniera autonoma in attesa di vedere, nel prossimo articolo, come iniziare la realizzazione di un'applicazione WPF utilizzando congiuntamente XAML e codice gestito.
Per ulteriori informazioni potete contattarmi al mio indirizzo visitare il mio blog.