MEFedMVVM v1.0 Explained

Introduction

In this post I will cover the basic things you need to know for quickly start building MEFedMVVM powered WPF and Silverlight. For those new to MEFedMVVM here is a quicky on what MEFedMVVM is all about.

MEF is an awesome framework for introducing extensibility in your projects. MEF is built in a generic manner so that you can use it in many different scenarios, example Backend service, ASP.NET application and yes also WPF and Silverlight. Because of MEF being so generic there is no out of the box support for MVVM (example ViewModelLocator so that a View can request a ViewModel to get injected in DataContext, etc…). One of the goals of MEFedMVVM  is to do all the MEF plumbing for you so that you can simple say “I want to Export this ViewModel” and then you can have a View that says “I would like that specific ViewModel” and BANG, MEFedMVVM will do all the plumbing by leveraging the Mighty MEF. Besides this MEFedMVVM has DesignTime Data capabilities. MEFedMVVM is very much Blend Aware so that you can add design time stuff (you’ll read more about this in a later section).

>> Are there any special requirements to use MEFedMVVM?

Yes and no 🙂 All the testing I did was with .NET 4.0 for WPF and Silverlight 4. Having said that there are users of MEFedMVVM using .NET 3.5. Till now no one reported any major bugs but be warned that myself I only tested MEFedMVVM with .NET 4.0 for WPF and Silverlight 4. With regards to MEFedMVVM at design time; only Blend 4 RC or newer are supported by MEFedMVVM, so unless you have Blend 4 RC or newer there is a chance that MEFedMVVM does not work as one would expect (especially with Blend 4 Beta).

>> How stable is the current code?

It’s pretty much stable. I am really pleased to announce that I marked change set 48734 as stable on Codeplex. Myself and some other guys at work are using it already in production projects and till now we did not find any issues. Having said that if you encounter any issue please contact me and I will do the best I can to help out.

>> I am already using an MVVM Framework! Can I use MEFedMVVM side by side?

Do not worry! If you are using an MVVM Framework go on using it, MEFedMVVM can work side by side. I am currently working with some MVVM library authors to provide samples of how to use MEFedMVVM with other MVVM libraries. On the other hand if you want to use MEfedMVVM on its own, well MEFedMVVM  will give you some basic things out of the box as well such as DelegateCommand<T>, Mediator, NotifyPropertyChangedBase and Visual State Management.

How can I start?

Let’s start by having a look at some core things in MEFedMVVM that you will be using to expose ViewModels for View to consume.

So first of all you have to add a reference to MEFedMVVM.WPF/MEFedMVVM.SL depending on if you are in SL or WPF (Api is 100% the same for both platforms!). You also need to add a reference to System.ComponentModel.Composition otherwise VS will not let you use the ExportViewModel or ExportService attribute.

Lesson 1: How to expose a ViewModel so that a View knows how to consume it?

MEFedMVVM: ExportViewModel

 

 

 

 

In order to expose a ViewModel all you have to do is decorate your VM with the ExportViewModel attribute and give the ViewModel a name so that the View can request that ViewModel by using the name you assigned to the ViewModel.

You might be wondering at this point, but how does that work? Well easy, MEFedMVVM is using MEF to get an Import from the Contract name (the name you gave the ViewModel) ignoring the type since a ViewModel can be of any type in MEFedMVVM (this was done like so so that you can have MEFedMVVM working side by side with any other MVVM library. MEFedMVVM does not dictate that your ViewModel has to inherit from any base class). A viewmodel import in MEF terms would look like this [Import(“ViewModelName”]public object ViewModel {get; set; }. Of course this is not how MEFedMVVM is doing it, in order for this to work MEFedMVVM had to quite a bit of plumbing to get this right 🙂

[Advanced] Besides a normal export of a ViewModel can also do a DataContextAware export. This is an advanced feature and there are only few use cases for it. To know know more on what this is read the DataContextAware section in this article.

 

 

Lesson 2: How can a View consume a ViewModel?

image

 

 

In order to make a View consume a ViewModel that you exposed via the ExportViewModel you have to specify it in the attached property ViewModelLocator.ViewModel.

By specifying this property MEFedMVVM will go looking for the ViewModel that has the name you specifying in the attached property.

[Advanced]In case MEFedMVVM does not find the ViewModel you requested it will store a weak reference of the View and the contract name it was requesting so that if a MEF recomposition happens it can satisfy that import and inject the ViewModel. This is a handy feature if you are build Silverlight applications that use Partitioning and downloads parts of the application async.

Where are we?

Well that’s it. With those 2 steps you are pretty much done! Expose a ViewModel and have a View consume it. But for more complex scenarios you need more then that!

Here are some of the main MEFedMVVM features and briefly how to use them… This will enable more complex scenarios, if you just want a ViewModel injected in a View you can stop here.

>> Dependency Injection for Runtime, Design Time and why not have Both if you are lazy 🙂

In a classical MVVM the usual approach is that the ViewModel does logic to facilitate the View. BUT a ViewModel does not do stuff like connecting to a database and get records from the database! That is the responsibility of a backend service which would then be consumed by the ViewModel (via Dependency Injection so that we can mock the service while testing) to get the data and expose it to View. With MEFedMVVM you can have dependency injection of services via standard MEF Imports.
So you can do like this (by using [ImportingConstructor])

image  OR like this

image

As you can see this is standard MEF exports, nothing to it… what is cool is that you do not have to worry about asking the CompositionContainer (or maybe in SL your CompositionInitializer) to satisfy your imports and clutter the code of your ViewModel. MEFedMVVM will do it for you!

The exports can be done via standard MEF exports (i.e [Export]public class MyService { } ), BUT MEFedMVVM has an export attribute of its own specifically for services so that you can control if the Service is injected in Runtime only – DesignTime only or if you want for both (obviously if you want it for both you do not need to use the ExportService because the same behaviour can be achieved via a standard MEF Export, but its there just in case the Framework will start doing something smarter with it in future).

So a Design time service would look something like this ( in this implementation you would make the service return design time data)

image

and for runtime it would be like this (in this implementation you would have your service connecting to the DB/Web Service/ what have you )

image

>> IContextAware services

This is a very powerful technique to have services that are “ContextAware”. What does that mean? what do you mean by context aware? I get a lot of questions on this and I think in the next version of MEFedMVVM will change its name to IViewAware since the context in MEFedMVVM will be the View requesting the service.

The idea is that if your service implements the IContextAware interface of MEFedMVVM, MEFedMVVM will call the InjectContext passing the View that is requesting the ViewModel which requires the service. Confusing isn’t it 🙂 Here is a Diagram that explain what happens

image

 

 

So why is this so cool? Well with this in place you can do really cool stuff. How many times did you have to create an attached property in order to have you View some MVVM friendly thing? Well now instead of an attached property you can have a service and this service will get injected in the ViewModel thus the ViewModel has now much more control then a simple attached property.

A very good example of this is the IVisualStateManager that comes out of the box with MEFedMVVM. Basically with IVisualStateManager a ViewModel can invoke VisualStates on a View with in code without coupling the ViewModel and the View. You can even mock the IVisualStateManager while doing unit testing and do assertions if the ViewModel did not invoke the correct state at the correct time.

Out of the Box MEFedMVVM has 3 IContextAwareServices

>> IVisualStateManager – This is used to invoke VisualStates. This is definitely my favorite and probably the answer to “how do I do animations in MVVM and give full control to the Designer?”

>>IContainerStatus – This was more of an experiment but hey it is quite useful sometimes. Basically the IContainerStatus hooks to the Loaded and Unloaded events of the View and raises its own events. In this manner the ViewModel can do stuff on load of the View (example only load data when the Loaded event is raised and maybe dispose that data when unloaded).

>> IDispatcherService – This is an abstraction on the Dispatcher so that the ViewModel can invoke operation to happen strictly on the Dispatcher thread.

>> More to come 🙂

 

 

 

 

>> Mediator

As such the Mediator has nothing to do with MEF but when it comes MVVM I feel that Mediator is essential! I use it a lot because it is a way of communicating between entities without each entity knowing of the other. Just like an Event Aggregator. What is interesting is how I exposed this in MEFedMVVM. So for starters there is an interface IMediator so that you can mock it as you like. But what is really cool (and this is a MEF feature) is that a MEdiator would only work if the instance is shared. Now a standard MEF import would be creating a new instance of the object being requested by default, BUT if you decorate the Export with [PartCreationPolicy(System.ComponentModel.Composition.CreationPolicy.Shared)] MEF will do some magic and instead of creating a new instance for the service, it will staisfy the import using a shared instance of that class. Of course this technique can be used for any kind of export, so if you every have a service that need to be shared all you have to do is put the PartCreationPolicy on top of the Export to export the service.

DESIGN TIME >> When you say this will work in Blend what exactly do you mean by that?

Let’s say you have a property in your ViewModel and in the constructor of the VM you set this property to some string, let’s say “Hello World :)”. In your View you wire up the View to the ViewModel using MEFedMVVM and in your View, you create a TextBlock and bind to the ViewModel property. When you open up Blend (if not already in it, you will see the text “Hello World :)” rendered on the screen! and yea if you run the app you would also get the same behavior 🙂 Basically the idea is that MEFedMVVM will do a MEF composition for design time as well as at runtime. for design time MEFedMVVM does some clever things to build the composion so that it ensures that all your Views get satisfied with the ViewModels.

For Design Time, MEFedMVVM offers loads of features besides ViewModel injection. Here are some other goodies that come out of the box with MEFedMVVM.

>> Design Time Services (explained above)
If you you want to make sure that your Designer has full Design Time Data and maybe even behaviour you can do this via Design Time Services. In order to do this you have to design your ViewModel (usually all of us do it that way by default to support unit testing) to use Dependency Injection. Besides this you need to create a Service for Design time (just like you would mock a service for your ViewModel for Unit Testing) and expose that service by decorating it with the ExportService attribute and pass ServiceTypes.DesignTime. Your service would look something like this

 

[ExportService(ServiceType.DesignTime, typeof(IIngredientService))]
public class DesignTimeIngredientService : IIngredientService
{
……
}

This is an opt in feature of course but I recommend that you have a look at it and give it a try since it’s really awesome. Basically if it is working at design time it will work at runtime (unless you have a bug in the runtime service of course 🙂 )

>> IDesignTimeAware

image

This interface does some magic at design time and does nothing at runtime. Some times you have some property in the ViewModel (or maybe even some operation) that you need to execute on the ViewModel at Design time. With the IDesignTimeAware you can do exactly that. In order to leverage this feature your ViewModel must implement the IDesignTimeAware interface and this will include a DesignTimeInitialization method. In this method you can write your own code and MEFedMVVM will make sure to invoke that method when the ViewModel is initialized at design time. At runtime this method will be ignored by MEFedMVVM.

 

 

 

>> DataContextAware ViewModels

This is one of my favorite features I must say! The scenario for this feature is very specific. You would want to use this feature if >>

1. You have an implicit DataTemplate (ex: <DataTemplate DataType=”{x:Type my:ViewModelX}”> ) thus at runtime a ViewModel is injected by the WPF runtime but in Blend the designer is left without any design time data!
2.  You have a case of Parent Child ViewModel. Example: You have a ViewModel that has a list of child ViewModels and in the UI you bind to the list of ViewModel in an ItemsControl and have an ItemTemplate to tell WPF/SL how to render that ViewModel.

The above are the 2 case I created this feature for yet of course this can be used for other things if you like!

If we think about the 2 scenarios that I specified above you can immediately see why those scenarios can work at runtime but not at Design Time. The problem is that at design time the designer can be working on only a specific part of the UI (example the Child UI i.e the User Control that renders the ChildViewModel). In this case the ChildView would not have the attached property that asks for a ViewModel to be injected because we would not want to inject a ViewModel as at runtime that ViewModel would be coming from the ParentViewModel. In order to accomplish this the ExportViewModel has a parameter where you can tell it I want the ViewModel only to be injected at design time, BUT I would also like MEFedMVVM to satisfy my imports when at runtime. You specify this by doing so..

image  As you can see by passing true in the constructor for the ExportViewModel, you are setting the IsDataContextAware to true thus you will start leveraging this feature.

At design time this will work just like a normal ExportViewModel, so it will create an instance of the ViewModel and inject it in the View datacontext. But at runtime this will do something more clever. I will hook to the DataContextChanged event (in WPF, in SL this is not available thus it is hooked to the Loaded event. This might affect you depending on how you are setting the ViewModel to the View but it will work for most cases, specifically for the cases I specified above) and satisfy the imports of the ViewModel. The runtime behaviour is really helpful especially if you are using some of the core MEFedMVVM features such as IVisualStateManager.

Tips for Design Time Data

>> If some design time data does not show attach Visual Studio to Blend so you can debug and see what is going on.

>> Many times when you reference assemblies that have Exports you might end up having funny composition errors; If you do not have strongly names assemblies Blend will load multiple version of the same assembly and this usually result in issues at design time. I always try to sign my assemblies so that I do not get such issue at design time + its always a good practice to sign your assemblies anyway

Conclusion

I am now using MEFedMVVM in all my new projects and I am really enjoying it. It enables me to quickly start a project without having to worry, what should I use for Dependency Injection, How do I give Design Time Data to the ViewModel etc etc… Of course this is work in progress so you might stumble upon a bug or 2 🙂 but I am pretty much committed in investing more time on this framework so if you have suggestions or find bugs please do let me know.

I hope you like MEFedMVVM and that it can help you like it is helping me in everyday projects.

Download MEFedMVVM and Samples for usage from CodePlex

26 thoughts on “MEFedMVVM v1.0 Explained

  1. Pingback: Dew Drop – Weekend Edition – May 22-23, 2010 | Alvin Ashcraft's Morning Dew

  2. Pingback: MEFedMVVM: Testability « C# Disciples

  3. Pingback: MEF и MVVM « Silverlight Course At FMI

  4. I love the work here. It makes the ViewModelLocator so simple, and easy to get MVVM code up and running.

    However, I’m noticing that the Visual Studio designer doesn’t have the design time data showing up. It works in blend fine. I’ve tried my own code and the sample code, and neither show design time data in Visual Studio.

  5. Thanks for your quick response. But sound seems to be we could not benefit from VM Ctor overloading when using the MEFedMVVM.

  6. its a MEF limitation…. To a certain extend you can still leverage overloading example while you are doing unit testing or if you are using DataContextAware ViewModel (i.e MEF does not create the instance of the ViewModel).

  7. Kindly correct me if I’m wrong, but in my opinion almost existing containers currently haven’t supported resolving viewmodel with the right ctor based on a given context, I mean it uses the ctor with most parameters. The MEF CompositionContainer is not an exception as well. So what do you think if we tweak the CompositionContainer in order to overcome the limitation (that’s exactly what I have done with UnityContainer when using Prims 2.0 to build My MVVM framework).

  8. Hi
    I’m having problems getting started. I’ve added the references as shown above but the ViewModelLocator isn’t being called even though I’ve add the following to me View.

    xmlns:MEFed=”http:\\www.codeplex.com\MEFedMVVM”
    MEFed:ViewModelLocator.ViewModel=”MainWindowViewModel”

    I’ve also added references to the MEFedMVVM DLL and to System.ComponentModel.Composition and I’ve added the attribute [ExportViewModel(“MainWindowViewModel”)] to my view.

    I’m obviously doing something simple wrong but I have no idea what. I’ve compared my project to the demo and I can’t see what I’m missing. Can anyone help?

    Thanks

    Simon

  9. I have what may be the dumbest question ever. If I want to refer to an instance of a viewmodel from some arbitrary code, how do I do that? I need to execute a method on the viewmodel that interrogates one of its properties so another class can work with them and reset the property in the viewmodel afterwards. Something like:

    var vm = ;
    vm.SomeMEthod();

    vm.SomeOtherMethod();

    etc.

    where vm is the viewmodel of interest. Matters, I guess, to know if it is a singleton or not but the real issue is that I need to be able talk to it. I am not finding an obvkous way to do this. That being said, I am no MEF expert. I am really hoping it is a one-liner!!!
    Cheers and TIA.

  10. Oh, I just wanted to mention without any hint of criticism:

    1) repoitory.cs should be repository.cs
    &
    repoitory should be repository in several places

    2) File BasicViewModelInializer.cs should be
    BasicViewModelInitializer.cs
    &
    Inializer should be Initializer in several places

    3) The folder PlatformIndependent was misspelled too.

    4) ReSharper reports a ton of unused using directives everywhere. Presumably it is safe to remove those?

    Again, this is by no means criticism! THANK YOU!

  11. So one viewmodel works, with no data service, but the one that ijnecta a data IRepository in the constructor fails. The exception below is raised on

    return_partQuery

    and means that something is wrong with the viewmodel definition apparently, but the demo does not provide any guidance on what should or should not be in the viewmodel.
    No valid exports were found that match the constraint ‘((((exportDefinition.ContractName == “RulesManagerViewModel”) AndAlso (exportDefinition.Metadata.ContainsKey(“ExportTypeIdentity”) AndAlso “System.Object”.Equals(exportDefinition.Metadata.get_Item(“ExportTypeIdentity”)))) AndAlso (((exportDefinition.Metadata.ContainsKey(“Name”) AndAlso System.String.IsInstanceOfType(exportDefinition.Metadata.get_Item(“Name”))) AndAlso exportDefinition.Metadata.ContainsKey(“IsViewModelFirst”)) AndAlso System.Boolean.IsInstanceOfType(exportDefinition.Metadata.get_Item(“IsViewModelFirst”)))) AndAlso ((Not(exportDefinition.Metadata.ContainsKey(“System.ComponentModel.Composition.CreationPolicy”)) OrElse Any.Equals(exportDefinition.Metadata.get_Item(“System.ComponentModel.Composition.CreationPolicy”))) OrElse NonShared.Equals(exportDefinition.Metadata.get_Item(“System.ComponentModel.Composition.CreationPolicy”))))’, invalid exports may have been rejected.

  12. Comment on parameter serviceType on class ExportService has wrong parameter name. Should be serviceType, but is IsDesignTimeService or some such now.

  13. just found this, looks really promising! One thing I don’t really like at first sight though: by specifying the name of the ViewModel a View has to use (“PizzamakerVM”) you introduce coupling between the V and the VM. And worse the coupling is based on a string literal. What’s your take on this? Or is it a non-issue?

  14. Pingback: More MEFedMVVM NavigationExtensions love « C# Disciples

  15. First off I would like to say superb blog! I had a quick question which I’d like to ask if you do not mind. I was interested to find out how you center yourself and clear your thoughts prior to writing. I’ve had a tough time clearing my thoughts in getting my ideas out there. I do enjoy writing but it just seems like the first 10 to 15 minutes are usually wasted just trying to figure out how to begin. Any ideas or tips? Appreciate it!Painting in Houston: Residential Painting, 8834 Andante Dr., Houston, TX 77040 – (281) 944-5450

  16. Greetings, I believe your web site could be having web browser compatibility issues.
    Whenever I look at your site in Safari, it looks fine however when opening in I.E.,
    iit has some overlapping issues. I erely wanted to
    pprovide yoou with a quick eads up! Other than that, great
    website!

Leave a comment