Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Starting with Prism - Part 1 of n

0.00/5 (No votes)
3 Oct 2012 1  
An introduction to Prism.

Introduction 

Prism provides the guidance to create composite applications and help us to design loosely coupled components, which can be integrated and developed in seamless manner. Like every other application, Prism application also need to get start from somewhere. And when coming to Prism, it is Bootstrapper and Shell. These two things help any Prism application up and running. In this article, we will look more into Bootstrapper and its process. So, gear up and let's get started...

Bootstrapper

So, what is Bootstrapper? Bootstrapper is the class, which is responsible for initializing our application. Now question is what to initialize? So, the first thing is to initialize is the Core Services and then the Application Specific Services.

Core Services: These are non-application specific services that Prism library provide to us. These services include:

  • IModuleManager - Responsible for retrieving application's modules
  • IModuleCatalog - It is used to register the modules
  • IModuleInitializer - Responsible for initializing the modules
  • IRegionManager - These are visual containers for our UI
  • IEventAggregator - It allows us to create events
  • ILoggerFacade - This is wrapper for logging mechanism
  • IServiceLocator - This is used to give application access to your container

Application Specific Services: Apart from core services, Prism also initializes some application-specific services. These are the services, which are specific to our application and which is common among all application modules. For example, if you are working on RSS type application, in that case, RSS Feed service will be application-specific service, which will be used by almost all the modules to read the feeds. 

Bootstrapper Process 

Bootstrapper is the very important class, which gives us control of every component, application gets wired up. Prism library provides a default abstract Bootstrapper base class, that has number of virtual methods. Let's go ahead and take a look a Bootstrapper process. Keep in mind that most of the stages of this process will be covered in more detail in subsequent articles.

  • First thing is to create a LoggerFacade, which will mainly deal with logging
  • Next one has to configure Module Catalog
  • Then one has to create a container and one can use any container of their choice such as Ninject, Unity, MEF, etc. Prism library actually includes, two Bootstrapper classes. One called the UnityBootstrapper and another one is MEF, which includes most of the functionality necessary to use Unity or MEF as your dependency injection container
  • Next one has to configure default Region Adapter Mappings. So, we have to create a custom Region Adapter, which we will register there
  • Next we would configure our default Region Behaviors
  • Then we will register our framework Exception Types
  • Next we would create the Shell
  • Then Shell will be initialized
  • And lastly Modules will be initialized

Please keep in mind that we need not to implement each and every single stage.

Sample code for UnityBootStrapper  

In order to use Unity, one needs to add below references to the project:

  • Microsoft.Practices.Prism.dll
  • Microsoft.Practices.Prism.UnityExtensions.dll
  • Microsoft.Practices.Prism.Unity.dll

Next we needs to add a class named Bootstrapper, as:  

public class Bootstrapper : UnityBootstrapper
{
    protected override System.Windows.DependencyObject CreateShell()
    {
        return Container.Resolve<Shell>();
    }

    protected override void InitializeShell()
    {
        base.InitializeShell();

        App.Current.MainWindow = (Window)Shell;
        App.Current.MainWindow.Show();
    }
}
public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        Bootstrapper bootstrapper = new Bootstrapper();
        bootstrapper.Run();
    }
}

Regions   

Here I am going to talk about the role of Regions in any Prism application. Here we will discuss, what Regions are and what role they play in our application. We will also look into RegionManager and how it manages our Prism application. We will also touch upon RegionAdapter and the relationship between Region and RegionManager. Then we will see, how to create a custom region as it is necessary for the controls, which Prism doesn't support.

What are Regions?  

A Region is simply a placeholder for any dynamic content, which is going to be presented in our UI. Regions are similar to the ASP.NET's content placeholders. It is simply a named location, that one can use to define, where our View will appear. I hope, you remember, we talked about the concept of the Shell earlier and how the Shell can contain Regions, where we will inject our Views into. 

Now let's take an example quickly. In this example, we will have MenuBar Region and a Content Region.

These regions define areas of the UI, where our View is going to be injected. Each Region should be explicitly named and describe the type of content in which we are going to inject the Region. So, given a Module with a two views named MenuBar View and Content View. These views will be injected to their respective regions. It means, each Region will have it's corresponding View. Here MenuBar View will be injected to MenuBar Region and Content View will be injected to Content Region.

Now, keep in mind, that we just don't have to be in the Shell as Region can also be defined in another View. 

Regions have no knowledge of Views. We can locate content to a Region, without exact knowledge of how and where the Region is defined. This allows the layout change without effecting the Views in the Module. Eg; In above figure, we can shift 'MenuBar Region' to left of 'Content Region', but our 'MenuBar view' will be injected to 'MenuBar Region' and 'Content View', will be still placed into 'Content Region'. So, in this way, we are able to re-design our Shell, without having to re-code any type of infrastructure code. 

Regions can be created in code or in XAML. One thing, which we need to keep in mind id, Region is not a control, but is a host control and it always implements a IRegion interface. This is important to know as it will be used, when you will programmatic access your Region.  

Region Manager 

I hope, as many of you have probably guessed that a Region Manager is responsible for managing the Regions in the application. It does this, by maintaining the collection of regions. It also provides a RegionName property. This is actually an attached property, that is used to create Regions by applying it, to the host control and this can be again done through XAML or through code.

Region Manager also maps RegionAdapter to controls. Now, RegionAdapter is responsible for associating a Region with the host control. In order to expose, UI control as a Region, it must have a RegionAdapter and each RegionAdapter adapts a specific type of UI control.

Prism provide us with four RegionAdapter:

  • ContentControlRegionAdapter - which adapts controls of type content control
  • ItemsControlRegionAdapter -   which adapts controls of type content control
  • SelectorRegionAdapter - which adapts controls provided by Selector class, such as tab control
  • TabContorlRegionAdapter - this is contained only by SL version because in SL, it is not a part of Selector class and behaves bit differently from WPF control

Now, if Prism provided RegionAdapter, doesn't meet our need, we can definitely create our own.

Region Manager also provides a RegionContext attached property. This property is similar to the concept of DataContext. It is a technique to share a data between a parent view and a child view. RegionContext can also be set form the code or from XAML. 

Sample code snippet to create a Region  

In order to create a Region, one needs to add below references to the XAML (Shell):

xmlns:local="http"//www.codeplex.com/prism" 

Next we needs to create Regions as , as:  

<DockPanel>
  <ContentControl DockPanel.Dock="Top" local:RegionManager.RegionName="MenuBarRegion"/>
  <ContentControl local:RegionManager.RegionName="ContentRegion"/>
</DockPanel>

Now, go to the Module class and add the following:

public class MyModule : IModule
{ 
   IUnityContainer _container;
   IRegionManager _regionManager;
   public MyModule(IUnityContainer container, IRegionManager regionManager)
   {
      _container = container; 
      _regionManager = _regionManager
   } 

   public void Initialize()
   {
      regionManager.RegisterViewWithRegion("MenuBarRegion", typeof(MenuBarView));
      regionManager.RegisterViewWithRegion("ContentRegion", typeof(ContentView));
   }
}

Custom Region   

There are times, when we need to use third party control or a custom control as a Region host. There is no issue, as far as our custom control can use the Prism provided RegionAdapters. But it can not be the case always. So, we need to create our own RegionAdapter to adapt a custom control as a Region host. There are only a few steps, we need to follow:

  • Derive your class from RegionAdapterBase<T>
  • Implement CreateRegion method - this method returns one of the following objects
    1. SingleActiveRegion (mainly used for content control)
    2. AllActiveRegion (mainly used for items control)
    3. Region (mainly used for controls derived from the Selector class)
  • Implement Adapt Method - this is to actually adapt your control
  • Register your adapter

Just watch my next article of this series, here.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here