MEFedMVVM NavigationExtension

Introduction

Most of the MEFedMVVM features so far were all around discoverability of ViewModels, yet when building MVVM application sometimes you want to also have a mechanism to discover and launch views. If we look at web development its all about resources sitting on a server and you can launch/load a specific resource via a URI (Unique Resource Identifier). This mechanism proved to be a very easy and scalable way of locating views and within a Web Page you can link to other pages very easily. When building WPF applications that are purely content based such a mechanism would really come in handy, and if you think about it MEFedMVVM is all about discoverability so why not support this scenario.

Since this is not really part of the core MEFedMVVM I created an extension that you can use to accomplish this, MEFedMVVM NavigationExtension.

MEFedMVVM.NavigationExtension support both WPF and Silverlight 4.

 

Enter MEFedMVVM Navigation Extensions

The idea is to be able to specify to a View that it can be located by a unique identifier (a string) and then you can have someway of launching that view and render it in some container/host. Something like this

image

And you make the view discoverable by decorating it with this attribute

image

As you can see in the figure above, there are 3 magic attached properties that are attached to the “Invoker”

  • NavigationExtensions.NavigateTo
    • Specify the unique identifier (string) to locate the view. I use a URI format but you can use whatever you like as long as its unique
  • NavigationExtensions.NavigationHost
    • Specify where you want the View to be rendered
  • NavigationExtensions.NavigationParameter
    • Specify a Parameter to be passed to the ViewModel of the View. The reason why the parameter is passed to its ViewModel is because if you are doing MVVM then your View has no need for parameters, its the ViewModel that needs the parameter(after all the ViewModel controls the logic). We will see how you can still cheat and do whatever you like at the end of the day, the parameter can be passed to the View.

So one might wonder how will my ViewModel receive the parameter. This is done by your ViewModel being set as DataContext of the View (if you are using MEFedMVVM to link the View to the ViewModel this happens automatically) and also your ViewModel has to implement the INavigationInfoSubscriber interface. This interface defines 1 method OnNavigationChanged which will pass along the parameter and also give you an instance of the INavigationManager responsible for starting the Navigation.

image

 

Recap

So till now we can

  1. Make a View discoverable by specifying a Unique Identifier
  2. Specify an Invoker and give it enough information on what to render and where to render it
  3. And also specify a parameter to be passed

This pretty much covers the bare basics, let’s get a better understanding of what is a Host and what is an Invoker before we deep dive in more complex scenarios.

 

Host and Invoker Deep Dive

When building the NavigationExtensions I wanted to make sure that you can create your own handlers both for Hosts and Invokers, and what is the best way to do so if not with MEF Smile

There are 2 base classes you need to write in order to create your own handlers.

  • ControlNavigationHost
    • This is to create your own hosting control. Out of the box you get one which is ContentControlNavigationHost (it handles any ContentControl)
  • ControlNavigationHandler
    • This is to create your own invoker for a control. Out of the box you get one which is the ButtonNavigationHandler (it handles any ButtonBase)

The ControlNavigationHost has 4 methods that you need to implement (all method implementation would be usually one liners)

image

In order to make your own ControlNavigationHost discoverable by the NavigationExtensions simple Export it like this

image

The ControlNavigationHandler has 3 methods you need to implement

image

In the implementation you simple have to register to the Event you want and then call the OnEventFired protected method of the base class. here is an example

image

And again to make the handler discoverable you Export it like so

image

Please note: that its up to you how you want the creation policy to be (i.e. If MEF should create a new instance of the NavigationHandler or not but in this case you should always make it NonShared so that for each invoker in your application you have a different ControlNavigationHandler instance)

Apps are usually more complicated, so let’s dive into more complicated scenarios

Before we start going through these scenarios let’s have a look at some interfaces and classes that MEFedMVVM exposes for you to consume/implement

INavigationManager 

image

INavigationManagerProvider

Implement this interface on a class that will be passed as NavigationParameter and you will get injected with a INavigationManager responsible for that Navigation

image

INavigationInfoSubscriber

Implement this interface in your ViewModel to get passed the NavigationParameter.

image

NavigationCommand<T>

A NavigationCommand is just a DelegateCommand<T> BUT it implements the INavigationManagerProvider interface. When used as a NavigationParameter it will hold the instance of the INavigationManager so that you can do things such as Closing a navigation. We will see the NavigationCommand<T> being used in the first scenario below.

 

Scenario 1

Let’s say you have a dialog that shows some settings and when you are done you want to get those settings back to the original ViewModel that “started” the navigation to the Settings screen. Here are a couple of screen shots for such a scenario.

image

In order to do this we need the MainViewModel to expose a NavigationCommand<T>

image

and the Execute handler for this would be something like this

image

We will revisit the code inside the Execute Handler in a bit**…

Now we can specify that the NavigationParameter is this command so that the SettingsViewModel can execute this command when it is done and give us the ApplicationSettings object instance.

image

The Settings ViewModel implements the INavigationInfoSubscriber thus it will get injected with the NavigationCommand that we are passing to it via the NavigationParameter attached property

image

Once the Settings ViewModel calls the Execute on the _onSettingChangedCommand it will invoke the method inside the MainViewModel (OnSettingChangedExecuted) passing the new ApplicationSettings.

**One thing to note is that the MainViewModel is also calling CloseNavigation on the NavigationManager of the NavigationCommand. This is so that as soon as its done applying the new settings the Settings screen disappears.

Download the sample and play around with it to get a better feel of how this all works together (its under Samples/TestNavigation)

Scenario 2

Let’s say you have a sort of Wizard Step by Step UI.

image

In this case we want to chain the Navigation so that the CreateUserProfileViewModel send the UserProfile not to the MainViewModel (the ViewModel that started the Navigation) but to the ViewModel next in the chain i.e. the RenderUserProfileViewModel.

In order to do so both “Invokers” (i.e. the button for the CreateUserProfile and the button for the RenderUserProfile) must have the same navigation “invoker”. You do so by explicitly setting the NavigationHander attached property (this is an attached property that exposes the Navigation handler for an “invoker”).

image

Ok so now we have both “invokers” using the same NavigationHandler; because of this we can register to the NavigatingAway event of the INavigationManager inside the CreateProfileViewModel and pass the data we want to the RenderUserProfileViewModel (which is the NewNavigationInfoSubsciber in the NavigationEventArgs passed by the event)

image

So basically the CreateUserProfileViewModel (Step 1) could pass along data to RenderUserProfileViewModel (Step 2) and you can continue chaining like this one step after another.

NOTE: For Silverlight you instead of using the NavigationExtensions.NavigationHandler use the NavigationExtensions.ChainToElement and specify the other button (this is because there are issues around binding to custom attached properties in SL). This approach can also be used in WPF.

image

 

Download the sample and play around with it to get a better feel of how this all works together (its under Samples/TestNavigation)

Conclusion

One thing I love about this Extension is that it enables you to use View-First approach to MVVM in nearly any scenario. Yes granted sometimes its better to have ViewModel-First approach but in my experience if you can always work using View-First life becomes much more easy because your code is more loosely coupled. In fact this is one of the things I love about MVC and Web in general… Controllers never reference each other, A View has a controller and thats it. In MVVM we tend to complicate things by having Parent ViewModels that have Child ViewModels yada yada yada… just my 2 cents…

This is all still work in progress, it needs more testing from my end to make sure there are no side effects such as memory leaks etc yet feel free to poke around and play around with it. As always feedback/bug reports are very welcome.

Download the code from http://mefedmvvm.codeplex.com/SourceControl/list/changesets

ICommand discovery with MEF

Sometimes you are in ViewModel X and you want to execute a command on ViewModel Y. You do not want to link the 2 because of some constrains that that might impose. How can you leverage MEFs capabilities to overcome such a situation?

Easy have the ViewModel Y expose the command as a property just like you would have it for binding from the View, but also add an Export attribute on the property and give it a name

image

 

Now from ViewModel X simple imports the ICommand by specifying that same name (yes you can have the string as a constant, also I would advice to use constants to avoid conflicts in strings)

image

 

MEF will automatically get the command from ViewModel Y into ViewModel X for you. This works very nicely with MEFedMVVM since MEFedMVVM resolves all ViewModels via MEF thus you do not need to do anything to resolve the ViewModel or anything. You simply decorate the properties for Export and Import and viola you can start drinking beer Smile

Happy coding Smile

MEFedMVVM with PRISM 4

Today I was looking at PRISM 4 and how it uses MEF as its DI Container and I thought, wouldn’t it be cool if you could use the 2 together?

Update: Please also check out this post to see how you can use the same composition container for both PRISM and MEFedMVVM so that stuff like IRegionManager, IEventAggregator etc can be injected also in MEFed ViewModels

http://mefedmvvm.codeplex.com/workitem/15391

Why would it be cool?

PRISM brings to the table

– Region Manager
– Modules infrastructure
– Many other utilities and services that you can consume

MEFedMVVM brings to the table

– ViewModel injection in XAML
– Design Time vs Runtime services (so that you can inject design time services when in blend)
– ContextAware services such as IVisualStateManager

Having the 2 working together would be awesome. The question is can they work together?

…teasing… suspense … ok enough Smile

The answer is yes and very easily…

How to do it

In PRISM you need to create a bootstrapper that will basically compose your application. MEFedMVVM also has a sort of Bootstrapper where you can specify how you want to compose the MEF composition. So as such all you need to do is to have your PRISM bootstrapper also tell MEFedMVVM how to do the composition.

Let’s start by creating a PRISM bootstrapper

We need a class that inherits from MefBootstrapper and we will need to override a couple of methods. Here is the code to do this

public class Bootstrapper : MefBootstrapper

{

    protected override void ConfigureAggregateCatalog()

    {

        this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));

    }


    protected override void InitializeShell()

    {

        base.InitializeShell();


        Application.Current.MainWindow = (Shell)this.Shell;

        Application.Current.MainWindow.Show();

    }


    #region Overrides of Bootstrapper


    protected override DependencyObject CreateShell()

    {

        return this.Container.GetExportedValue<Shell>();

    }


    #endregion

}

Now lets enable MEFedMVVM

In order to do this we will simple need to implement the IComposer interface from MEFedMVVM and then return the AggregateCatalog property (that is given to us by PRISM)

#region Implementation of IComposer (For MEFedMVVM)


public ComposablePartCatalog InitializeContainer()

{

    //return the same catalog as the PRISM one

    return this.AggregateCatalog;

}


public IEnumerable<ExportProvider> GetCustomExportProviders()

{

    //In case you want some custom export providers

    return null;

}


#endregion

In this case we will return null as the GetCustomExportProviders. This is a feature used if you have some custom ExportProvider you want MEFedMVVM to use.

The last step (which is the actual line of code to enable MEFedMVVM) is where we tell the MEFedMVVM LocatorBootstrapper to use this class as runtime composer.

protected override DependencyObject CreateShell()

{

    //init MEFedMVVM composed

    MEFedMVVM.ViewModelLocator.LocatorBootstrapper.ApplyComposer(this);


    return this.Container.GetExportedValue<Shell>();

}

As you can see I have put that line of code in the CreateShell method so that the Composer is applied as early as possible so that all views can use MEFedMVVM.

 

Now you can start using MEFedMVVM as you would in a normal project… For example in the Shell you can say

<Window x:Class="MEFedMVVMAndPRISM.Shell"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="Shell" Height="300" Width="300"

        xmlns:mefed="http:\\www.codeplex.com\MEFedMVVM"

        mefed:ViewModelLocator.NonSharedViewModel="ShellViewModel">

and the ShellViewModel would be

[ExportViewModel("ShellViewModel")]

public class ShellViewModel

{

    public string Text { get; set; }


    public ShellViewModel()

    {

        Text = "Hello from the ViewModel";

    }

}

Of course here I am not really leveraging MEFedMVVM capabilities, yet the purpose of this post is not to show those capabilities but to show how you can use PRISM and MEFedMVVM together and take what is best from both. To read more on MEFedMVVM visit the codeplex site.

I create a small sample project to showcase both PRISM and MEFedMVVM working together.

Download sample

Capture

Adding more goodies in MEFedMVVM

Thanks to some good feedback from the community and also some really awesome help from Glenn Block and Sasha Barber, I added some new stuff to MEFedMVVM.

The core 3 additions are

- Reloading of design time data in Blend as you compile in Visual Studio (Patch by Chris Szabo)

      Before this patch you had to close and re open Blend everytime you did a change in your ViewModel for Blend to pick up this change. Chris Szabo sent me a code snippet showing me how I could overcome this issue. Very cool Chris!!!!!

- Added a new method in IComposer so that you can specify a list of custom ExportProviders.

      A user of Cinch suggested this feature since he had some ExportProvider he wanted to use in MEFedMVVM for versioning of objects. Now the IComposer has a new method that looks like this

image

You can return a list of ExportProviders or if you do not want to just return null. MEFedMVVM will attach its own ExportProvider even if you return null. (MEFedMVVM uses the ExportProvider for IContextAware services such as IVisualStateManager so that it can inject the View that requested the ViewModel)

-

- Added 2 new attached properties to make things more clear.

By default Exports in MEF are treated as Shared. This implies that if before you did an [ExportViewModel(“MyVM”] without specifying a [PartCreationPolicy(CreationPolicy.NonShared)] the ViewModel would be exported as a shared item so all imports get the same instance of the ViewModel. Also this implies that the ViewModel would never be garbage collected since MEF will keep its instance alive. The workaround for this would be to specify [PartCreationPolicy(CreationPolicy.NonShared)] where you put the ExportViewModel attribute. Once you know this its all good but if you are new to MEF maybe it is not that obvious that exports are by default Shared. So in order to make this crystal clear I added 2 new attached properties SharedViewModel and NonSharedViewModel, which will impose the CreationPolicy on the ViewModel you want to export (this is like doing the CreationPolicy on the Import if you were doing standard MEF). Glenn Block came up with this idea, kudos to Glenn!!!!

 

Besides these changes I also did some bug fixing here and there and some minor changes as per request …

- Export for ViewModel had an incorrect ImportCardinality. now the ImportCardinality is set to ExactlyOne.
- DataContextAware ViewModels used to call the DesignTimeInitialization 2 times, this is now fixed.
- Exposed the MEFedMVVM CompositionContainer, you can now access the CompositionContainer directly by doing this ViewModelRepoitory.Instance.Resolver.Container. This is useful if you want to get some Exported object from the CompositionContainer that MEFedMVVM is using.
- Fixed issue with ImportMany. This was a problem in the ExportProvider of MEFedMVVM.
- Added propertyObserver. you can see more about this here
- Fixed issue with DelegateCommand (was not hocking automatically to the CanExecute of the Command Manager in WPF)

Hope you enjoy MEFedMVVM and as always keep feedback coming !

INotifyPropertyChanged… I am fed up of handling events just to know when a property changed

The INotifyPropertyChanged is what tells the WPF/SL binding that a property changed and that the binding should be updated. For this purpose its quite good. But what many times we end up doing is; handling the PropertyChanged in code so that we get notified that a property changed. An example is a ViewModel that need to know when a property in the underlying model changed and if it did it will do something to facilitate the View.

Doing this in code is a bit ugly because you base everything on “magic strings”.. something like this

image

Another problem is that if you use an anonymous delegate you need to do loads of tricks in order to unregister to the event.

In order to over come this I created a PropertyObserver that handles these 2 issues. (Please note that there are already others, Philip Sumi has a good one here and  Josh Smith has a good one here. I created my own since I wanted to have extra + different way of doing it). Also this problem can be solved easily using Rx, I am doing this sample so that you do not need to depend on Rx.

The implementation I did is very simple, I created a PropertyObserver class that uses lambdas so that you tell it what property you want to subscribe to and pass an action to do your “Property Changed handling”. What I also did is an attached method so that all objects that implement INotifyPropertyChanged can simple handle the property changed… so the code looks like this

image

One would ask and how do I unregister? is this using weak event pattern? The answer is NO. I wanted to keep it simple and cross platform (for WPF and SL). what you can do is a more Rx approach… basically in RX if you subscibe to something you get an IDisposable in return so that you can Dispose (i.e in our case unsubscribe) when you want like this

image

as you can see here I am wrapping the call in a using statement… but if you need to unsubscribe in any specific state you can store the IDisposable that you get from the Do call and call Dispose to unsubscribe.

Many times you need this for only one time i.e a property changes you do something and you do not want to get called any more times. For this I created a DoOnce. This will unsubscribe for you once the property changes once. The API is very similar and looks like this

image

That’s more or less it.

Big thanks go to Diego Colombo and John Rayner (two champs that work with me) for the help and input they gave me on this :) You rock guys!

You can download the code here.

OR if you have MEFedMVVM download the latest version since its in MEFedMVVM.

MEFedMVVM: Testability

>> If you are new to MEFedMVVM, I suggest you first read this article to get started: https://marlongrech.wordpress.com/2010/05/23/mefedmvvm-v1-0-explained/

Having solid unit tests is key to have successful projects. When these projects get really large and especially if there are several developers on the project. Once you get used to unit testing you feel un-complete if you do not unit test your code. One of the virtues of the Art of Unit testing is Mocking. Mocking is really important while you are unit testing so you remove all the dependencies of the code you are testing and you just test what you really want to test.

“Testability” is something that I take very seriously and in MEFedMVVM it was no exception.

Unit testing best friend is Dependency Injection(since with this you can mock all the dependencies); MEFedMVVM leverages MEF thus this comes for free. Having said that what is also really cool with MEFedMVVM is that all services exposed can be mocked. By services I do not just mean backend services (example a service that connects to a DB to load data) but also UI services (or as I usually refer to them MEFedMVVM IContextAware services).

Here is a sample unit test (you can see this in the source code of MEFedMVVM) Please note I am using Rhino Mocks as my mocking framework for this sample.

 

image

As you can see in this test I am testing that when I set the SelectedUser property on the ViewModel (which would be updated by binding at runtime) I send a mediator message. I can do this because the Mediator that comes out of the box with MEFedMVVM is exposed as an IMediator thus I can easily mock it and test that I am doing the right calls to the Mediator.

What is really cool is that I can even mock behaviours like ViewModel setting a Visual State or even testing that on Loaded event of the View the ViewModel does something (in my case it will load some data from a service)

image

As you can see in the above code, I am testing that when the ContainerLoaded event (which is an event in the MEFedMVVM IContainerStatus an IContextAware service that abstracts the Loaded and unloaded event of the View) of the IContainerStatus is raised, I am setting the “Welcome” state via the IVisualStateManager ( which is another MEFedMVVM IContextAware service that lets you set a specific VisualState on the View).

I am also testing that the first user is selected by default and that my data is loaded.

Conclusion

I think the fact that I can mock any dependency that my ViewModel has (even if it is a “UI” thing) is a really powerful thing! Currently MEFedMVVM is helping me and my team a lot and we are finding that Unit Testing with MEFedMVVM is really awesome. Having said that if you have any comments/suggestion on how to make testing easier with this library, Please do let me know.

Thanks

Download MEFedMVVM

http://mefedmvvm.codeplex.com/

How does MEFedMVVM compose the catalogs and how can I override the behavior? – MEFedMVVM Part 4

Some content may be out of date. See latest blog on changes made here.

Introduction

As you already know, MEFedMVVM is capable of composing the catalogs for you so that you do not have to worry about it both in Silverlight and in WPF. The composition happens a bit differently in SL and WPF so I will divide the “How to write a composer” section in 2, how it works for SL and how it works for WPF. But first let’s see what is common.

Please Note: This article is for advanced scenarios of using MEFedMVVM if you are using MEFedMVVM with its default behavior you do not need to do this since by default MEFedMVVM does the composition on its own. Yet if you want to have a silverlight app that uses multiple XAP files or a WPF app that is loading dlls that are not referenced by the main application and that reside somewhere else then the exe directory (or even Extensions folder of the base directory).

The LocatorBootstrapper and the IComposers

If you have been looking in the code of MEFedMVVM you’ll know that there is a class called LocatorBootstrapper. This class is responsible of checking if the MEF composition is done and if not I will ask the Composers to do so.

The “Composers” ? What the hell are these??

Basically these are instances of IComposer and there are 2 of these in the LocatorBootstrapper, one for DesignTime composition and one for Runtime. By default MEFedMVVM uses its own implementation of the IComposer which are DefaultRuntimeComposer and DefaultDesignTimeComposer but if you want to do something smarter (I will talk more on this later in the article) you can call the ApplyComposer method of the LocatorBootstrapper and inject a runtime composer that you implement. You must make sure to make this call before anything gets composed. A good place to do this is in the Application class constructor.

In the current version you cannot supply a DesignTime IComposer. I could have made the ApplyComposer API to accept another composer for DesignTime yet this method would be called always too late from Blend. I am currently working on a solution for this. Having said this, I do not see why you would want to override the default DesignTime composer since you still have control. I will talk more on this later in the post but any assembly marked with the DesignTimeCatalog will get picked up and loaded by the DefaultDesignTimeComposer. The only case where you would want to override this behavior is if you want to ignore the DesignTimeCatalog attribute. This is not suggested since not only it will slow down a lot the composition since blend loads many assemblies but it can also cause exceptions in Silverlight. I am open for suggestions so if you have any please let me know.

How can I create a Composer?

You do so by implementing the IComposer interface which looks like this.

   1: public interface IComposer

   2:     {

   3:         bool InitializeContainer();

   4:     }

In the InializeContainer you should put the code to initialize the Container and call CompositionHost.Initialize. (For WPF there is a catch that I will explain in the WPF section of the post).

Understanding and writing a Composer for Silverlight

What do the default MEFedMVVM composer do for SL?

The DesignTimeComposer will load all the assemblies that are decorated with the DesignTimeCatalog attribute in the AppDomain of Blend by using a trick explained here and create a CompositionContainer with MEF AssemblyCatalogs. So even if you have multiple XAP files MEFedMVVM will still get resolved as long as you put the DesignTimeCatalog attribute. If you forget to do this MEFedMVVM will put a message in the output window saying “No assemblies found for Design time. Quick tip… do not forget to put the DesignTimeCatalogAttribute for the assembly that contains your design time stuff. Even if its just a ViewModel you want to load.”. Yet in order to get this you need to have Blend attached with VisualStudio. (I am working hard on a solution to make this more obvious).

The Runtime Composer does not do anything. No really! It does not. The implementation simple returns true in the InitializeContainer method. This is because in SL CompositionInitializer.SatisfyImports (a class that is not present in WPF since WPF does not have System.ComponentModel.Composition.Initialization.dll) will create a container from the existing XAP.

So if you want to override the Runtime behavior for the SL version of MEFedMVVM you do not even have to call LocatorBootstrapper.ApplyComposer because for SL this is not doing anything anyway! But for the code to be the same for SL and WPF maybe its best if you do the call.

Quick Tip: If you are overriding the default container do not forget to add the an assembly catalog for the MEFedMVVM library, if you want to get injected with services that come out of the box with MEFedMVVM such as IVisualStateManager. Here is some sample code that is loading different XAP files

   1: AggregateCatalog aggregateCatalog = new AggregateCatalog();

   2: //add the catalogs for the current assembly and the MEFedMVVM assembly since we are overriding the default behavior

   3: aggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(ViewModelLocator).Assembly));

   4: aggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(App).Assembly));

   5: var listOfPluginXAPs = new[] { "Plugin1.xap" };

   6: foreach (var item in listOfPluginXAPs)

   7: {

   8:     DeploymentCatalog deploymentCatalog =

   9:       new DeploymentCatalog(item);

  10:  

  11:     aggregateCatalog.Catalogs.Add(deploymentCatalog);

  12:  

  13:     deploymentCatalog.DownloadCompleted += (s, args) =>

  14:     {

  15:         if (args.Error != null)

  16:             Debug.WriteLine("Error downloading plugin from " + item + " Exception: " + args.Error);

  17:         if (args.Cancelled)

  18:             Debug.WriteLine("Downloading of plugins was cancelled");

  19:  

  20:         PluginsDownloaded = true;

  21:     };

  22:  

  23:     deploymentCatalog.DownloadAsync();

  24: }

  25: CompositionHost.Initialize(aggregateCatalog);

Understanding and writing a Composer for WPF

What do the default MEFedMVVM composer do for WPF?

The DesignTimeComposer will load all the assemblies that are decorated with the DesignTimeCatalog attribute and create an AssemblyCatalog for each one. If you forget to put the DesignTimeCatalog attribute MEFedMVVM will put a message in the output window saying “No assemblies found for Design time. Quick tip… do not forget to put the DesignTimeCatalogAttribute for the assembly that contains your design time stuff. Even if its just a ViewModel you want to load.”. Yet in order to get this you need to have Blend attached with VisualStudio. (I am working hard on a solution to make this more obvious).

The RuntimeComposer will create a DirectoryCatalog for the AppDomain base directory and also checks if there is an Extensions folder and if so it will create a DirectoryCatalog for that folder as well. So yea if you have a set of plugins that are not being referenced by the main application, you do not even need to override the default behavior since you can make the plugins compile in an Extensions folder and MEFedMVVM will still load those assemblies. This is the code that creates the MEF catalog for the Default WPF Runtime Composer.

   1: var catalog = new AggregateCatalog();

   2: var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;

   3: var extensionPath = String.Format(@"{0}\Extensions\", baseDirectory);

   4: catalog.Catalogs.Add(new DirectoryCatalog(baseDirectory));

   5: catalog.Catalogs.Add(new DirectoryCatalog(baseDirectory, "*.exe"));

   6: if (Directory.Exists(extensionPath))

   7:     catalog.Catalogs.Add(new DirectoryCatalog(extensionPath));

   8: return catalog;

The “catch” with WPF version of MEFedMVVM

WPF does not have System.ComponentModel.Composition.Inialization so as such it does not have CompositionHost and CompositionInitializer but Mr.MEF, Glenn Block created this dll for us over here, and we are using it in MEFedMVVM, thus we benefit from the same code for SL and WPF. The only difference is that you have to do a trick when creating the CompositionContainer. You need to specify the ExportFactoryProvider when creating the CompositionContainer. like so

   1: var provider = new ExportFactoryProvider();

   2: var container = new CompositionContainer(catalog, provider);

   3: provider.SourceProvider = container;

   4: CompositionHost.Initialize(container);

If you fail to do so MEFedMVVM will not resolve the ViewModels and the Services since MEFedMVVM using ExportFactory to get the imports.

Enough talking (well as such its blogging :) ) give us some code!

I did 2 samples one for Silverlight by using DeploymentCatalog to load assemblies from different xap files and one for WPF using DirectoryCatalog to load plugins from a folder called Plugins (this was just to show how you can do it because as such I could made the plugins compile in a Directory called Extensions and it would still have worked).

The source can be found in by download the code from http://mefedmvvm.codeplex.com/SourceControl/list/changesets there is a folder samples where you will find these 2 samples.

Conclusion

As you can see MEFedMVVM can also be used in more advanced scenarios where you want control over the MEF Composition of Catalogs. The default composition will work for most of the apps, yet for some (such as multiple XAP SL applications) you must have control over the composition.

As always feedback is much appreciated.

Download MEFedMVVM and start MEFing it up!

http://mefedmvvm.codeplex.com/