Prism V2 – Drop 5 (Composite Application Guidance for WPF and Silverlight)

Today, we’ve released the fifth drop of the Prism V2 project. You can get it at: https://www.codeplex.com/CompositeWPF/Release/ProjectReleases.aspx?ReleaseId=19170 

 

New in this Drop

This iteration was a bit slower, due to the P&P summit (which was awesome btw). But we did get some nice things done:

  • Refactored some namespaces
    We had to refactor some namespaces, from Microsoft.Practices.Composite.Wpf namespace to Microsoft.Practices.Composite.Presentation. Most of prism is UI technology agnostic, so in V1, we put all WPF specific functionality in the .WPF assembly and Namespace. Now we need the exact same functionality in WPF and Silverlight, so calling it .WPF doesn’t make much sense anymore. This is a breaking change however.
  • ServiceLocator
    In Prism V1, we used our own IContainerFacade interface for DI. The idea was that you could implement a different DI container (IE: Castle Windsor) behind this facade. Now we’ve moved to the IServiceLocator interface, which is part of the CommonServiceLocator implementation (https://www.codeplex.com/CommonServiceLocator). This should make it a lot easier to use a different DI container, because we expect that adapters for different DI Containers will be created.
  • EventAggregator 
    We have ported the Event Aggregator from Prism V1 into Silverlight.  
  • Top Down Composition
    After a couple of excellent discussions with our advisors, we have changed our approach for top down composition. This drop contains first steps into the new approach.
  • Reference Implementation
    The reference implementation has been extended with several new modules. The new modules don’t show very much yet. We haven’t had time to include the new chart controls in the Silverlight Control Toolkit into the RI yet. Hopefully we can do this in the next drop.
  • Docs
    We’ve added & updated a whole bunch of topics to the documentation.

 

Event aggregator

The EventAggregator service is primarily a container for events that allow decoupling of publishers and subscribers so they can evolve independently. This decoupling is useful in modularized applications because new modules can be added that respond to events defined by the shell or, more likely, other modules.

This example shows how to define, consume and publish events:

    1: // **********************************************
    2: // Defining the Event payload
    3: // **********************************************
    4: public class TickerSymbolSelectedEvent : CompositeWpfEvent<string>{}
    5:  
    6: // **********************************************
    7: // Subscribing to the event from the consumers side
    8: // **********************************************
    9: public void Initialize()
   10: {
   11:    eventAggregator.GetEvent<TickerSymbolSelectedEvent>().Subscribe(ShowNews,
   12:                                                       ThreadOption.UIThread);
   13: }
   14:  
   15: public void ShowNews(string companySymbol)
   16: {
   17:    articlePresentationModel.SetTickerSymbol(companySymbol);
   18: }
   19:  
   20: // **********************************************
   21: // Publishing the Event
   22: // **********************************************
   23: EventAggregator.GetEvent<TickerSymbolSelectedEvent>().Publish(e.Value);
   24:  

The nice thing about the Prism EventAggregator that it is very loosly coupled, but still strong typed. We have now ported the Prism V1 Event Aggregator service to Silverlight.

 

Top down composition revisited

In Prism V2 – Drop 4, we introduced an Top Down composition implementation. In that implementation, you could define an interface on some kind of region. This would allow the region to resolve views based on this type, but also would provide a mechanism that would allow the hosting region to talk to the resolved view, through it’s well defined interface.

New design

We got quite a bit pushback on this model, because it somewhat broke the modularity concept. You have to know beforehand what kind of view gets loaded into the view and you have to define the views interface in a well known place.

So after a lot of discussions, we redefined our goals:

  1. We want to be able to pull views in, based on some well known piece of information. In bottom up composition, you are using region names for this.
  2. A hosting view typically has some context, that would be useful for any child views to know about. For instance, if you have a window to edit a customer, then dynamically loaded child views will likely be interested to know which customer is currently edited.

Now we are still in the middle of implementing this top down feature, but I would like to tell you a bit more about it.

RegionNames for topdown composition

So we agreed that we are already sharing a piece of information about the regions between the modules in bottom up composition: the Region names.

We have built a class where a module can register view types with region names, called the RegionContentRegistry. Whenever a region gets loaded, it will automatically ask the RegionContentRegistry for all viewtypes associated with it’s regionname. This will essentially create and pull the views into the region. This means you no longer have to explicitly find a region instance by name, create the view, and inject the view into the region.

This diagram shows how this model will look now:

image

In the red boxes, you can see that a module associates it’s views with a Region Name. The

This approach makes top down composition a lot easier than bottom up composition:

  • You’ll no longer run into timing issues where a region might not be created yet when a module wants to add it to a region.
  • Showing multiple instances of your region becomes a lot easier. For example, you want to show the same window twice. In this case, you no longer need to know about scoped region managers to find the specific region instance to inject your views into.
  • If you want, you can plug in more dynamic registration classes. For example, you could create a class that would read the registration data from an config file. In this config file, you would define which views (which modules) go to which regions.
  • You could query the RegionContentRegistry class. For instance, give me all the views associated with the ‘MainRegion’. You could bind a menu to this list. We are thinking of building some navigation logic (if we have time), that could tie into this registry.

 

Sharing Context

So the other goal was, to be able to share context. We are trying to create an attached property on a region, called RegionContext. A control that hosts a region can put whatever object it wants into the region context. This can either be a simple value (IE: CustomerID), a poco object, or a more complex controller. A control that gets pulled (or pushed) in the region can then decide if it wants to do something with this region context. Now this is a bit of an implicit model for injecting context into the views, but if you can make that implicit agreement, we think it can be very useful.

If you don’t like the implicit model, we are thinking about making the sharing of regioncontext a bit more explicit, but we haven’t decided yet what shape or form this should get.

Now you might argue, why are you not using the datacontext for this. In Silverlight, you probably want to put a Views ViewModel in the datacontext. But this is an internal implementation detail of a view. Any higher level controls shouldn’t know anything about this implementation detail, especially if the view comes from a different module.

 

What’s Next (Mini Roadmap)

So what’s next on our backlog?

  • Commanding.

    Silverlight doesn’t have nice support for Commands like WPF. So we want to provide some kind of mechanism that provides similar benefits but works both in WPF and Silverlight. We’ll keep you posted on how & what.

  • RegionContext
    The regioncontext doesn’t really work yet, so we’ll try to get it working during next interation.

  • Reference implementation
    Step by step we are recreating the reference implementation in Silverlight. Soon, we want to have it the same in WPF and Silverlight. But to do that, we have to have all of Prism 1’s functionality ported.

  • Navigation

    If we have time, we would like to look at some solutions for navigation in an app. We have some ideas around this, but feel free to give us your requirements!

As always, any feedback is welcome (and highly appreciated)

- Erwin