Blend 4’s new Model-View-ViewModel support


Sono da sempre un sostenitore di Blend e continuo a ritenerlo uno strumento indispensabile per chi sviluppa applicazioni WPF/Silverlight (ora dovrei forse anche aggiungere Windows Phone 7…) ovviamente ci sono delle funzionalità che dal basso della mia esperienza ho sempre ritenuto degli ottimi “tentativi” ma nulla di più: il caso più evidente sono i Design time data, ovvero la possibilità di definire dei dati disponibili a design time per facilitare il disegno della user Interface

image

Il motivo percui non ho mai preso in considerazione questa possibilità e facile da capire: Se i dati a runtime provengono da un modello, è con il modello che voglio interagire e non su una fantomatica entità che ne rappresenta una copia esatta perchè, proprio per il fatto di essere una copia, è abbastanza probabile che il modello e la copia finiscano per desincronizzarsi con tutte le problematiche del caso.
La necessità di avere dei dati a design time (a.k.a Blendability) è, e rimane, uno degli aspetti fondamentali per chi usa Blend, provate a editare un ItemTemplate senza Blendability e vi sfido a capire come apparirà il template a runtime.

 

Queste “lamentele” sono state riportate anche al team di Blend il quale, oltre a riconoscere il valore della Blendability ha capito che sempre più sviluppatori stanno usando Model-View-ViewModel non solo perchè è cool, ma perchè effettivamente funziona , ecco quindi che nella nuova versione appena rilasciata è stato introdotto direttamente in Blend il supporto ai design time data così come è giusto che sia, ovvero, usando direttamente il modello.

Se, come accade in applicazione MVVM, la MainPage deve essere associata al relativo MainPageViewModel:

image

Con la nuova versione di Blend quello che dobbiamo fare è semplicemente usare la nuova opzione: Create Object Data Source…

image image 

A questo punto, per collegare le proprietà del ViewModel agli elementi di UI non dobbiamo fa altro che trascinare la proprietà sull’elemento desiderato

image

Questo determina l’associazione a design time del relativo DataContext secondo la modalità che ho spiegato qui, visualizzando il contenuto nella nuova finestra DataContext che possiamo utilizzare anche per fare Drag-Drop delle  proprietà da collegare via dataBinding (se trascinate la proprietà nell’artboard vi viene generato direttamente il controllo)

 

 

image

Utilizzando questa modalita implica che, il fornire i dati a design time è delegato al ViewModel generando dei dati “dummy” quando viene istanziato a Design time.

Se non volete scrivere del codice per il supporto a design time esiste un alternativa altrettando valida che consiste nel selezionare l’opzione: Create Sample Data from class…

Dopo aver scelto la classe da usare come fonte dati, secondo una modalità analoga ai sample data già presenti in Blend dalla precedente version alle proprietà verranno dati dei valori autogenerati (che volendo potete anche configurare) e che vengono associati anche alle proprietà read-only.

image

 

 

Attenzione: L’opzione Create Object Data Source richiede che il modello/ViewModel esponga un costruttore pubblico senza parametri.

 

Visto che tutto questo avviene a design time rimane da capire meglio come associare View e ViewModel a runtime, se già usate MVVM questo sicuramente già lo sapete, ma con l’arrivo di MEF qualcosa mi dice che lo scenario andrà a modificarsi.

Stay tuned!

 

 

author: Corrado Cavalli | posted @ lunedì 15 marzo 2010 19.13 | Feedback (1)

The power of Behaviors in Model-View-ViewModel


Un applicazione WPF/Silverlight basata su Model-View-ViewModel è il risultato di un insieme di dettagli che fanno la differenza, ad esempio una delle cose che sto iniziando ad apprezzare e grazie al quale è possibile fare delle cose veramente carine con poco sforzo è il VisualStateManager (che in WPF 4.0 diventa parte integrante della piattaforma)
Prendiamo un caso molto semplice: Cambiare il colore di un rettangolo (ma la cosa potrebbe essere complessa a piacere) alla pressione di un tasto.
Usando Blend, definiamo due stati Normal e Fail e in ognuno di essi cambiamo il colore del rettangolo (Rosso=Fail, Verde=Normal) giocando eventualmente con transizioni, easing e tutto ciò che il VisualStateManager ci permette di fare.

image

A questo punto associamo alla nostra pagina un ViewModel che esporrà un comando ChangeStateCommand da associare ad un pulsante che aggiungeremo alla nostra pagina.

public class MyViewModel:ViewModelBase
{
   private string stateName;
   private bool isFailState;
 
   public MyViewModel ()
    {
      this.ChangeStateCommand = new RelayCommand(this.OnChangeState);
    } 
   
   public RelayCommand ChangeStateCommand { get; private set; }
 
   public string StateName
   {
      get {return this.stateName;}
 
      set
      {
         if (value != this.stateName)
         {
            this.stateName = value;
            this.RaisePropertyChanged("StateName");
         }
      }
   }     
   
   private void OnChangeState()
   {
      if (!this.isFailState)
         this.StateName = "Fail";
      else
         this.StateName = "Normal";
      this.isFailState = !this.isFailState;
   }      
}

image

A questo punto ci manca un dettaglio fondamentale: Come facciamo, a far cambiare di stato il VisualStateManager quando lo stato del ViewModel cambia? ovvero nel nostro esempio quando premiamo il pulsante…
Ci sono varie possibilità ma quella più comoda è sicuramente quella di ricorrere ad un Blend Behavior, ad esempio il GotoStateAction che permette di selezionare gli stati di un VisualStateManager

image

 

Trasciniamo due oggetti GotoStateAction sulla griglia che contiene il rettangolo e il button e impostiamo i relativi stati da selezionare:

image

 

A questo punto rimane un problema evidente, come faccio a comandare il behavior in base allo stato del mio viewmodel? se date un occhiata alla figura a fianco noterete che, by default, il GotoStateAction permette di mappare lo stato del VisualStateManager verso un evento, ma questo non è quello che vogliamo.

 

 

 

 

 

 

 

Come risolviamo il problema?: Creando un custom trigger bindato alla proprietà StateName del nostro ViewModel, trigger che potremo poi riutilizzare anche con altri behaviors nel caso ci faccia comodo.

Ecco il codice del Blend trigger:

public class StatePropertyTrigger : TriggerBase<DependencyObject>
    {
      public static readonly DependencyProperty BoundPropertyProperty =
          DependencyProperty.Register("BoundProperty", typeof(string), typeof(StatePropertyTrigger),
              new PropertyMetadata(new PropertyChangedCallback(OnBoundPropertyChanged)));
 
      public string BoundProperty
      {
         get { return (string)GetValue(BoundPropertyProperty); }
         set { SetValue(BoundPropertyProperty, value); }
      }
 
      public string Value { get; set; }
 
      private static void OnBoundPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
      {
         StatePropertyTrigger target = (StatePropertyTrigger)d;
         if (e.NewValue.ToString() == target.Value)
            target.InvokeActions(null);
      }     
    }

Il trigger ha due proprietà:

  • BoundProperty: E’ la proprietà del ViewModel che lo alimenta.
  • Value: Il valore da confrontare.

Quando il valore di BoundProperty è uguale a Value, l’azione associata viene invocata, nel nostro caso specifico l’azione è la GotoStateAction che seleziona lo stato del VisualStateManager.
Una volta compilato il progetto, in Blend è sufficiente selezionare “New” alla voce TriggerType e selezionare il nostro custom trigger StatePropertyTrigger.

image

Ora configuriamo le proprietà del nostro trigger, collegandolo alla proprietà StateName e impostando il rispettivo valore da confrontare, il tutto ripetuto per entrambi i GotoStateAction draggati in precedenza.

image

Fatto questo, la pressione del tasto, invocherà il Command esposto dal ViewModel che di conseguenza cambiera alternativamente il valore della proprietà StateName provocando l’intervento del trigger e la conseguente selezione dello stato.

Può a prima vista sembrare complesso, ma tutto quello che abbiamo scritto è completamente riutilizzabile in altre applicazioni e sopratutto va ad arricchire la library dei propri behaviors che, vi assicuro, fanno la differenza quando si realizzano interface utente “evolute”.

author: Corrado Cavalli | posted @ lunedì 8 marzo 2010 22.42 | Feedback (0)

MediaElement and Visual Tree


Sto lavorando su un applicazione Silverlight che, tra le varie funzionalità, deve eseguire il play di streams in formato .wma e per questo requisito la scelta cade automaticamente sulla classe MediaElement. Convinto della banalità della cosa ho scritto qualcosa tipo:

MediaElement me = new MediaElement();
me.Source = new Uri("http://thesite.com/stream.wma", UriKind.Absolute);
me.Play();

per scoprire che non funziona, ho quindi rimediato usando:

WebClient wc = new WebClient();
wc.OpenReadCompleted += (s, arg) =>
{
   me.SetSource(arg.Result);
   me.Play();
};
 
wc.OpenReadAsync(new Uri("http://www.thesite.com/stream.wma", UriKind.Absolute));

Il problema vero è nato quando ho cercato di regolare il volume, semplicemente agganciando uno slider alla proprietà Volume di MediaElement ovvero qualcosa tipo:

private void slider1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
  me.Volume = slider1.Value;
}

e qui non c’è stato verso di farlo funzionare.

Dopo svariate prove e successiva conferma da parte del team di Silverlight ho scoperto l’inghippo e quindi anche il motivo percui l’assegnazione dell’Uri allo stream non funzionava: Ogni MediaElement deve far parte di un Visual Tree.
Aggiungendo il MediaElement al visual tree oppure semplicemente definendo lo stesso direttamente via XAML sembra risolvere tutti i problemi, certo per questa particolare necessità (in questo caso non ho nulla da visualizzare) mi sembra di essere tornato ai tempi di VB6 dove le form erano piene di controlli invisibili a run-time, ma è pur vero che normalmente un MediaElement è spesso legato ad un video e quindi la presenza nella UI è più che normale.

Technorati Tags:

author: Corrado Cavalli | posted @ domenica 7 marzo 2010 8.01 | Feedback (0)

Visual Studio 2010 RC: Error adding a custom control


Dopo aver migrato dalla beta2 alla RC la mia installazione di Visual Studio 2010 mi sono accorto che ogni volta che cercavo di aggiungere un custom control ad un applicazione WPF o Silverlight l’operazione falliva col seguente messaggio:

image

Non è che aggiungo custom controls tutti i giorni, però questa cosa mi dava parecchio fastidio anche perchè aveva tutti i sintomi del problema legato a qualche “cadavere” rimasto dalla precedente installazione.
Fortunatamente grazie al supporto di due sviluppatori del team di Cider (thank you Zambho and Saurabh!) e qualche centinatio di mega di dump che hanno viaggiato dall’Italia a Redmond abbiamo scoperto la causa: Il plug-in Power Commands

image

è bastato disabilitarlo per risolvere il problema.

Nell’attesa che venga rilasciata la versione per la RTM, nel caso vi capitasse, ricordatevi di questo post.

Technorati Tags:

author: Corrado Cavalli | posted @ martedì 2 marzo 2010 21.58 | Feedback (0)

Free Windows7 Location Sensor


image Volete aggiungere alla vostra macchina Windows 7 un sensore di posizione senza necessariamente avere un GPS integrato? allora provate questo driver gratuito: Geosense for Windows.
Sebbene non precisissimo (almeno nel mio caso) è sicuramente utile per testare le nuove Location and Sensor API di Windows 7

Technorati Tags: ,

author: Corrado Cavalli | posted @ lunedì 1 marzo 2010 11.06 | Feedback (0)

WPF Toolkit February 2010 release


E’ stato rilasciata la nuove release del WPF Toolkit datata Febbraio 2010, oltre ai soliti fix da notare la presenza dei nuovi controlli AutoCompleteBox,Accordion e Rating il cui codice è condiviso al 100% con gli equivalenti in Silverlight, quale miglior segno di convergenza tra le due tecnologie?

Lo trovate qui: http://wpf.codeplex.com/releases/view/40535

Technorati Tags:

author: Corrado Cavalli | posted @ martedì 23 febbraio 2010 21.29 | Feedback (1)

Cosa vorreste avere in WPF 5?


Cosa vi piacerebbe avere nella prossima versione di WPF? dite la vostra votando qui: http://dotnet.uservoice.com/forums/40583-wpf-feature-suggestions
Visto che la stessa cosa è stata fatta con Silverlight 4.0 e gran parte delle richieste è stata soddisfatta vale la pena votare.

Technorati Tags: ,

author: Corrado Cavalli | posted @ domenica 14 febbraio 2010 18.58 | Feedback (1)

Visual Studio 2010 Release Candidate is here!


E’ disponibile sul sito MSDN Subscribers per gli abbonati, da domani per chi non ha un abbonamento.

 http://blogs.msdn.com/jasonz/archive/2010/02/09/announcing-vs2010-net-framework-4-release-candidate-rc.aspx

Technorati Tags:

author: Corrado Cavalli | posted @ martedì 9 febbraio 2010 6.37 | Feedback (1)

[Blend] Extract Template from a Style


Quando si usa la funzionalità Edit Template->Edit a Copy di Blend

image

Blend in realtà crea uno style che applica il template appena estratto.
Personalmente mi piace organizzare le risorse all’interno di resource dictionaries (styles.xaml, templates.xaml…) e, sebbene Blend permetta di specificare dove posizionare lo style il risultato è che style e template sono tutt’uno e spesso finisco per spostare il template nel relativo resource dictionary e linkarlo nello style via {StaticResource} manualmente.
Oggi, Laurent, mi ha indicato come fare il tutto direttamente da Blend: Mentre si è in modalità di editing del template, selezionate il simbolo dello style nell’elenco superiore:

image

dopodichè selezionate il property peg della proprietà Template e selezionate Convert to new resource

image

e decidete dove memorizzare il template. smile_regular

Technorati Tags:

author: Corrado Cavalli | posted @ giovedì 4 febbraio 2010 23.30 | Feedback (1)

WCF RIA Services=RAD 4 RIA


Ho appena terminato slides e demo per il “Community Tour” di martedì prossimo, l’argomento è tra i miei preferiti: WCF RIA Services non solo perchè li uso quotidianamente ma perchè è ormai una tecnologia della quale non riuscirei più a farne a meno sviluppando in Silverlight.

Se sviluppate applicazioni Silverlight (o pensate di iniziare a svilupparle) e ancora non li state usando, venite alla sessione, vi renderete subito conto di quello che vi state perdendo… smile_wink

CU There!

author: Corrado Cavalli | posted @ mercoledì 27 gennaio 2010 22.44 | Feedback (0)