Quando prendete confidenza con Wpf scoprite che, tra le tante cose, i template, gli stili e i trigger sono la manna dal cielo.
Quando però approcciate lo sviluppo di un’applicazione complessa, che magari vuole anche usare M-V-VM, anche mettendoci tutta la buona volontà scoprite che il design della UI diventa una delle attività più onerose e time consuming nel ciclo di sviluppo. Il motivo è presto detto:
  • Se usate come designer Visual Studio (aka Cider) avete l’inghippo che:
    • Definirlo stabile è difficile ;-)
    • Non c’è mezzo di editare in maniera visuale i template;
    • Non c’è alcuna possibilità di avere una preview dei dati che a runtime andranno in binding con la UI;
    • Avete però un ottimo intellisense anche per l’editing dello xaml;
  • Se usate Blend 2 siete invece in una condizione per cui:
    • Non avete supporto dell’intellisense, se non con qualche barbatrucco, per l’editing diretto dello xaml;
    • Avete però un ottimo designer con la possibilità di editare anche i template;
    • Avete purtroppo un supporto moltissimo-parzialissimo per il binding dei dati a design-time. La cosa è talmente scomoda, debole e prona ad errori che lasciate perdere pressochè subito… ;-)
L’accoppiata dei 2 non è certo comoda e non allevia le nostre sofferenze… finchè non diamo un’occhiata come si deve a Blend 3.0 (in CTP e scaricabile da qui)
Ignorable
Prima di approfondire vediamo una cosa che Blend ha/fa da sempre, rispetto a Visual Studio, e che è la base di tutto:
image
Blend, come designer, ha il supporto per un set di attached properties che possono essere piazzate sui controlli e che servono per aggiungere comportamenti a desing-time, come ad esempio il concetto di IsLocked:
image
Il bello è che le proprietà vengono bellamente ignorate a run-time permettendo di fatto di avere comportamenti diversi a design-time… interessante! Quindi questo cosa farà?:
image
SampleDataSource
ndr: Sto ancora facendo esperimenti quindi non ho spinto Blend verso lo spazio profondo ;-), ma per ora promette molto e molto bene.
Andiamo per gradi, diciamo che il nostro obiettivo è di realizzare una ListBox “custom” dove la cosa “custom” sono i ListBoxItem e i dati che vanno in pasto alla ListBox provengono da un ViewModel.
Gironzolando per Blend troviamo una “nuova” Tool Window: Data, interessante per noi è la possibilità di aggiungere una nuova “Sample Data Source…”, sia apre una dialog che ci permette di definire il nome (la resource key) da assegnare alla data source e se vogliamo persistere al nuova data source a livello di Window o di Application
image
Una volta fatto questo possiamo definire un set di proprietà che la nostra sorgente dati espone, a noi fondamentalmente interessano solo i nomi delle proprietà e parzialmente, almeno per ora il tipo. Se vogliamo quindi realizzare un potenziale master-detail lo possiamo fare in questo modo:
image
SelectedPerson non è di certo di tipo Person ma è piuttosto un ComplexType noto a Blend, ma o noi poco importa perchè l’essenziale è che possiamo scrivere, nello xaml, questo:
image
Notate il prefisso “d” davanti a DataContext? quel DataContext verrà utilizzato solo a design-time e ignorato a runtime permettendoci di specificare un’altra proprietà DataContext con la binding expression che dovrà essere utilizzata a runtime.
A mano fortunatamente dobbiamo fare ben poco, fa tutto il buon Blend; ora possiamo “draggare” una ListBox sulla nostra Window e dalla consueta finestra dei binding selezionare tutto quello che più ci piace:
image
producendo una cosa di questo genere:
image
Adesso possiamo metterci a lavorare al nostro template, sempre tutto da designer, e dopo avere realizzato un semplice template vedere direttamente a design-time questo:
image
Senza aver scritto un solo pezzetto di xaml a mano. Molto bene, direi che è un gran bel passo in avanti verso qualcosa di concreto e produttivo.
Ma non è tutto oro ciò che luccica… purtroppo!
…e voi direte: che barba che noia , non gli va mai bene nulla :-) nulla di più falso stavolta: quello che abbiamo visto è decisamente potente e flessibile quanto basta per fare il 90% delle cose (se non di più), essendo però “qualcosa” generato da un designer soffre del problema di non poter fare tutto, come ad esempio gestire tipi enumerativi cosa che io personalmente espongo molto volentieri dai miei ViewModel…
It’s a kind of magic
Se andiamo a sbirciare nello xaml scopriamo che non c’è nessuna magia dietro quello che fa Blend, anzi c’è un sacco di tecnologia molto nota :-)
Quando usiamo il designer delle Sample Data Source viene creata una cartella SampleData nel progetto e per ogni Data Source una sotto cartella nella queale trovano posto 3 file:
  • SourceName.xsd: definisce la struttura dei dati, è a tutti gli effetti il file che disegnate con il designer;
  • SourceName.xaml: contiene i valori dei dati che verranno assegnati alle istanze delle classi definite in:
  • Sourcename.xaml.cs: in cui vengono generate, direi a naso da un T4 template, le classi sulla base di ciò che avete disegnato nell’xsd;
Il tutto viene poi esposto al vostro mondo come risorsa nel file App.xaml.
E’ quindi facile fare una semplice prova replicando la situazione, fregandocene del file xsd, e costruendo la classe dei dati come meglio crediamo e scoprendo che possiamo usare quella perchè Blend la digerisce senza battere ciglio, mettendoci quindi tutti i tipi che vogliamo noi! :-) naturalmente perdiamo il supporto per il design della SampleDataSource ma direi che questo è il minore dei mali. Probabilmente smanettando un po’ con l’xsd si potrebbero fare cose decisamente interessanti mantenendo il supporto per il design anche della DataSource.
.m