Confessions of a Dangerous Mind

Brain.FlushBuffer()
posts - 176, comments - 234, trackbacks - 93

WPF Prism Design Concepts Part 1: UI Composition

Prima di iniziare ad utilizzare Prism, conosciuto anche come Composite Application Library (CAL), ci sono dei concetti di design delle applicazioni che si possono realizzare che non possono assolutamente essere ignorati. Questi vanno sotto il nome di:

  • UI Composition
  • Modularity
  • Container
  • Multi Targeting

UI Composition

La “composizione dell’interfaccia” è uno degli aspetti chiave di Prism. Si basa su un concetto piuttosto semplice, ovvero che le applicazioni possono essere composte da diversi “moduli” che risiedono all’interno di zone predeterminate (View Composition). Questi moduli, poi, devono essere in grado di accettare comandi dall’esterno (Commanding) e comunicare tra di loro (Eventing). Questi tre concetti, uniti all’impiego del pattern Model-View-ViewModel, consentono di raggiungere l’obiettivo di avere delle applicazioni con interfaccia utente veramente flessibile e, soprattutto, indipendente dalla logica di business.

View Composition: Layout, View Discovery e View Injection

La prima cosa che viene in mente quando si progetta un’applicazione modulare è la gestione del layout. Prism permette di gestire il layout dell’applicazione utilizzando le innumerevoli possibilità messe a disposizione da WPF. E’ di fatto possibile creare addirittura layout “ricorsivi”, in modo da poter creare “regioni in regioni” nelle quali i moduli verranno caricati ricorsivamente. Il punto di forza di questo approccio è dato dal fatto che i moduli non devono sapere nè dove verranno visualizzati, nè come verranno visualizzati. Per quanto riguarda la collocazione delle view all’interno delle region che formano il layout, ci sono fondamentalmente due approcci: View Discovery e View Injection.

Con la view discovery, i moduli possono “registrare” delle views per essere ospitate all’interno di determinate regions. A run time, quando una determinata region viene mostrata, i moduli caricheranno in modo automatico la view di pertinenza della region. In questo approccio è quindi il registry delle views che preleva le views da mostrare, in un approccio View-First.

Con la view injection, invece, il modulo diventa responsabile della collocazione delle view all’interno della region. Questo approccio è più adatto se si pensa di utilizzare un approccio ViewModel-First piuttosto che View First per la gestione dell’interfaccia utente dei nostri moduli.

Prism mette a disposizione la classe RegionManager che funge da repository delle region della nostra applicazione, e l’interfaccia IRegion per modellare le region che ospiteranno delle views.

Commanding: Command Delegation e Command Composition

Il concetto di Commanding è estremamente importante, e può essere considerato un pilastro fondamentale della separazione tra logica ed intefaccia, implementato dai pattern MVVM e MVP. In WPF, infatti, a differenza di Windows Forms, è possibile fare il binding non solo dei dati, ma anche di comandi. Il concetto importante è rappresentato dal fatto che non è possibile utilizzare i comandi standard di WPF (RoutedUICommand) in CAL, in quanto questo tipo di Command necessita di EventHandlers (e quindi di Code Behind!!) e segue il Visual tree dell’applicazione. Per gestire i comandi in una “Prism-application” è necessario impiegare l’interfaccia ICommand e creare dei comandi custom per gestire l’input da parte dei componenti di interfaccia utente

I due concetti riportati nel titolo sono di importanza fondamentale nella realizzazione di una applicazione basata su CAL. Il primo concetto, la Command delegation, prevede che il codice eseguito da un comando sia contenuto in un metodo all’interno del componente di presentation logic, e quindi NON nel code behind della view. Questo approccio porta ad avere applicazioni che possono essere testate più facilmente, ma soprattutto mantiene separata la logica del comando dall’interfaccia che lo scatena. La classe del CAL framework che implementa questo concetto è la DelegateCommand<T>.

Il concetto di Command Composition è altrettanto importante, in quanto consente di “aggregare” comandi, in modo che un sono comando possa eseguire il codice di altri comandi. Lo scenario più comune per un comando di questo tipo è il “Save All” o il “Close all documents”. Anche questo concetto è implementato in CAL tramite la classe CompositeCommand.

Eventing: Event Services e Event Aggregation

In un ambiente fortemente disaccoppiato, come quello proposto da Prism, la gestione della comunicazione tra diverse parti dell’applicazione può divenire un problema. Non è possibile, infatti, utilizzare un Handler di un evento standard, in quanto quando stiamo realizzando un modulo non sappiamo neppure dove verrà inserito e se esiste un altro modulo che scatenerà l’evento per il quale ci stiamo registrando. E’ assolutamente necessario, quindi, implementare la comunucazione impiegando una soluzione di brokering che utilizzi il pattern Publisher/Subscriber.

Nella prima implementazione, Event Services, il publisher è implementato tramite un classe che solleva eventi standard .net. Ci sono dei contro nell’uso di questo approccio e sono rappresentati dal fatto che per aggiungere nuovi eventi si deve modificare l’interfaccia della classe, ed inoltre ogni sottoscrittore dovrà gestire manualmente il thread marshaling e la deregistrazione dall’evento.

Nell’implementazione Event Aggregation, viene utilizzato un Event Aggregation Service che funge da repository di eventi. Questi Eventi sono effettivamente dei delegates e quindi vengono immediatamente utilizzati e rilasciati, non soffrendo del problema della de-registrazione dell’evento tipica degli eventi .net. Inoltre viene getito in modo automatico anche il Thread-Marshaling, semplificando di fatto l’utilizzo degli eventi stessi. In pratica, un publisher seleziona uno degli eventi memorizzati nel repository e chiama il suo metodo Publish. Gli handlers dei sottoscrittori vengono invocati quando l’evento viene pubblicato da parte del publisher. In questo modo si viene a creare una infrastruttura di comunicazione estremamente flessibile che consente di creare moduli che si registrano su eventi gia documentati e presenti in altri moduli.

Questo conclude una overview del concetto di UI Composition. Nella prossima parte parleremo di Modularity. Nel frattempo invito tutti a scaricare e provare Prism. Lo potete trovare a questo link.

Print | posted on venerdì 17 luglio 2009 01:20 |

Feedback

Gravatar

# re: WPF Prism Design Concepts Part 1: UI Composition

Ottimo!
17/07/2009 01:37 | Leonardo
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET