With the advancement in the Silverlight technology starting with the 1.0 release to 2.0, 3.0, and lately 4.0, Silverlight is loudly saying WOW “Watch Out World.” Can you guess which world I am talking about here? It is the RIAs world! Really WOW!

All the features already delivered in Silverlight or on their way to be released are great and you can use them out of the box in your applications. What applications am I talking about? For sure, simple applications-those that cannot be tested with Unit Testing, have a single UI containing all features, have their UI holding all the driving logic, and were developed as one big chunk of code mixing together all functionalities hence tightly coupling the code. Consider larger Silverlight applications:

  • What happens when your application starts growing?
  • What happens when you have to extend an application with additional features?
  • What happens when the developer and the designer have to work side by side on the same application when the application fills the UI with application logic with no means of separation of concerns?
  • What happens when you want to employ unit testing for the application?

The above is just a sample of questions you start asking yourself when you start developing large-scale Silverlight applications.

One way to mitigate the problems mentioned above is to follow proven design patterns that have helped solve so many software-oriented problems over the years. One pattern that best suits Silverlight or WPF development is the MVVM, model view view-model design pattern.

The MVVM helps in the separation of concerns between the UI design of the application (View), the behavior (View-Model) of the UI, and its interaction with the data source (Model).

The MVVM helps in the separation of concerns between the UI design of the application (View), the behavior (View-Model) of the UI, and its interaction with the data source (Model).

M is the model or data source where data comes into the application. V represents the View where the layout of the applications is defined. VM encapsulates the UI behavior and plays the role of the “link” between the V and the M so that data coming from the model gets bound to the UI controls displayed by the application. Shawn Wildermuth has an informative article on how MVVM applies to Silverlight that you can read by following this link: Model-View-ViewModel in Silverlight 2 Apps (http://msdn.microsoft.com/en-us/magazine/dd458800.aspx).

MVVM helps to improve the architecture of the application mainly by allowing separation of concerns in terms of source code and UI design and making sure the source code fits for unit testing. However, it does not satisfy the requirements of large-scale applications. This is where third-party libraries like the Composite Application Library (Prism), developed and maintained by the Microsoft Patterns and Practices team, helps in building robust and well-organized Silverlight business applications.

Throughout this article, I will uncover the details of Prism and I hope it will help you start designing your Silverlight applications, taking into consideration whatever Prism offers you to build robust, fast, and maintainable solutions.

Composite Application Library (Prism)

Prism is a mixture of both development guidance and framework published by the Microsoft Patterns and Practices team to help developers build modular, loosely coupled, and multitargeted code applications in both Windows Presentation Foundation (WPF) and Silverlight technologies.

To cater to the ongoing changes in a growing application without affecting existing features, Prism promotes the use of modules to split the application into logical units where each unit is independent of the rest of the modules in the application. Hence, changing one module has no effect on the rest of the modules in the application. Prism provides the infrastructure to create modules and load them into the application.

When it comes to loading modules, Prism provides two ways to do so. One is to load the module upon application loading. The other option is to load the module on demand.

For instance, if your application has a module that presents reports to be viewed by managers at the end of each month, then there is no use in loading the reporting module whenever the application is loaded. A better solution is to go to the server whenever the reporting module is accessed by a manager and download it before it is viewed. This is an efficient technique that minimizes the time needed to load the application.

When developing a module it is important to remember the following:

  1. Modules should not add references to other modules, hence tightly coupled modules are not recommended.
  2. Modules should focus on a single or set of related functionalities.
  3. Modules should communicate between each other in a loosely coupled fashion.
  4. Each module should load its own views.
  5. Modules should not manage their dependencies. Prism helps in this by making use of the Dependency Injection (DI) pattern.
  6. There are other features that modules should have which you can read about in more detail in the documentation that accompanies Prism libraries.

A major architectural decision to be made when developing a new module is to make sure the module manages its own view components. This means when a module is loaded it also loads a certain view, or UI component, into the main application. In this way, each application is a collection of composed views that are loaded by each module initialized. Hence the concept of UI composition that Prism supports. When you develop an application in Prism, you mainly start by defining a Shell component. Think of the Shell component as the Master Page in ASP.NET. The Shell contains placeholders, named regions, the same as Master Pages contain ContentPlaceHolders. At run time, certain content will be loaded into those dynamic placeholders and there you will get a composed UI from several places.

In Prism, you define a Shell component, representing the application’s visual appearance, with run-time-loaded placeholders, or regions. Each module when loaded must register its views, which are nothing but UserControls, to specific pre-defined regions on the Shell. When the application loads, Prism also loads modules registered to be loaded at application startup. Once Prism loads a module, it loads the views registered with regions and places each in its proper position on the Shell. Therefore Prism not only supports functionality composition, but also UI composition where each module is responsible for its own functionality or set of features together with managing the UI that presents the functionality to the users.

Prism provides two techniques to register views to regions: View Discovery and View Injection. The former maps a view to a region name so that when the region loads, it dynamically queries an internal service inside Prism to detect what views are mapped to it and loads them on the spot. On the other hand modules making use of View Injection dynamically add views’ instances to regions. Based on your requirements, you can make use of those two techniques provided by Prism.

Another major feature to be considered when developing modules in Prism is that modules should be loosely coupled. At the same time they need a way to communicate or interface between each other. Luckily Prism provides Event Aggregation that allows modules to publish and subscribe to events. Consider a simple application where you have two modules: the List of Employees module and the Employee Details module. The two modules are totally isolated from each other; the only way they communicate is through an event “published by” the List of Employees module when an employee is selected, and “subscribed to” by the Employee Details module. When the Employee Details module is first loaded, it automatically subscribes to the well-known and agreed-upon event by the List of Employees module. Therefore, when the event is fired upon the selection of an employee, the event handler that was registered by the Employee Details module at load time will be fired. This way, the two modules communicate in a very loosely coupled fashion without having to know any details about each other.

Prism provides two techniques to register views to regions: View Discovery and View Injection.

Moreover, I mentioned above that modules should not manage their own dependencies. Consider for example a module that needs to connect to a Web Service that is a common data source to the application being developed. The module has the option to use either of the following two techniques:

  1. Add a Web Reference to that Web Service to create a local proxy instance.
  2. Let Prism provide a proxy instance.

Assume your application is composed of several modules that require access to the same Web Service, and in each module you need to repeat the same steps to add references to that Web Service. This is complex and requires lots of work by the module itself.

What if Prism can provide each module a proxy instance to connect to that Web Service?

Then each module will not bother managing a reference to the Web Service and will not worry, for example, if the address of that Web Service has changed. Prism makes use of DI containers to manage and provide dependencies to modules instead of having those modules manage their dependencies on their own. Prism also makes use of DI containers to inject dependencies to classes that are not bound to a specific DI container. On the contrary, Prism employs Service Locator, another component provided by the Patterns and Practices team, to generically wrap any container used. It also ships with a single Service Locator that wraps the Microsoft Unity container.

Back to the example, the Shell application creates and manages a proxy to the Web Service in question, and then registers that instance with the container as a singleton instance. Therefore the proxy instance is now accessible to any module in the application where a module can resolve that instance and use it. One requirement though is that each module must request an instance of the Container service as one of the parameters of the module definition class constructor.

One last feature to cover is the perfect support for developing Silverlight applications based on the MVVM and Presentation Model design patterns. These design patterns focus on the separation of concerns between the XAML, representing the UI, and its behavior and state. Hence, the functionality of a view is now grouped into the ViewModel class that is married to the Data-Context of the view. In addition, following one of those design patterns, especially MVVM, allows you to write clean and well-separated code available for unit testing.

Having this brief overview on Prism, it is time to start seeing how these concepts get implemented by code.

Prism in Code: A Practical Walkthrough

Prism adds the Command feature that is missing from Silverlight 3 and still a primitive feature in Silverlight 4. By a Command feature I mean the ability to fire a command on the UI and have the event handler for that command be defined in a location other than the code-behind of XAML. For instance, in terms of MVVM, the view will define the command to be fired when a user clicks the Button control on the view. Once clicked, the event handler for that command is fired in a method defined inside the ViewModel class. Following the MVVM design pattern helps in having a developer and designer both working on the same screen, where the developer is writing code to handle the state and behavior of the UI that is being constructed by the designer using XAML.

Following the MVVM design pattern helps in having a developer and designer both working on the same screen.

Bootstrapper

In a typical Silverlight application, the App class represents the root class of the application and it is the one responsible to show the main visual layout of the application. To do so, it makes use of the App_Start event defined within the App.xaml.cs class in any new Silverlight application that you create:

public partial class App : Application
{
    public App()
    {
        this.Startup += this.Application_Startup;
        …
    }
    private void Application_Startup(object
sender, StartupEventArgs e)
    {
        this.RootVisual = new MainPage();
    }
}

The Startup event handler simply creates a new instance of the MainPage class, representing the MainPage.xaml file that gets created with each new Silverlight application and assigns it to the RootVisual of the application. Hence, when the application loads, it automatically displays the MainPage as the main UI of the application.

Prism integrates itself into the Silverlight application by defining a Bootstrapper class. The Bootstrapper controls the startup behavior of the application by defining all the services and infrastructure that belong to Prism and at the same time, creates the Shell and sets the RootVisual. Therefore, it is through the Bootstrapper that Prism gets the chance to define and initialize itself before any UI is sent back to the end user.

Prism ships with the UnityBootstrapper base abstract class that registers the entire infrastructure of Prism for an application in a sequence of configuration calls that are to be discussed below. The class is named after the Unity container, which is another component provided by the Patterns and Practices team. The class is located in the Microsoft.Practices.Composite.UnityExtensions assembly and initiates an implementation of the IServiceLocator interface. It is this implementation that makes Prism independent of the DI container being used. The Service Locator is another component provided by the Patterns and Practices team that adapts any DI container and makes access to it generic so that the DI container could be easily replaced with any other container without changing a single line of code in the application. This is the case of Prism libraries that access the services defined in the container through the Service Locator and not directly through an instance of the Unity container. To adapt Prism to any other DI container, all that you have to do is provide your own implementation of the Bootstrapper based on your choice of DI containers currently available.

The default Bootstrapper contains several major components that I will cover in detail. Now that Prism is being used in the Silverlight application, the first step is to create a new Silverlight application, called the Bootstrapper application, and then add a new class to it that inherits from UnityBootstrapper:

    public class Bootstrapper : UnityBootstrapper
    { … }

The major methods that the UnityBootstrapper base class implements and exposes for inherited classes to override are shown below in the order they are executed:

  1. ConfigureContainer()
  2. GetModuleCatalog()
  3. ConfigureRegionAdapterMappings()
  4. RegisterFrameworkExceptionTypes()
  5. CreateShell()
  6. InitializeModules()

The two methods that you must override are the GetModuleCatalog() and CreateShell() methods.

ConfigureContainer() method

Once you have created the Unity container, it is time to configure the container by registering all the services used by Prism as resolvable types of the Unity container. Services include IServiceLocator, IModuleInitializer, IModuleManager, IRegionManager, etc. To get the details of the ConfigureContainer() method, simply refer to the Composite Application Library source code inside the UnityBootstrapper class located in the Microsoft.Practices.Composite.UnityExtensions assembly. This method is internally called when the Bootstrapper runs and gives the inheritor the opportunity to override it to register additional custom services into the Container to be accessible by the rest of modules in the application:

        protected override void
ConfigureContainer()
        {
            // Important to call base method to
            // load services used by Prism
            // globally
            base.ConfigureContainer();
            // I can register additional services
            RegisterCustomServices();
        }
        private void RegisterCustomServices()
        {
            Container.RegisterType<IMyService1,
Service1>(new
ContainerControlledLifetimeManager());
            Container.RegisterType<IShellView,
ShellView>();
            Container.RegisterType<
IShellViewModel,
ShellViewModel>();
        }

The first service has been registered as a singleton service using the ContainerControlledLifetimeManager class. The second two registrations simply register a direct implementation of two interfaces with the container that are to be used later on.

GetModuleCatalog() method

Not every simple Silverlight application requires the use of Prism. Prism is best utilized when you are developing a medium to large application where more than one module is to be developed and be part of the application. To let Prism load the modules for the application, you have to inform Prism of those modules ahead of time. Hence, the implementation of this method in the application-specific Bootstrapper becomes a must do. There are several ways for loading modules in Prism:

  1. Add a reference to each module into the Bootstrapper application.
  2. Load modules from a XAML file added to the Bootstrapper application as a Resource file containing definitions of each of the modules to be loaded.
  3. Load modules from a XAML file located at a remote location containing definitions of each of the modules to be loaded. Refer to the source code for a demonstration on this option.

Obviously the first option is limited and doesn’t fit into the nature of Prism applications, where each module has to be referenced by the Bootstrapper application which increases the startup loading time for the application. On the other hand, the second option is more dynamic where no hard-coded references have to be added into the application. Example of the second option is as follows:

        protected override IModuleCatalog
GetModuleCatalog()
        {
            return ModuleCatalog.CreateFromXaml(
                new Uri(
"/MyApplication.UI;component/ModulesCatalog.xaml",
                    UriKind.Relative));
        }

The sample code above makes use of the CreateFromXaml() method defined on the ModuleCatalog class of the Prism infrastructure to load the contents of a XAML file listing the definitions of all modules to be loaded into the application. The method returns an instance of ModuleCatalog in terms of the IModuleCatalog interface.

The third option is the most flexible and dynamic way of loading modules into the application without the need to recompile for the changes to take place. A XAML file could be easily stored on the server containing the definition of all the modules to be loaded. The file’s contents could be changed at any time during the application lifetime without having to impose any change into the application. All changes would take effect the next time the application is visited by the end user.

The ModuleCatalog.xaml file can be something similar to the following:

<?xml version="1.0" encoding="utf-8" ?>
<Modularity:ModuleCatalog
    xmlns=
"http://schemas.microsoft.com/winfx/2006/
xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/
2006/xaml"
    xmlns:sys="clr-namespace:
System;assembly=mscorlib"
    xmlns:Modularity="clr-namespace:
Microsoft.Practices.Composite.Modularity;
assembly=Microsoft.Practices.Composite">
    <Modularity:ModuleInfo
        Ref="Module1.xap"
        ModuleName="Module1"
        ModuleType=
"Module1.ModuleDefinitions.Module,
Module1, Version=1.0.0.0">
    </Modularity:ModuleInfo>
    <Modularity:ModuleInfo
        Ref="Module2.xap"
        ModuleName="Module2"
InitializationMode ="WhenAvailable"
        ModuleType=
"Module2.ModuleDefinitions.Module,
Module2, Version=1.0.0.0">
        <Modularity:ModuleInfo.DependsOn>
            <sys:String>Module1</sys:String>
        </Modularity:ModuleInfo.DependsOn>
    </Modularity:ModuleInfo>

Two modules have been defined where Module2 depends on Module1. It is important to mention that any module defined has the “WhenAvailable” value set for the InitializationMode property by default. This property has two possible values:

  1. WhenAvailable
  2. OnDemand

The former tells Prism to load the module on application startup while the latter loads the module when Prism is requested to do so during the lifetime of the application. This is the power of Prism in providing modularity into Silverlight applications by building loosely coupled modules that are loaded based on the requirements of the applications.

ConfigureRegionAdapterMappings() method

The ConfigureRegionAdapterMappings() method plays a major role in the initiation of the Bootstrapper in registering adapters for Silverlight controls to enable them to be placeholders for views displayed by the application. It is rarely overridden in an application since Prism provides major region adapters out of the box including controls that inherit from the following:

  1. Selector
  2. ItemsControl
  3. ContentControl

Whenever you want to provide a new adapter, you need to override this method and register a new region adapter mapping.

A Shell in Prism resembles Master Pages in ASP.NET apps.

RegisterFrameworkExceptionTypes() method

The RegisterFrameworkExceptionTypes() method is internally called during the initiation of the Bootstrapper to register Prism-specific exception types. You can register any additional exception type to be used globally among the modules in the application at this stage.

CreateShell() method

The CreateShell() method is the second method that you must override that is responsible for creating the Shell component and setting it to the RootVisual of the application:

        protected override
            DependencyObject CreateShell()
        {
            // Get the types
            IShellView shellView =
Container.Resolve<IShellView>();
            IShellViewModel viewModel =
Container.Resolve<IShellViewModel>();
    
            // Marry them
            shellView.ApplyModel(viewModel);
    
            App.Current.RootVisual = shellView;
            return shellView;
        }

The method above creates an instance of the ShellView component, sets the DataContext property of the ShellView to an instance of ShellViewModel, depicted in the ApplyModel() method implemented by the ShellView, sets the application’s RootVisual to the ShellView and finally the ShellView is returned back as a return value of the method.

InitializeModules() method

The InitializeModules() method is called internally during the Bootstrapper initiation to load all the modules that have been registered in the application. Typically, all modules defined with the ModuleInfo’s InitializationMode property set to “WhenAvailable” will be loaded. Once all modules are loaded and initialized, the Shell component is shown and displayed.

Now that the Bootstrapper is done, it is time to flip into the App class of your application and specifically to the App’s Startup event handler to do the following changes:

        private void Application_Startup(
object sender, StartupEventArgs e)
        {
            Bootstrapper boot = new
Bootstrapper();
            boot.Run();
        }

Instead of directly setting the RootVisual to a XAML page instance, the code above creates a new instance of the Bootstrapper and calls the Run() method on the Bootstrapper, which starts its functionality in the order that has been listed and explained above.

Now that you know the GetModuleCatalog() method inside the Bootstrapper is forced to return a populated ModuleCatalog object containing all the module definitions to load, it makes sense that you should run an asynchronous call to deploy the ModuleCatalog.xaml on the server as the most dynamic and efficient way of providing module definitions to an application. The asynchronous call should be in the first line of the Application’s Startup event handler to load the ModuleCatalog.xaml file from the server. Then, once the Completed event handler receives a response, the application now has access to all module definitions to be loaded. You can now create a new instance of the Bootstrapper and call its Run() method to initialize it.

UI Composition

In terms of Prism, the Shell component contains the visual elements that constitute the visual layout of the application. You do not need to have a Shell component in the application; however, it is good practice to identify a main Shell composing the visual layout of the application. You can do this by grouping together views from the different modules loaded into the application into a single view displayed to the user, hence the UI composition!

The reasons behind using a Shell in a Silverlight Prism-enabled application are the same as those when using Master Pages in ASP.NET.

The Shell component defines locations or placeholders known as regions in Prism terminology. Each module that gets loaded into the application and has a view to show can simply register its views with the regions defined on the Shell. The Shell automatically manages those views and displays them.

Out of the box, Prism adapts several Silverlight controls to enable them to be used as regions to hold views. For instance, if you need a control to hold only one view at a time, then go for ContentControl. Prism defines an adapter for any control that inherits from this control. If you want to display several views together in one region (or UI area), then go for ItemsControl. If the region adapters defined by Prism are insufficient, then you can define your own region adapter for the control you want.

Prism enables defining regions in XAML through the use of an Attached property on the RegionManager class that is included as part of the Prism library. A sample on how to define regions inside the Shell UserControl or any other view is as follows:

<UserControl x:Class="MyApplication.Shell"
    xmlns=
"http://schemas.microsoft.com/winfx/2006/
xaml/presentation"
    xmlns:x=
    "http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ctls="clr-namespace:
    System.Windows.Controls;assembly=System.
    Windows.Controls"
    xmlns:rgn="clr-namespace:
    Microsoft.Practices.Composite.
    Presentation.Regions;
    assembly=
    Microsoft.Practices.Composite.Presentation">
    <Grid>
        <ContentControl
            rgn:RegionManager.RegionName
            ="MainRegion"
            HorizontalContentAlignment="Stretch"
            VerticalContentAlignment="Stretch">
        </ContentControl>
    </Grid>
</UserControl>

Notice the use of the RegionName attached property on the RegionManager class to define a new region inside the Shell designating the ContentControl as a placeholder to host a single active view at a time.

Throughout the article, the word view has been excessively used. Views are nothing but DependencyObject classes. For instance, UserControls are the best candidates when it comes to defining views for the application.

When discussing UI Composition, Prism provides two ways of adding views to regions: View Discovery and View Injection. You can read in detail about these two techniques in the Prism documentation; however, briefly they can be defined as follows:

  1. View Discovery: Is a technique used to map a view to a region. This technique doesn’t provide much control on how the view is being loaded inside the region. Simply, you map a view to be displayed in a certain region. Once the module hosting that view gets loaded, Prism automatically discovers the views mapped to regions on the Shell component to display them. You can map a view to a region by either using the type of the view or by using a delegate:

Using the Type

            IRegionManager regionManager =
Container.Resolve<IRegionManager>();
            regionManager.RegisterViewWithRegion(
"MainRegion", typeof(MyView));

Using a Delegate

            IRegionManager regionManager =
Container.Resolve<IRegionManager>();
            regionManager.RegisterViewWithRegion(
"MainRegion", () => Container.Resolve<IMyView>());

This technique is best used with views that need only to be loaded once into the Shell and remain there throughout the application lifetime, i.e., static views.

  1. View Injection: This technique gives you more control on when to inject the view into a region. You can add/remove views from any defined region in the application. Typically this technique is best used in master/detail scenarios or when implementing a screen-based application where clicking a menu item loads a new view into a region on the Shell:
         // Get a reference to the main region.
         IRegion mainRegion =
         _regionManager.Regions["MainRegion"];
    
         // Create the view if we need to.
         object view = mainRegion.GetView(
         viewName );
         if ( view == null )
         {
             // Resolve the view
             view = this.
             _container.Resolve<IMyView>();
    
             // Add the view to the main region
             mainRegion.Add( view, viewName );
         }
    
         // activate the view.
         if ( view != null )
         mainRegion.Activate( view );

This is in brief how UI composition works in Prism. A Shell component is defined with several identified regions, ready to hold views. Each module loaded registers its own views with the regions on the Shell. Finally, the Shell component composes its layout from the different views registered by modules.

Modularity

A module is defined as a functional unit in the application representing a collection of features, components, and resources. One of motives behind using Prism is the capability to modularize a Silverlight application by allowing the application to load its main interface with just enough functionality to make it work. Later on, when a module is requested that has not been loaded at startup time, a service is present to locate the module’s .XAP file on the server, download it, and initialize it. This technique allows you to break down your application into smaller functional units. Each unit is responsible for certain functionality in the application and its loading is governed by the application’s business logic. Hence, the smallest functional unit of work in a Prism application becomes the module. It is through the technique of developing modular applications that Prism promotes application extensibility (in the sense that each new set of requirements could be grouped into a module that gets loaded into the application without having to change the existing requirements). Further, a major advantage of writing such modular applications lies in the fact that a module can be developed and tested separately from the application, which again conveys the idea that Prism supports extensible applications.

When creating a new Prism module it is important to create new Silverlight Application project and not a Silverlight Class Library. As you will see later, each module is represented by a XAP file that gets downloaded and initialized by Prism infrastructure.

Previously, I highlighted how to define modules in the Bootstrapper that Prism could load either at startup time or any other time during the application’s lifetime. To provide a module definition, here are the properties that need to be set on the ModuleInfo class:

    <Modularity:ModuleInfo
        Ref="Module1.xap"
        ModuleName="Module1"
        ModuleType=
"Module1.ModuleDefinitions.Module,
Module1, Version=1.0.0.0"
        InitializationMode="WhenAvailable" />

  1. Ref: Contains the path to the XAP file where the module package is located.
  2. ModuleName: Represents the name of the module.
  3. ModuleType: Represents the fully qualified assembly name for the module’s assembly.
  4. InitializationMode: It has two values: WhenAvailable (default value) and OnDemand. When this property is set to OnDemand, the module won’t be loaded at the application startup.

Each of the above sections gets parsed to a ModuleInfo class managed by the Prism framework.

The InitializeModules() method, explained above as part of the Bootstrapper functionality, loops through all the modules defined with their InitializationMode set to “WhenAvailable”. It then locates their XAP files, or if not present, downloads them, and finally initializes each of the modules downloaded.

Initializing modules requires that each module class implements the IModule interface that has a single method to implement, the Initialize() method:

  public class Module : IModule
  { … }

The Initialize() method is a void one and is usually utilized by the module to register the views, ViewModels, and services into the Container and register views to regions. A sample module’s Initialize() method looks like the following:

      public void Initialize()
      {
          // Register the DataService concrete
          // type with the container.
          container.RegisterType<IDataService,
          DataService>();
    
          // Show the EmployeeList view in the
          // MainRegion
          regionManager.RegisterViewWithRegion(
          "MainRegion", () => container.Resolve
          <EmployeeListView>() );
      }

Another important piece of the module is the module constructor. At the beginning of this article, I explained the concept of IoC containers and DI to tell you that Prism bases its functionality on IoC containers to perform DI to modules that request dependencies. For instance, if a module needs to register a view with a region, how will it get access to the RegionManager class that is part of the Prism infrastructure registered with the container when the Bootstrapper ran? The answer lies in the fact that the module requests service through its constructor. Those services get injected into the module by means of an IoC container used by Prism. Therefore, a module that needs to register services and views has to have two things:

  1. Container instance.
  2. RegionManager instance.
        private readonly
           IUnityContainer _container;
        private readonly
           IRegionManager _regionManager;
        
        public Module (
           IUnityContainer container,
           IRegionManager regionManager )
        {
            _container = container;
            _regionManager = regionManager;
        }

Prism populates the Container and RegionManager parameters with actual instances of the Container and RegionManager upon the creation of the module class and before running the Initialize() method of each module.

Sometimes certain modules do register some services to be used by other modules. Therefore, you should load those modules before any other module that makes use of the services registered by them. Prism, again and again, provides the means to restrict registering modules that depend on other modules, before registering the modules providing the services. This can be shown in the ModuleCatalog.xaml file below:

    <Modularity:ModuleInfo
        Ref="Module2.xap"
        ModuleName="Module2"
        InitializationMode="WhenAvailable"
        ModuleType
          ="Module2.ModuleDefinitions.Module,
          Module2, Version=1.0.0.0">
        <Modularity:ModuleInfo.DependsOn>
            <sys:String>Module1</sys:String>
        </Modularity:ModuleInfo.DependsOn>
    </Modularity:ModuleInfo>

The DependsOn property of the ModuleInfo class allows you to specify a collection of module names that this current module depends on. Defining a module before defining its dependencies forces Prism to throw an exception at run time once the application starts.

In summary, Prism promotes dividing an application into a set of independent modules, each loaded at different times of the application’s lifetime. All that the module class has to do is implement the IModule interface single method, the Initialize() method. In case a module requests a service, it is being injected automatically at run time by the Container utilized in Prism without having the module manage its dependencies.

Event Aggregation

Up till now this article has focused on how Prism promotes modularity in developing WPF and Silverlight applications. An application is composed of several functional units, i.e., modules, each responsible for certain set of features in the application. When a module loads, it adds its own view into the main Shell component. Definitely this view is responsible for handling the functionality exposed by the module it belongs to.

For instance, there are two modules in an application. One of them shows a list of employees in your department and the other module is responsible to present the details of each selected employee in the first module.

How will these two views communicate?

How will the second module know what employee has been selected and when?

The answer lies in the Event Aggregation service provided by Prism to help remedy such a situation. Actually, event aggregation supports developing loosely coupled modules, each responsible for a specific task, together with cross-module communication.

The way event aggregation is implemented in Prism is that one module publishes an event and any module interested in listening to that event subscribes upon module initialization. This way, when a module publishes an event, the subscribed modules respond to the event being published. Prism even goes beyond this publishing/subscribing process by giving the subscriber the chance to filter the events fired. Hence, a module can provide a filter for the events to respond to based on some criterion, i.e., payload of the event.

Before an event can be published and subscribed to it has to be created. For an event to be utilized by the event aggregation service it must derive from the EventBase class. This class is located inside the Microsoft.Practices.Composite.Events namespace and it manages the internals of subscribing to and publishing events by the event aggregation service.

As part of cross-module communication service in Prism, a generic class, the CompositePresentationEvent<TPayload>, located in the Microsoft.Practices.Composite.Presentation.Events namespace and derived from the EventBase class, is used as a base class for defining events processed by the event aggregation service allowing an event to specify a payload that can be published together with the event. For instance:

    public class EmployeeSelectedEvent :
       CompositePresentationEvent<Employee>
    { }

The EmployeeSelectedEvent derives from the CompositePresentationEvent class and specifies the Employee object as a payload for the event. Hence, when an employee is selected, the EmployeeSelectedEvent is published together with the employee record that was selected on the view. Publishing an event is done as follows:

        eventAggregator.GetEvent
<EmployeeSelectedEvent>().Publish(employee);

The event aggregator is a generic class that implements the IEventAggregator interface and contains a single method, the GetEvent<TEventType> where TEventType derives from the EventBase class. The first time the EmployeeSelectedEvent is queried by the GetEvent() method, an instance of that class is created and stored internally by the event aggregator service so that the same instance is used when publishing the event and subscribing to it.

To subscribe to an event, the following is used:

            eventAggregator.GetEvent<
EmployeeSelectedEvent>().Subscribe(
OnEmployeeSelected);

The EmployeeSelectedEventHandler() method is defined as follows:

        public void OnEmployeeSelected(
           Employee selectedEmployee)
        {
        }

The Subscribe() method usually subscribes a delegate to an event that is being published and has the following overloads:

  • Subscribe(Action<TPayload> action)
  • Subscribe(Action<TPayload> action, ThreadOption threadOption)
  • Subscribe(Action<TPayload> action, bool KeepSubscriberReferenceAlive)
  • Subscribe(Action<TPayload> action, ThreadOption threadOption, bool KeepSubscriberReferenceAlive)
  • Subscribe(Action<TPayload> action, ThreadOption threadOption, bool KeepSubscriberReferenceAlive, Predicate<TPayload> filter)

The delegate defined by all the overloads for the Subscribe() method is of type Action<TPayload> representing a void method accepting a single parameter, the payload published by an event. This delegate gets executed when the event is published. One of the overloads takes as a parameter one of the values of the ThreadOption enumeration defined by Prism as follows:

        public enum ThreadOption
        {
            PublisherThread,
            UIThread,
            BackgroundThread
        }

ThreadOption specifies on which thread an event subscriber would be called, whether on the same thread as that of the publisher (PublisherThread), on the UI thread, or asynchronously on a background thread.

Two of the Subscribe() method overloads accept a Boolean, KeepSubscriberReferenceAlive, when set to True, the CompositePresentationEvent<TPayload> event keeps a reference to the subscriber so it does not collect garbage. On the other hand, when this value is set to False, the CompositePresentationEvent<TPayload> event will maintain a WeakReference to the object that defines and hosts the action delegate. Therefore, it is important to note that when setting the KeepSubscriberReferenceAlive to True, developers must explicitly call Unsubscribe for the event when disposing the subscriber in order to avoid memory leaks or unexpected behavior.

The last overloaded method above accepts as input a predicate<TPayload> delegate named filter. This delegate gets executed before the Action<TPayload> gets the chance to execute. The filter fires to evaluate whether the subscriber should process the event published. This allows the subscriber to respond based on the payload being passed, which again provides a flexible way of handling cross-module communication.

In summary, Prism provides the event aggregator service to allow cross-module or cross-view communication between modules promoting all means of separation of concerns between loosely coupled modules.

Delegate Commands

WPF already ships with command support, based on the ICommand interface, allowing applications developed with WPF to implement presentational design patterns, such as Presentation Model and Model View View-Model. However, Silverlight has been missing this feature until recently. Silverlight 4.0 Beta that adds command support through the ICommand interface; however, it is still primitive. It is expected that by the time Silverlight 4.0 is officially released, it will have a robust command framework.

I have mentioned above the importance of using MVVM in developing Silverlight applications. With MVVM, there is a complete separation of concerns between the View, ViewModel, and Model. The V represents the view or UI of the application (or module), the V M represents the ViewModel of the class used to handle the state and behavior of the view, and the M represents the model or data object that is being bound to the UI. A link to an article on Silverlight and MVVM has been supplied above to understand how intrinsic it is to implement MVVM in Silverlight applications.

For a brief overview, the view is required to show the UI, any control on the view requesting data from the server gets it data source property bound to a property on the ViewModel class. ViewModel itself is responsible to get the data from the server and binds it to the view. Hence, the complete separation between the view and model by having a mediator class, the ViewModel that plays the role in binding a view to a model through the effective use of the powerful data-binding framework in Silverlight. ViewModel not only is responsible to bind the view to model objects, but also holds the state of the view. For instance, you add a Button control to the view as follows:

    <Button x:Name="btnSubmit" Content=
    "Submit" Grid.Row="0" />

In case MVVM is not used, in the code-behind of the view, the IsEnabled property of the Button control can be controlled as follows:

    this.btnSubmit.IsEnabled = false;
    // or true

However, with MVVM, the way to control the IsEnabled property is to bind the Button’s IsEnabled property to a property defined inside the ViewModel as follows:

    <Button x:Name="btnSubmit" Content="Submit"
Grid.Row ="0" IsEnabled ="{Binding IsEnabled}" />

The ViewModel’s IsEnabled property is defined as follows:

        bool isEnabled = false;
        public bool IsEnabled
        {
            get
            {
                return this.isEnabled;
            }
        }

ViewModel has no direct references to controls on the UI, which is a major concept while developing MVVM. In effect, you must isolate ViewModel from all controls defined by the UI, hence making the ViewModel ready for unit testing.

View’s code-behind has no single line of code; however, there might sometimes be exceptions to this rule. But as a general way of implementing MVVM, it is required to have a clean codeless code-behind for a view.

Now that you know the ViewModel plays the role of binding the view to the model objects, i.e., provides the data source for controls displayed by the view and handles the state of the view layout, you still need to learn about how the ViewModel handles the behavior of the view. Behavior can be summarized this way: When a user clicks a button on the view, how do you handle the Click event? When a user selects a ListBox item, who handles the SelectionChanged event? In normal situations, the event handlers for controls on the view could be handled by the code-behind. However, with proper implementation of MVVM, the ViewModel is responsible for handling the entire behavior of the view. The way the ViewModel handles such events is through the use of commands that Prism introduces into Silverlight to help the developer code pure MVVM Silverlight applications.

Prism provides implementation to two kinds of commands: CompositeCommand and DelegateCommand. Both command types implement the ICommand interface which defines the contract for commands. For the sake of this discussion, only DelegateCommands are discussed. It is also worth mentioning that Prism ships with command support for the ButtonBase class, i.e., any control that derives from this class, for instance the Button control, will have the capability to use commands in Prism.

Typically in an MVVM Silverlight application, you define a delegate command inside the ViewModel, something like the following:

        public DelegateCommand<object>
SaveOrderCommand { get; private set; }

In the constructor of the ViewModel, you initialize the command as follows:

        this.SaveOrderCommand = new
DelegateCommand<object>(this.Save, this.CanSave);

When the command is executed, the Save() method runs, which was defined on the ViewModel. Right after running the Save() method, the CanSave() method runs. This method is present to update the control that executed the command, for instance you can disable a Button control right after clicking it the first time.

On the view, you start by referencing the Microsoft.Practices.Composite.Presentation.Commands namespace.

    xmlns:cal="clr-namespace:
Microsoft.Practices.Composite.
Presentation.Commands;assembly=Microsoft.
Practices.Composite.Presentation"

Then bind the command defined above to a Button control:

<Button Content="Save" cal:Click.Command="{
Binding Path=SaveOrderCommand}" />

When a user clicks the Button, the Click event on the button is fired, and then the SaveOrderCommand executes (defined on the ViewModel), which in turn fires the Save() method.

As you can see, because of the command support that Prism provides, you can fully implement MVVM and other presentational design patterns.

As mentioned above, Prism supports commands only for controls deriving from ButtonBase. However, it provides the tools to create commands for other types of controls, which is a topic in itself and is not covered in this article.

In summary, the support of commands allows handling user interaction with the view and on the ViewModel, but not directly on the view’s code-behind; hence, promoting unit testing for the functionality of the view that is encapsulated inside the ViewModel.

Summary

The goal of this article was not to provide an implementation for a Silverlight application using Prism. But rather the goal was to go through the details of the Prism framework to show you the power of Prism in building better Silverlight applications.

Prism provides modularity to Silverlight and WPF applications in a sense that helps the developer divide the application into separate loosely coupled functional units called modules, each having its own self-contained functionality.

As a consequence to modularity, each module will be responsible to load its own layout to be integrated into the Shell component representing the entire UI of the application; hence, the UI composition concept introduced by Prism that lets every module bring its own UI into the application’s Shell or main UI.

Having loosely coupled modules in an application made Prism offer the event aggregation service as a way of cross-module communication. In other words, having a module publish an event to signal a change in the module itself where other modules in the application subscribe to that event to receive those changes and react accordingly.

Finally, to support best practices in developing Silverlight applications, Prism supports commands, a feature that has been missing from Silverlight. Only in Silverlight 4.0 Beta has there been primitive support for it. With commands, you can implement presentation design patterns, such as the Model View ViewModel (MVVM) pattern. MVVM separates concerns by making the View responsible for only showing the layout or UI of the application, the Model representing all the data objects, and the ViewModel becoming the tie or link that binds the View into the Model and handles the state and behavior of the view, and above all, communicates with the server for data retrieval and data binding.