Month: February 2010

Build enterprise applications with WPF, WCF, EF and Prism. Tutorial 09.

Today we will see the modularity concept of Prism. Probably the best part of it, as it will allow us to build a real plug-and-play application where the main Shell won’t know anything about the modules.

Discover and load the module.

What does it mean? As we saw in the previous article, we have declared a reference in our Shell for the hello world module. In this way we force the Shell to be compiled including in the shell project a reference to the Hello World module. Fine, but what happen if we want to replace this module with a new version? We need to change the reference in the project and recompile it … Pretty ugly for a modular application doesn’t it?

The basic concept in Prism is that we can discover on fly the available modules and load them … This is the workflow process of discovering and loading a module in Prism.

 prism module

There are different ways to load a module. As we saw in the previous article, the easiest way is to add a direct reference to the module in the Shell and load it in the bootstrapper:

  1: ModuleCatalog catalog = new ModuleCatalog()
  2:    .AddModule(typeof(HelloWorldModule.HelloWorldModule));

The second way is to add the module reference in the app.config and REMOVE the code in the bootstrapper. In this way we won’t need to recompile the module each time we will run the application in Visual Studio and we won’t need a direct reference to it. Let’s see the code below. I have a added an app.config file in my shell project:

  1: <?xml version="1.0" encoding="utf-8" ?>
  2: <configuration>
  3:   <configSections>
  4:     <section name="modules"
  5:              type="Microsoft.Practices.Composite.Modularity.ModulesConfigurationSection, Microsoft.Practices.Composite"/>
  6:   </configSections>
  7:   <modules>
  8:     <module 
  9:       assemblyFile="Modules/HelloWorldModule.dll" 
 10:       moduleType="HelloWorldModule.HelloWorldModule, HelloWorldModule" 
 11:       moduleName="HelloWorldModule"/>
 12:   </modules>
 13: </configuration>

I am using the composite section in the app.config file to load a specific module. Now, in order to make this ‘runnable’ we need to:

  • remove the reference in the Shell project
  • clean-up the code in the bootstrapper that loads the module

The shell project will use this code now to load the Module catalog:

  1: ModuleCatalog catalog = new ConfigurationModuleCatalog();

As you can see we are telling to Prism to look in the app.config and load the modules available there. In order to make the module available in the modules folder inside the bin folder of the shell you can play with MSBuild or a post-event action in VS. I copied this code from MSDN and added to the post event build action in the HelloWorldModule project properties:

  1: xcopy "$(TargetDir)*.*" 
  2: "$(SolutionDir)Shell\bin\$(ConfigurationName)\Modules\" /Y

Pretty cool! We can now work with our modules without breaking any change in the Shell project, and trust me, when you work on a team, this happens every day …

Additional configuration options.

Of course the game is not done yet. We have a lot of options that we can configure in the app config in order to load modules on fly and to add dependencies from other modules. For example, let’s say that Outlook can’t open a view if the ribbon is not loaded, but the ribbon is on another module … Wink

Load on demand

We can specify, for example, that we want to load on demand (by request) a specific module that we don’t know. Pretty cool as this is how should work a real modular application. In order to do this we don’t need anything more that this tag in the app.config:

  1: <module 
  2:    assemblyFile="Modules/HelloWorld.dll" 
  3:    moduleType="HelloWorld, HelloWorld" 
  4:    moduleName="HelloWorld" 
  5:    InitializeMode="OnDemand"/>

Now that we setup the module to load “onDemand” the module won’t be load in memory until we will instruct Prism to do that. This is a real plug and play concept, because without any dependencies we can load on demand part of our UI during the program execution. In Windows Form this can’t simply be done!

  1: moduleManager.LoadModule("HelloWorld");

There you go, in a simple call from any view we can ask for a specific module. The initialize method of the module will be call and our UI will receive the ‘default’ view of that module, injected in the shell or in another module … there are no limitations at all.

Now we are ready to build the first cool module of our app, the main Ribbon bar.

Tags:

2 Years of blog.raffaeu.com.

Today it’s 2 years that I have opened my blog in English and it’s two years that I moved to Bermuda web site.

I should do some considerations about it but it’s not the right time for me so I will try to be as less negative as I can.

Job and career.

I moved here 2 years ago as a Senior Software Developer working for a public Company as the IT Manager. In this company I was in charge of the entire (small) IT department. Unfortunately, after the Market Crisis of the 2009 I was ‘convinced’ to look for another job.

Actually I am working as a ‘real software architect’ for a pretty cool company also in the re-insurance business. In this company I am using all my knowledge (design architectures, .NET, latest technologies like WCF, WPF, WF) and I have also the luckiness to have the opportunity to mentor my colleagues with a weekly workshop. Trust me, for a community addicted like me it’s a huge satisfaction!

I got some new Microsoft Certifications and I am working hard to gain the complete set of MCPD certifications too.

Moving to Bermuda web site.

Bermuda web site is a small Island in the Atlantic Ocean. The size is around 50Kmq and the population size is around 60,000 people, more or less.

After the ‘first year honeymoon’ the life starts to be really hard here.

Honestly, is not an easy place for a lot of reasons, especially for someone like me that is coming from one of the nicest place in the North of Italy, the Lake Maggiore and that likes a lot mountain activities like skiing and walking in the forest. What I miss in order of importance are:

  • Friends, friendship in Italy is very different than in any other country, trust me! Smile
  • Food, also if me and my wife are decent cook, we still miss a lot of our traditional food here.
  • The environment. I miss the mountain, the snow, the lake and the quite winter we have in my town. I miss Milan and the shopping and I also miss the Switzerland where I spent the last 7 years.
  • NET Communities. Nothing like that in Bermuda web site, I also tried to open a workgroup a year ago but it seems to be a mission impossible.

Life is crazy expensive, just to give you a small idea, a normal rent is around 3, 4K a month and a decent dinner in a decent restaurant is around 150, 200 USD for two person.

Fortunately, I have here all my family (my wife, my sweetie dog and my cat) so I feel comfortable and for now I still don’t have the need to come back home; I also found some nice Italians friends that help me in the daily complains … Smile

Personal.

When I moved here two years ago I started an awesome sport called ‘Kite surfing’. Unfortunately, last year, I had a bad accident in Brazil, when I was on holiday with my wife, and I had a hernia surgery. After that I stopped to kite also because my wife won’t allow me to do that anymore. Wink

The plan for this year is pretty ambitious but I won’t mention anything yet. I am just planning to write a lot, articles, online tutorials, book and more. Of course everything will be related to .NET 4.

My blog has now a small but really interesting average of 150 feed readers and an average of 200 visits per day with at least 1 daily feedback. Trust me, it’s a huge satisfaction especially when your readers send you e-mail for business requests. Laughing

Build enterprise application with WPF, WCF, Prism and Entity Framework. Tutorial 08.

Update: source code and documentation are now available on CodePlex at this address: http://prismtutorial.codeplex.com/

Today we will build the skeleton of our application using the latest version of Prism, available in this section of MSDN: Prism February 2009. One of the reasons that I didn’t write anything concrete until now is the fact that I knew that the new version of Prism was coming this month. Smile

The classic Hello World application.

As for every tutorial, is always better to start with the classic Hello World in order to understand, step by step, how Prism structures the various part of the UI.

Let’s open our VS Solution (remember that if you download the solution from my CodePlex repository the solution will contains already the entire code of each article) and let’s add a new project of type WPF application. I called Prism.Shell because this one will be our shell that will contain the bootstrapper.

Note about references.

In order to add the assemblies that I will mention in this and in the next tutorials you must download the latest version of Prism V2 and build the solutions so you will have all the assemblies you need. This is the structure of my Prism Framework:

image_thumb6

For practice I have already compiled all the required assemblies and added them to a solution folder in VS. This is what I have and what I reference in my projects:

image_thumb14

Finally, remember also that you can open each Prism component and re-compile it, add new future and suggest new capabilities to the Microsoft team. They will appreciate for sure! Smile

So … coming back to our project this is what we need in our Shell:

References:

  1. Microsoft.Composite
    This is the core of the composite framework
  2. Microsoft.Composite.Presentation
    This assembly contains the components that target Prism for WPF
  3. Microsoft.Composite.UnityExtension
    It’s a utility assembly for unity IoC container

The Shell XAML container.

Let’s add a new Windows Component from WPF template and the name will be Shell.xaml. Below the code I have added to the window in order to show 3 different regions.

1: <Window x:Class=“Shell.Shell”

2: xmlns=“http://schemas.microsoft.com/winfx/2006/xaml/presentation”

3: xmlns:x=“http://schemas.microsoft.com/winfx/2006/xaml”

4: Title=“Hello World with Regions” Height=“500” Width=“500”>

5: <DockPanel>

6: <ItemsControl x:Name=“HeaderRegion” DockPanel.Dock=“Top” Height=“50”>

7:

8: </ItemsControl>

9: <ItemsControl x:Name=“LeftRegion” Width=“100” DockPanel.Dock=“Left”>

10:

11: </ItemsControl>

12: <ItemsControl x:Name=“MainRegion” DockPanel.Dock=“Bottom”>

13:

14: </ItemsControl>

15: </DockPanel>

16: </Window>

We have added 3 ItemsControl inside a DockPanel in order to design a simple Outlook style layout with an header, a main container and a left navigation menu.

Now we need to extend this control using the attached properties in order to use the Prism region adapters. This is the code we must include in the xaml declaration:

1: xmlns:cal=”http://www.codeplex.com/CompositeWPF”

Now we are ready to change our xaml code in this way:

1: <ItemsControl

2: x:Name=“HeaderRegion”

3: cal:RegionManager.RegionName=“HeaderRegion”

4: …

5: <ItemsControl

6: x:Name=“LeftRegion”

7: cal:RegionManager.RegionName=“LeftRegion”

8: …

9: <ItemsControl

10: x:Name=“MainRegion”

11: cal:RegionManager.RegionName=“MainRegion”

12: …

We said to Prism: “Hey when you load the Shell assign to each ItemsControl the corresponding Region using the attached property regionManager.RegionName”.

The bootstrapper.

The bootstrapper is nothing more than the entry point of our application. He is in charge to resolve and charge the modules and assign them to the corresponding view for the initial setup. So we need to create a new class in our Shell project and call it Bootstrapper.cs. This is the code we need for our initial setup:

1: protected override IModuleCatalog GetModuleCatalog() {

2: ModuleCatalog catalog = new ModuleCatalog();

3: return catalog;

4: }

This method should return an instance of the modules catalog used inside the application. What is the module catalog? The catalog contains all the modules we will use in our application. As we don’t have any module right now, this method returns an empty catalog. We will see in the future that we can load modules in the catalog also during the application execution.

1: protected override DependencyObject CreateShell() {

2: Shell shell = new Shell();

3: shell.Show();

4: return shell;

5: }

The create shell method, is only creating a new instance of the main window, called Shell and showing it to the user. Let’s say that this is the first entry point.

Now we need to modify the app.xaml in order to startup our application using the Boostrapper. First of all remove this row from the xaml code:

1: StartupUri=”Window1.xaml“>

We don’t want anymore that the application will start using this window but we want to use the boostrapper.

Now we need to modify the app.xaml.cs in this way:

1: protected override void OnStartup(StartupEventArgs e) {

2: base.OnStartup(e);

3: Bootstrapper bootstrapper = new Bootstrapper();

4: bootstrapper.Run();

5: }

As you can see, starting from now our application will request to the bootstrapper to load the first window and we won’t have any more dependency to the related main window.

You should be able to press F5 and run this part of the tutorial without any problem.

Add custom content to the regions.

Until now we wrote the code to startup our prism application but we still need to create at least 3 views, in order to load some content to the corresponding regions.

We need for this a new “module” that in VS is nothing more than a Class Library Project. We need the following references in order to be able to use WPF and the composite framework in our assembly:

image_thumb22

The first thing that every module will have is a “module class” that will implement the IModule contract from the composite framework. It’s pretty easy because this contract exposes only 1 method “void Initialize()”. The basic structure of the module class is something like this:

1: public sealed class HelloWorldModule : IModule {

2:

3: private readonly IRegionManager regionManager;

4:

5: public void Initialize() {

6:

7: }

8:

9: public HelloWorldModule(IRegionManager regionManager) {

10: this.regionManager = regionManager;

11: }

12: }

13:

So we have declared a private IRegionManager that will represent the main region manager instantiated by the bootstrapper. As soon as the bootstrapper will load it will inject the region manager inside our module. Than we have created a constructor with dependency injection, this mean that as soon as the module will be declared it will receive a specific RegionManager class. Finally we have implemented the IRegionManager Initialize() method that will be used to register the views to the corresponding regions.

Now let’s go back to the shell application. We need now to add a “project reference” to the new module we have created. After that we need to add this line of code inside the Bootstrapper class:

1: protected override IModuleCatalog GetModuleCatalog() {

2: ModuleCatalog catalog = new ModuleCatalog()

3: .AddModule(typeof(HelloWorldModule.HelloWorldModule));

4: return catalog;

5: }

We said to the boostrapper that as soon as it will load it will need to add to the module catalog a new module, our HelloWorldModule class. If we try to run the app now it will run successfully but nothing will change in the UI because we still need to create the views.

What I want to show is the power of loading different views in different regions, so for this reason I am rendering a special textblock with some fancy shadows. This is the code and the final result:

image_thumb31

1: <Border

2: Margin=“20”

3: Padding=“10”

4: BorderThickness=“3”

5: CornerRadius=“15”

6: Background=“White”

7: BorderBrush=“SteelBlue”>

8: <Border.Effect>

9: <DropShadowEffect Color=“Gray”/>

10: </Border.Effect>

11: </Border>

12: <Border

13: Margin=“20”

14: Padding=“10”

15: BorderThickness=“3”

16: CornerRadius=“15”>

17: <TextBlock

18: Text=“A custom header.”

19: FontSize=“24”

20: TextWrapping=“Wrap”

21: Foreground=“DarkSlateBlue”

22: HorizontalAlignment=“Center”

23: VerticalAlignment=“Center”/>

24: </Border>

Now, we need to add to our module 3 views using this effect in order to have this final result in our project:

image_thumb40

Now, in the module class we need to tell to Prism where each view should be loaded in the shell region manager. The ‘declarative way’ do to that it’s pretty simple:

1: public void Initialize() {

2: regionManager

3: .RegisterViewWithRegion(“HeaderRegion“, typeof(Views.HeaderView));

4: regionManager

5: .RegisterViewWithRegion(“LeftRegion“, typeof(Views.LeftView));

6: regionManager

7: .RegisterViewWithRegion(“MainRegion“, typeof(Views.MainView));

8: }

So for each view I assign the view to a corresponding region. The region name is the one we used in the attached property of the ItemsControl in the shell view.

Now if you press F5 this will be your final result:

image_thumb43

Conclusions.

This is the ‘primordial’ way to use Prism and to load 3 different views in 3 different regions. The next time we will see how many way Prism offers to load a module and the corresponding view, dynamically.

Tags: WPF Prism Composite application