Introduction

I know some of you will know that I am a WPF lover, and that I have my own MVVM framework out there called Cinch, and that I not so long ago published a whole series of articles on V2 of Cinch, and you are probably bored to death of it, well, from time to time me too, but someone asked me how easy it would be to get Cinch to work with Prism, and I just had to give it a try.

So this article will demonstrate how easy it is to use my own MVVM framework Cinch V2 with all the good bits and pieces you have grown to love from the Microsoft composite WPF/SL application block A.K.A.: Prism.

Oh, one thing I should mention is that Cinch also relies on a MEF View/ViewModel resolution framework from fellow WPF Disciple Marlon Grech, called MEFedMVVM. This is nothing new, and those of you that have read all the previous Cinch articles will know about this. I know it seems odd for my library to take a dependency on Marlon's, but I have nothing but praise for MEFedMVVM and have not had any problems with it at all, apart from the one time I updated my version of MEFedMVVM I was using with Cinch, where I managed to get the one release where Marlon was "Experimenting" bless. That said, since then, not one problem with MEFedMVVM; I am not worried by this dependency at all, and neither should you be I feel.

Prism V4

I do not know how many of you know what Prism is or keep track of its active releases, but Prism is the composite WPF/SL application block from Microsoft. If you used the Smart Client Software Factory (SCSF) for WinForms, it may look slightly familiar, but Prism is a different beast from SCSF and was written from the ground up to work with WPF and later Silverlight.

It is now in its fourth release, and offers features like:

Modules (these take the form of separate projects where there is everything you need to create a discrete unit of work, so if you are doing MVVM, this might be a View/ViewModule and DataAccess Layer helpers)

Regions, which are bits of the UI which are marked up as placeholders (like ASP.NET placeholders) that can take other bits of content at runtime

Shell (single start window)

Bootstrapper to get it all wired together

Now, there are a lot of people out there that think Prism is an MVVM framework, but it is not. It might lend itself to doing MVVM, but the truth is even after four releases, it still lacks some of the core bits to the MVVM puzzle. As such, people have written a great many MVVM libraries; this is not because we are all retarded, it is from a genuine need. Prism does not have all the bits you need, so people (myself included) have written MVVM frameworks to try and fill that gap.

That is not to say Prism is bad, it is not bad at all, and its region support alone is very, very attractive, but it still lacks certain things, such as core services you would expect of an MVVM framework, such as MessageBox, Modal windows, etc. Why is this? Well, it's simple: Prism is not an MVVM framework, it is a composite UI block that does have some bells and whistles that make it OK to do MVVM stuff with. The way I see it, Prism should be something you use along side your favourite MVVM framework.

Like I say, Prism is now in its fourth release. Previous releases have all used the Unity application block for Dependency Injection/IOC Container. Version 4 is different, it is also able to use MEF. As luck would have it, Cinch V2 also uses MEF, so this article will show you that you can use Cinch V2 with Prism (v4) with absolutely no issues what so ever.

In fact, I would go as far as to say they are an excellent pair of complimentary frameworks.

Demo 1: Architectural overview

Demo 1 is available as CinchV2AndPrismRegions.zip at the top of this article.

This demo does not use Prism modules but it does show you how to use Prism regions along side Cinch V2 with no bother at all. It also shows the user how to create a custom Prism region adaptor.

There is a single shell window that has a single TabControl region (using the standard Prism TabControl region adaptor) which will get two views loaded into it at runtime.

There is a welcome view which simply shows a simple bit of rich text, and utilises a Cinch V2 MEF injected ViewModel.

There is an Image view which shows a list of images that match a keyword driven Google search, and allows the user to click on one of the retrieved images, and have it show as a larger image in a custom region adaptor. The Image view also utilises a Cinch V2 MEF injected ViewModel.

Demo 1: What does it look like?

This demo is a bit more elaborate than the second one, but then again, the whole idea of regions/modules is more complicated, so I kept the second demo app quite simple. As previously stated, this first demo has a welcome view, which is pre-loaded in the Shell at startup and looks like this within the Shell.

The demo also allows multiple instances of another random Google image search view to be loaded using the button just below the banner (top left), but there is a pre-loaded one of these random image views loaded into the Shell on startup that is set to search Google for "Flowers", and this looks like this:

Note: This is half way through transitioning from one element to another, more on this later.

I have included a little threading helper control, so this is what it will look like while it is busy fetching data from Google:

To load a new instance of this view, and load some more random Google images, you can use the following button:

Demo 1: How does it all work?

These next sections will walk you through how it all works.

Demo 1: The Shell

The first step I carried out when building this demo was to create the Shell, which obviously meant getting all the relevant DLL references, but you can see that from the actual attached demo code. The Shell is a very simple Window which has the following XAML, and it really is just a region container for the other views to be loaded into.

And here is its code-behind; note that is marked with a MEFExportAttrtibute which allows the MEFCompositionContainer (we will see that next) to be able to resolve the Shell type and any MEFImports the Shell may require. It should be noted that in this demo, the Shell does not need to satisfy any other Imports, but in real life code, it more than likely would, so it is good practice to Export the Shell; it is also the defacto way that Prism works in V4.

It should also be noted that the Shell is using MEFedMVVM to resolve its ViewModel, which is of type ShellViewModel. ShellViewModel basically starts up and immediately populates the TabControl region "MainRegion" with a single WelcomeView and a single GoogleImageSearchView; this is shown below. ShellViewModel also allows new instances of a GoogleImageSearchView to be created where the GoogleImageSearchView will have some contextual data set by the ShellViewModel which will dictate the name of the region in the new GoogleImageSearchView just created. Care needs to be taken to ensure region names are unique within the same parent scope. More on this below.

And we also have the following code-behind which sets the region name to a dynamically changing string such that there are no two regions with the same name in the app ever. With Prism, if you want to make sure your content gets put into the correct region, that name needs to be unique, and as the demo allows multiple instances of the same GoogleImageSearchView to be opened, we need to make sure the region name is generated and assigned on the fly. That is what the code-behind does, along with some code in a command handler in the ShellViewModel which is run whenever a new GoogleImageSearchView is asked to be shown.

This is the code-behind for GoogleImageSearchView that sets the TransitionElement region name:

Demo 1: Bootstrapper

The next thing one must do when creating a Prism V4 application is to create a bootstrapper which inherits from MefBootstrapper; this is where the Shell is created and other Prism related overrides should be done.

There are a few things to note in there to do with getting Cinch V2 to work nicely with Prism; these things of note are:

That the MEFedMVVM (therefore Cinch V2) IComposer interface is implemented such that we can instruct MEFedMVVM to use the same CompositionContainer and Parts (Exports/Imports) as Prism. You can literally follow the example in this demo; that is all you need to do.

That we add the relevant catalogs to make Cinch V2/MEFedMVVM work in the ConfigureAggregateCatalog() override.

That the following line is run in the CreateShell override MEFedMVVM.ViewModelLocator.LocatorBootstrapper.ApplyComposer(this);.

That I am also running the Cinch V2 bootstrapper to get it resolve any popups / workspace views that are attributed up with the relevant Cinch V2 attributes (such as PopupNameToViewLookupKeyMetadata / ViewnameToViewLookupKeyMetadata).

That we also override the ConfigureRegionAdapterMappings() method to add in our custom region adaptors.

That is all you need to do to get Cinch V2 (and remember Cinch V2 makes use of MEFedMVVM for ViewModel resolution) /Prism to work together. Simple, isn't it?

Now that we have a bootstrapper, we need to make sure it is called, which is typically done in a Prism application in the App.xaml.cs code as follows:

Demo 1: Welcome View

The welcome view is pretty simple and just looks like this:

In fact, the XAML for the WelcomeView is dead simple too; here it is:

<UserControlx:Class="CinchV2AndPrismRegions.Views.WelcomeView"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:meffed="clr-namespace:MEFedMVVM.ViewModelLocator;assembly=MEFedMVVM.WPF"mc:Ignorable="d"d:DesignHeight="300"d:DesignWidth="300"meffed:ViewModelLocator.ViewModel="WelcomeViewModel"><GridBackground="White"Margin="5,0,0,0"><Grid.RowDefinitions><RowDefinitionHeight="auto"/><RowDefinitionHeight="auto"/></Grid.RowDefinitions><BorderHeight="30"Margin="0,10,10,0"VerticalAlignment="Bottom"CornerRadius="5"><Border.Background><LinearGradientBrushEndPoint="0.5,1"StartPoint="0.5,0"><GradientStopColor="Black"Offset="1"/><GradientStopColor="#FF7C7C7C"/><GradientStopColor="#FF3D3D3D"Offset="0.5"/></LinearGradientBrush></Border.Background></Border><StackPanelOrientation="Horizontal"Grid.Row="0"Grid.Column="0"Grid.ColumnSpan="2"><ImageHorizontalAlignment="Center"Margin="10,-3,0,-17"Source="/CinchV2AndPrismRegions;component/Images/blackInfo.png"Stretch="Fill"Width="60"Height="60"VerticalAlignment="Center"/><LabelContent="Information About This App"FontSize="15"HorizontalContentAlignment="Center"VerticalContentAlignment="Center"Foreground="White"FontFamily="Verdana"FontWeight="Bold"Padding="0"Margin="10,10,0,0"HorizontalAlignment="Left"d:LayoutOverrides="Height, GridBox"/></StackPanel><TextBlockMargin="5,30,5,5"Grid.Row="1"TextWrapping="Wrap"FontFamily="Verdana"><RunLanguage="en-gb"Text="This small "/><RunForeground="#FF020202"FontWeight="Bold"Language="en-gb"Text="Cinch"/><RunForeground="#FFF15C23"FontWeight="Bold"Language="en-gb"Text=" V2 "/><RunLanguage="en-gb"Text="demo shows just how you easy it is to use "/><RunFontWeight="Bold"Language="en-gb"Text="Cinch "/><RunForeground="#FFF15C23"FontWeight="Bold"Language="en-gb"Text="V2"/><RunForeground="#FFF15C23"Language="en-gb"Text=" "/><RunLanguage="en-gb"Text="along side Microsofts Composite WPF block
(Aka Patterns and Practices "/><RunFontWeight="Bold"Language="en-gb"Text="PRISM"/><RunLanguage="en-gb"Text="). "/><LineBreak/><RunLanguage="en-gb"/><LineBreak/><RunLanguage="en-gb"Text="This is largely down to the fact that "/><RunFontWeight="Bold"Language="en-gb"Text="PRISM "/><RunLanguage="en-gb"Text="and "/><RunFontWeight="Bold"Language="en-gb"Text="Cinch "/><RunForeground="#FFF15C23"FontWeight="Bold"Language="en-gb"Text="V2 "/><RunLanguage="en-gb"Text="both use MEF to assemble their UI's,
so it really could not be easier to use "/><RunFontWeight="Bold"Language="en-gb"Text="PRISM"/><RunLanguage="en-gb"Text="s excellent region support alongside "/><RunFontWeight="Bold"Language="en-gb"Text="Cinch "/><RunForeground="#FFF15C23"FontWeight="Bold"Language="en-gb"Text="V2 "/><RunLanguage="en-gb"Text="other classes, should you wish to do so."/><LineBreak/><RunLanguage="en-gb"/><LineBreak/><RunLanguage="en-gb"Text="This demo is WPF based, but the same
rules will apply when working with "/><RunFontWeight="Bold"Language="en-gb"Text="Cinch "/><RunForeground="#FFF15C23"FontWeight="Bold"Language="en-gb"Text="V2"/><RunForeground="#FFF15C23"Language="en-gb"Text=" "/><RunLanguage="en-gb"Text="for "/><RunForeground="#FF46B7E7"FontWeight="Bold"Language="en-gb"Text="Silverlight "/><RunLanguage="en-gb"Text="and making use of "/><RunFontWeight="Bold"Language="en-gb"Text="PRISM "/><RunLanguage="en-gb"Text="for "/><RunForeground="#FF46B7E7"FontWeight="Bold"Language="en-gb"Text="Silverlight"/></TextBlock></Grid></UserControl>

The only thing of note here is that the WelcomeView resolves its ViewModel using MEFedMVVM, where the WelcomeViewModel looks like this:

It can be seen that it inherits from the Cinch.ViewModelBase class and as such is able to set the IsCloseable property, which is used when styling the TabItems for the Shell TabControl region (see the demo's AppStyle.xaml resources for that).

Demo 1: Image View

The second view in this first demo is slightly more sophisticated, and uses a freely available Google image search which you will find in the attached code that searches Google's images using a random keyword. It presents these images in a ItemsControl and allows the user to use a standard Cinch V2 event to command Action to fire a command in the GoogleImageSearchViewModel when the user MouseDowns over one of the images in the ItemsControl. The Google searching can take some time to do, so this calling is wrapped up in a new UI service to fetch the image URLs, which uses a Task Parallel Library Task to conduct this work.

It also hosts the special TranstionElement region adaptor we discussed earlier.

When the command is run in response to a MouseDown in GoogleImageSearchViewModel, a new view is requested to be put into the TranstionElement region adaptor. As you would expect, this new view transitions into place using the currently selected transition type in the GoogleImageSearchViewModel.

Let's start with the GoogleImageSearchView; here is the most relevant parts of its XAML:

It's all pretty standard stuff, apart from two things, one being the TransitionElement control from the Transitionals.dll, and the other being a special threading control which I have developed which has three items in it, where only one is shown at any one time. It can show either the Content or a Busy control, or a Failed control; this showing/hiding is handled from the GoogleImageSearchViewModel

And here is its code-behind. Note the use of the IViewContext that we saw earlier when we were looking at the ShellViewModel, where the ShellViewModel sets the random keyword and region name for the GoogleImageSearchView.

I think most of that code is pretty self-explanatory; most of it is using Cinch V2 Core UI Services, namely IMessageBoxService and IViewAwareStatus.

But GoogleImageSearchViewModel also makes use of a special service (of type ItemRepository) specifically for the GoogleImageSearchViewModel. This service is the one that is using the Task Parallel Library Task; as such, when we use this potentially long running service, we can signal the threading control in the view to show a busy indicator while we are doing the work and to show either content or the failed control when we either finish getting the results or get an Exception. This should be clear enough from the code within the GoogleImageSearchViewModel.

where the runtime version of this service looks like this, where we use the Task Parallel Library to conduct this fetching using a Task (as I say, this takes no time at all, but it does show you how you might call something using a Task that would take a long time):

And here is a design time service, which is actually in an entirely different project, that does not even have to be referenced by any other project. Basically, as long as the project that holds the design time service references MEFedMVVM.WPF, it should be resolved at design time and show up in Blend.

One important note is that I am using Windows 7, so the design time service shown below uses paths found to sample images on Windows 7. You may have to alter these paths if you are not using Windows 7.

And to prove that this all works OK, let's go back to our original screenshot of this Cinch V2 with Prism solution in Blend 4.

See that all is good. I prefer the way that MEFedMVVM deals with design time data, as opposed to how the Blend d: design time tags work, as they assume a default constructor is available for your ViewModel. I have to say in my production code, I rarely find that I have ViewModels which have a default constructor; they normally always rely on some context or services. Also, using the d: Blend design tags means you mock the whole ViewModel. It should be the services that provide the data, so they should be mocked, not the entire ViewModel. Also, Blend requires all get/set properties to do this mocking, which I think encourages bad design.

But hey, that is just my 2 cents.

Demo 2: Architectural overview

Demo 2 is available in CinchV2AndPrismModulesRegions.zip at the top of this article.

The second demo article included in this article is designed in a more traditional Prism style, with separate Modules (projects) which are all brought into a single application at runtime.

Personally, I am not a massive fan of Modules, and prefer my solutions to be structured something like this:

Shell project

Views project

Controls project

ViewModels project

I think, for me, that shows much better separation of concerns (SOC) than that used by adopting the Prism Modules paradigm. I mean, if you follow the separate ViewModels project, and it has no knowledge of any of the WPF/SL specific DLLs, such as PresentationCore, and someone goes to add something like that, they are more likely to think, hang on here, why am I adding this DLL to the ViewModels project? But I know I am more than likely in the minority here, so as I say, this demo goes about showing you how to use Cinch V2 with all the standard Prism goodies like Modules/Regions etc.

There is a single shell window that has a single TabControl region (using the standard Prism TabControl region adaptor) which will get two views loaded into it at runtime. The two views are located within two separate modules.

There is a welcome view/module which simply shows a simple text item, and utilises a Cinch V2 MEF injected ViewModel, and it also makes use of several Cinch V2 Core UI Services, namely the IMessageBoxService and IViewAwareStatus.

There is a list view/module which simply shows a list of items, and utilises a Cinch V2 MEF injected ViewModel, and it also makes use of several Cinch V2 Core UI Services, namely the IMessageBoxService and IViewAwareStatus and also shows the use of a multithreaded custom service, where there is also a design time service available.

Demo 2: What does it look like?

Well, recall I said there was a simple Shell Window with two Tabs inside a TabControl region, where there were two modules, a welcome view and a list view. The demo 2 screenshot is shown below. Granted it will not win any prizes in a beauty contest, but it does show that Prism/Cinch V2 work together with no problems.

And here is screenshot of it in Blend 4, where in the demo 2 application, I have provided a default design time data access service for the list module to use.

Demo 2: How does it all work?

These next sections will walk you through how it all works.

Demo 2: The Shell

The first step I carried out when building this demo was to create the Shell, which obviously meant getting all the relevant DLL references, but you can see that from the actual attached demo code. The Shell is a very simple Window which has the following XAML, and it really is just a region container for the two other module views to be loaded into. Like I say, in a production system, your Shell would obviously do a lot more and look a lot better than this; this is just a demo.

And here is its code-behind; note that it is marked with a MEFExportAttrtibute, which allows the MEFCompositionContainer (we will see that next) to be able to resolve the Shell type and any MEFImports the Shell may require. It should be noted that in this demo, the Shell does not need to satisfy any other Imports, but in real life code, it more than likely would, so it is good practice to Export the Shell; it is also the defacto way that Prism works in V4.

Demo 2: Bootstrapper

The next thing you must do when creating a Prism V4 application is to create a bootstrapper which inherits from MefBootstrapper. This is where the Shell is created and other Prism related overrides should be done.

There are a few things to note in there to do with getting Cinch V2 to work nicely with Prism; these things of note are:

That the MEFedMVVM (therefore Cinch V2) IComposer interface is implemented such that we can instruct MEFedMVVM to use the same CompositionContainer and Parts (Exports/Imports) as Prism. You can literally follow the example in this demo and that is all you need to do.

That we add the relevant catalogs to make Cinch V2/MEFedMVVM work in the ConfigureAggregateCatalog() override.

That the following line is run in the CreateShell override MEFedMVVM.ViewModelLocator.LocatorBootstrapper.ApplyComposer(this);.

That is all you need to do to get Cinch V2 (and remember Cinch V2 makes use of MEFedMVVM for ViewModel resolution) /Prism to work together. Simple, isn't it?

Now that we have a bootstrapper, we need to make sure it is called, which is typically done in a Prism application in the App.xaml.cs code, as follows:

Demo 2: Welcome Module

WelcomeModule is a very simple module that has a single view/Cinch V2 based ViewModel, and as such, it must reference the MEFedMVVM.WPF DLL and Cinch.WPF DLL, and the Prism DLLs, as shown below.

There is one special thing you must adhere to when referencing the Cinch.WPF and MEFedMVVM.WPF DLLs. They must be set with Copy Local set to false. This is to do with the way the Bootstrapper's MEF AggregateCatlog builds up the Imports/Exports. If you do not set "Copy Local" to false, then more than one Import/Export may be found for a particular MEF part contact name, which causes issues for MEFedMVVM.

Simply make sure that you have "Copy Local = False" for the two references, Cinch.WPF and MEFedMVVM.WPF for any custom module you create, and all will be cool.

Now that you have the references sorted, all you need to do is create a module, which is done as follows:

There is one thing that you must ensure for each module that you include, which is to make sure it is outputting to a special folder that was included in the Bootstrapper code to scan for any custom modules. This is shown below for the WelcomModule, but is the case for any custom module you write.

It can be seen that this WelcomeModule simply shows a new instance of a WelcomeView in a region that was declared in the Shell. So let's have a look at the WelcomeView.

Like I say, the WelcomeModule is not that complicated. And as such, all its WelcomeViewModel does is use one of the standard Cinch V2 services, in this case the IMessageBoxService/IViewAwareStatus to show a message when the view loads (which it knows using the IViewAwareStatus to tell the ViewModel the View has loaded).

Demo 2: List Module

The second module in this demo uses a runtime multithreaded service which simulates fetching a list of data from somewhere that would take a long time (OK, in the demo, it does not take a long time, but it shows you how to do it), and it also shows how to use a design time service to provide design time data.

The way you must set the MEFedMVVM.WPF and Cinch.WPF references to have "Copy Local=False" applies here as well, as does changing the build output path to be the "Modules" folder of the overall solution.

Whilst the DisciplesListView is only slightly more complicated than WelcomeView, in that this time we are displaying a list of items, and there is a simple DataTemplate to style the data items in the list. Here is the full XAML for the DisciplesListView; again, notice that DisciplesListViewModel is wired up using MEFededMVVM.

And DisciplesListViewModel looks like this, where it can be seen that it not only uses some of the core Cinch V2 services, but also makes use of a special service (of type IDisciplesListProvider) specifically for the DisciplesListViewModel.

Where the runtime version of this service looks like this, where we use the Task Parallel Library to conduct this fetching using a Task (as I say, this takes no time at all, but it does show you how you might call something using a Task that would take a long time):

And here is a design time service, which is actually in an entirely different project, that does not even have to be referenced by any other project. Basically, as long as the project that holds the design time service references MEFedMVVM.WPF, it should be resolved at design time and show up in Blend:

And to prove that this all works OK, let's go back to our original screenshot of this Cinch V2 with Prism solution in Blend 4.

See, all good? I prefer the way that MEFedMVVM deals with design time data, as opposed to how the Blend d: design time tags work, as they assume a default constructor is available for your ViewModel. I have to say, in my production code, I rarely find that I have ViewModels which have a default constructor, they normally always rely on some context or services. Also, using the d: Blend design tags means you mock the whole ViewModel. It should be the services that provide the data, so they should be mocked, not the entire ViewModel. Also, Blend requires all get/set properties to do this mocking, which I think encourages bad design.

But hey, that is just my 2 cents.

That's all folks

I hope that I have shown you in this article that you really can use Cinch V2 with Prism with absolute ease and get the best out of both frameworks. You know, if you like Prism's regions/modules, you can use them whilst still taking advantage of Cinch V2s services, ViewModel base classes, and extra utilities. They just work together seamlessly, largely thanks to MEF.

As always, if you like what you have seen, please spare some time to add a comment and a vote, they are always welcome.

One thing that I always find missing from a framework is a login module. This is usually worth its weight in gold. Just to be able to supply credentials and have it validate securely would be a huge help in any framework. Any plans of this being in here or any modules you are aware of that can be plugged into it?

System.NullReferenceException
Object reference not set to an instance of an object.
at CinchV2AndPrismRegions.ViewModels.ShellViewModel.ViewAwareStatus_ViewLoaded() in C:\csharp4\CinchV2AndPrismRegions\CinchV2AndPrismRegions\ViewModels\ShellViewModel.cs:line 66

I am attempting to add a close button to the tabbed view of your Cinch/Prism/Modules approach. I am basing it on a project called PrismQuickStart2 someone wrote that has the close "x" button. Theirs isn't using cinch for event handling which is what I'd like to do (just to know I can).

in the following style resource. The view model's CloseTabbedViewAction is not getting called when I press the x button which is the problem. I can, however, get the command handler to execute if I place the eventToCommandTrigger on a regular label control elsewhere on the xaml page.

Hey man I had 1/2 hour free on the train on the way home so updated the regions/modules demo (2nd link at top of article) that now have closeable tabs.

Its easier than you had it but you were on right track, you simply need to do

1. Create custom TabItem style which has button, bind button to CloseViewCommand in VM
2. Have CloseViewCommand in VM which removes view from region manager
3. Use Cinch IsCloseable ViewModelBase property to bind to BoolToVisibilityConverter to dictate whether tab is closeable (you could have it disable close button too if you want that instead)