MVVM in the web world

Introduction

Lately I have been experimenting with some web and I must say. the web is really making really amazing advances. The JS libraries out there are pretty awesome and make your job much more fun that it was a couple of years back !

One library that really really impressed me is (no not JQuery even though I must say I am quite impressed with JQuery as well !!) Knockout.js. The idea behind Knockout.js is to introduce MVVM to the world of web… One might ask does it even make sense to introduce a pattern like MVVM, how will it work without data binding capabilities ?? Well easy, bake binding capabilities in the library Smile and that is what Knockout.js is all about.

I will not give a deep dive to knockout but I will just show some of the capabilities of this library and then explain why I see this library playing a big part of web development we know today.

Binding capabilities of Knockout

So for those that are used to XAML technologies binding is our bread and butter. You can databind to properties in the view model to any DependencyProperty in an element. With Knockout the same features are available… Lets have a look

Knockout as the awesome JS library that it is uses unobtrusive javascript which really means it uses attributes to specify behaviour thus if JS is not enabled, no big deal everything would render since browsers ignore attributes that they do not understand.

To set the datacontext you call ko.applyBindings(viewModel, domElement) the second parameter is optional and if you do not set it, binding will be applied to the root element (and yes binding works like DataContext in XAML its “inherited”.

To specify a binding you specify the data-bind attribute to the element and inside you specify the type of binding and to which property

image

There are many types of bindings (by type I mean the “text” in this case part of the binding). You can see the full list here.

As I said I am not going to do a deep dive since the documentation for knockout is pretty awesome but here are some highlights for those that are used to XAML binding.

In XAML we are used to convertors if for example we have a bool property and we want to control Visibility; in Knockout you just put the code there and then. If you want to bind to more that one property just seperate it with a comma Smile simple; easy; AWESOME

image

For example in the above snippet I am binding the css class to be negativeTextBid if the negative property is greater or equal to positive BUT if it is the other way round then I am setting positiveTextBig. And yea I am also binding the text to count property in the same line. Wuhu!! You can imagine what one can do with such binding capabilities!

Ok so cool what about updates, if I change a property in my ViewModel how do I push it to the UI. Well in XAML we have INotifyPropertyChanged in Knockout.js we have ko.observable();

image

An observable will do all the work of looking up who is referencing it and give it the update. One other really awesome thing that comes in Knockout is dependantObservable (or also known as computed properties). This is a property that has a function and the function depends on other observables thus when one of those observables changes also the computed property/ dependant observable will fire a notification to the UI.

image

For collections (i.e. INotifyCollectionChanged for those XAML guys reading) there is ko.observableArray();

Speaking of which.. So how would you leverage a ko.observableArray?

Is there something like ItemsControl?

hah of course… There is something called the foreach binding… you put it for a div and magic happens

image

What about DataTemplates like stuff? well Knockout can also be used with JQuery templates to do this sort of stuff. Read more here

Ok so hang on tight for some more coolness…

What about commanding

In XAML technologies we have command that would link for example a button click to some sort of action/functionality in the ViewModel. In knockout this is just a normal databing called the click binding. Read more here

image

and yes you can go beyond click. There is event binding, selectedOptions binding and many others…

So why would you want to have ViewModels in javascript?

Well today’s web is quite complex and having code running around, manipulating DOM elements after getting responses from AJAX calls can become one giant nightmare. By having a “UI layer” that separates the concerns where the HTML is your presentation and the viewModels in Javascript are the facilitators for the presentation data, then have a binding mechanism that glues the 2 together; is really a dream come true. Thank you Knockout!

One must understand that Javascript of 2012 is not the same as we know it a couple of years back where it was really a scripting language to do small things that you could not do declaratively in html. With the introduction of AJAX Javascript started growing and growing into a full fledge language that many today work with everyday to build compelling web applications. So YES you must ensure that you apply the proper patterns even when doing Javascript! Fail to do so and you will get stuck in nightmares and hate the web with all your might !

Knockout really enables you to clean up your presentation layer and introduce MVVM to it. It does so by giving us Databinding capabilities and a whole bunch of utils to facilitate javascript development for the presentation layer.

If you did not try it already, I suggest you give it a shot!

Knockout you truly knocked me out !

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 !

MEFedMVVM: Testability

>> If you are new to MEFedMVVM, I suggest you first read this article to get started: http://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/

IContextAware services to bridge the gap between the View and the ViewModel – MEFedMVVM Part 3

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

If you did not have look at MEFedMVVM introduction please so here. I also wrote an article on ExportViewModel here.

So what the hell is an IContextAwareService??

It is a service that knows about its context (which is the UIElement that invoked the import for the ViewModel and the services it depends on).

As I said in previous posts this is one of my favorite feature that MEFedMVVM has. Why well many times I created attached properties to extend UI functionality so that I can do proper MVVM. Yet some times it does not feel right because there is still a gap. The ViewModel does not have control over what the attached property does. Usually this is solved by exposing commands from the ViewModel and then you have another attached property that invokes the command which is magically databound ad what not. An example of something like this is VSM support I did a while ago here.

Enter MEFedMVVM with it’s IContextAwareServices.

You create this kind of service when you want to do some thing to or with the UI Element using the ViewModel as its DataContext. For example let’s say I want to know when the UIElement is Loaded and Unloaded so that my ViewModel does something smart only when you are Loading and Unloading. (please note this is just one example and I choose this example just to show the technique)

So let’s start by creating a service to do this.

First thing we have to do is create a class that Implements IContextAware. So our class will look like this

   1: public class DefaultContainerStatus : IContainerStatus


   2: {


   3:    #region IContextAware Members


   4:


   5:    public void InjectContext(object context)


   6:    {


   7:    }


   8: }

As you can see this interface has a method called InjectContext. This method will be called by MEFedMVVM with the UIElement that is requesting the ViewModel that has this service as Dependency. Since now we have the instance to the UIElement we can hook to the Loaded and Unloaded event and raise our own events that can later be mocked when unit testing the ViewModel.

So let’s create an interface to hide the default implementation of our service

   1: public interface IContainerStatus : IContextAware


   2: {


   3:     event Action ContainerLoaded;


   4:     event Action ContainerUnloaded;


   5: }

and now make the service implement that interface

   1: [ExportService(ServiceType.Both, typeof(IContainerStatus))]


   2: public class DefaultContainerStatus : IContainerStatus


   3: {


   4:     #region IContainerStatus Members


   5:


   6:     public event Action ContainerLoaded;


   7:


   8:     public event Action ContainerUnloaded;


   9:


  10:     #endregion


  11:


  12:     #region IContextAware Members


  13:


  14:     public void InjectContext(object context)


  15:     {


  16:         var element = context as FrameworkElement;


  17:         if (element != null)


  18:         {


  19:             element.Loaded += new RoutedEventHandler(ElementLoaded);


  20:             element.Unloaded += new RoutedEventHandler(ElementUnloaded);


  21:         }


  22:     }


  23:


  24:     void ElementLoaded(object sender, RoutedEventArgs e)


  25:     {


  26:         if (ContainerLoaded != null)


  27:             ContainerLoaded();


  28:     }


  29:


  30:     void ElementUnloaded(object sender, RoutedEventArgs e)


  31:     {


  32:         if (ContainerUnloaded != null)


  33:             ContainerUnloaded();


  34:     }


  35:


  36:     #endregion


  37: }

As you can see here all I am doing is handle the Loading and Unloading of the UIElement and raise the IContainerStatus events. In the code about I am also Exporting the service by using the ExportService attribute which tells MEFedMVVM that this is a service that can be consumed by ViewModels.

And that’s it folks. We are done. Now a ViewModel can start using this service by simple requesting it from the ExportViewModel attribute like so

   1: [ExportViewModel("VM1", typeof(IContainerStatus)]


   2: public class TestViewModel : BaseViewModel

One thing you should not forget is putting the [assembly: DesignTimeCatalog] somewhere in your project, otherwise MEFedMVVM will ignore your project. This is something that is not used at runtime but for design time it is crutial so that MEFedMVVM only loads your projects. MEFedMVVM will ignore any assembly at design time that does not have this attribute set!

Conclusion

There is a lot of potential in this approach. Currently MEFedMVVM exposes some out of the box IContextAware services which are

IViewStateManager – You can use this to invoke Visual States from your ViewModel.

IDispatcher – You can use this service to invoke delegates on the UI thread

IContainerStatus – You can use this service to get loaded and unloaded events.

and many more are coming up. But hey build your own if MEFedMVVM does not give you one already, it’s easy :) and yea we would love to see what you come up with, if you want to contribute we are always happy to have your code :)

As always feedback is most appreciated.

Go MEF it up now :) http://mefedmvvm.codeplex.com/

Leveraging MEFedMVVM ExportViewModel – MEFedMVVM Part 2

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

In this post I will explain and show case what you can do with your VieModel by leveraging MEFedMVVM. If you want an introduction to MEFedMVVM please go here.

In order to make your ViewModel discoverable you simple decorate the ViewModel with ExportViewModel and give your view model a name so that the View can import the ViewModel by name. Some thing like this

ViewModel

   1: [ExportViewModel("VM1")]

   2: public class MyViewModel

and the view can look for this view model like this

   1: <UserControl x:Class="MEFedMVVMDemo.Views.UsersScreen"

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

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

   4:              xmlns:meffed="http:\\www.codeplex.com\MEFedMVVM"

   5:              meffed:ViewModelLocator.ViewModel="VM1">

The ViewModelLocator.ViewModel will leverage MEF to go get the exported ViewModel and set an instance of that ViewModel as the UserControl’s DataContext. BUT there is more stuff you can do.

 

DesignTime Data

The best way how to have design time data is by having Data Services injected in the ViewModel so that at design time you inject design time services and at runtime you inject the real services. This also allows you to better unit test because you can mock the data services while unit testing.

MEFedMVVM allows you to easily export services so that you can then import these services in the ViewModel. When you are exporting the service you also supply MetaData which is used by MEFedMVVM to decide which service to inject. Let’s do a quick example. Let’s say your ViewModel is using a service that implements IUserService to get a list of user from a database at runtime and you create another implementation of this service for design time that just returns a static list of Users. you would export these services like this

Design time Service

   1: [ExportService(ServiceType.DesignTime, typeof(IUsersService))]

   2: public class DesignTimeUsersService : IUsersService

   3: {

   4:    #region IUsersService Members

   5:  

   6:    public IList<Models.User> GetAllUsers(){}

   7: }

Runtime Service

   1: [ExportService(ServiceType.Runtime, typeof(IUsersService))]

   2: public class UsersService : IUsersService

   3: {

   4:    #region IUsersService Members

   5:  

   6:    public IList<Models.User> GetAllUsers()

   7: }

As you can see all you do is decorate the service with the Export Service attribute and specify if its Runtime or DesignTime. You can also specify ServiceType.Both if you want that service to be injected both at runtime and design time. I will talk more on the Export Service and what you can do with it in my next post. Just to give you a quick insight of what this can do here is a small list

- Have shared services (a service that is shared for all ViewModels)

- Have prioritized Services (have a service priority and MEFedMVVM will pick the appropriate service to be injected)

- Have IContextAware services. These are special UI related services. Basically MEFedMVVM will call InjectContext passing the UI element that requested the ViewModel, so that service can work as a bridge for the ViewModel and the View without any coupling. (This is one of my favorite features)

OK let’s not get side tracked. Were are we?

We have a ViewModel that is an empty class decorated with ExportViewModel and we have two services exported one for runtime and one for design time.

In order to inject the services we need in our ViewModel, we need to state that in the ExportViewModel attribute, like this

   1: [ExportViewModel("VM1", typeof(IUsersService))]

   2: public class TestViewModel {}

This will tell MEFedMVVM to get that service and inject it to the ViewModel. But how can MEFedMVVM inject this in the ViewModel? Well in order to do so your ViewModel must implement an interface called IServiceConsumer. Here is the interface contract.

   1: /// <summary>

   2: /// Defines a service consumer.

   3: /// An entity that has a Service Locator and consumes services

   4: /// </summary>

   5: public interface IServiceConsumer

   6: {

   7:     /// <summary>

   8:     /// Gets the service locator that contains the services 

   9:     /// </summary>

  10:     IServiceLocator ServiceLocator { get; }

  11:     

  12:     /// <summary>

  13:     /// Call to be made when services are injected to the ServiceLocator

  14:     /// </summary>

  15:     void OnServicesInjected();

  16: }

So you will have a ServiceLocator property from where you can get the Services injected from and you need a method called OnServicesInjected which will be called when MEFedMVVM injects the services.

Don’t worry if you do not want to implement the interface yourself we made the heavy lifting for you. You can inherit from BaseViewModel which implements this interface for you. BaseViewModel also implements the INotifyPropertyChanged so you can do PropertyChanged notifications by calling OnPropertyChanged( () => Myproperty); Yes the implementation of INotifyPropertyChanged we used leverages lambdas so that you do not have spelling mistakes when doing property changed notifications :)

Back to service injection…. So our ViewModel is not implementing IServiceConsumer or inheriting BaseViewModel; inside the OnServicesInjected you can get the services and get the data you need. Like this

   1: protected override void OnServicesInjectedOverride()

   2: {

   3:     foreach (var item in GetService<IUsersService>().GetAllUsers())

   4:     {

   5:         if (SelectedUser == null)

   6:             SelectedUser = item;

   7:         users.Add(item);

   8:     }

   9: }

So here I am getting the data from the IUsersService that was injected and adding them in a collection which is bound in the View.

So yea finally my designer can see this in Blend

image

This sounded like a lot of work because I went into details of how everything works. But try it and you’ll see how easy it is to do. If its not easy enough get back to me and I really want to hear your feedback.

What if I do not have a service injected but I still want design time data??

Yes, I agree. There are some ViewModels that do not have a service injected BUT they still want design time data. An example of this… Let’s say you have another ViewModel which renders the SelectedUser which the end user selects from the other ViewModel. This ViewModel does not have a service because the data is coming from either from a Mediator callback or from a Property that is bound to some UI…. How can I have Design time data for this ViewModel?

MEFedMVVM let’s you do this as well. All you need to do is implement the IDesignTimeAware. This is the interface

   1: /// <summary>

   2: /// Interface to be implemented by ViewModels that want to do something when rendering in design time

   3: /// </summary>

   4: public interface IDesignTimeAware

   5: {

   6:     void DesignTimeInitialization();

   7: }

The DesignTimeInitialization method will be called on your ViewModel (ONLY AT DESIGN TIME) and inside there you can do what you want in order to have Design Time Data. Here is an example

   1: [ExportViewModel("VM2", typeof(IMediator), typeof(IVisualStateManager))]

   2: public class SelectedUserViewModel : BaseViewModel, IDesignTimeAware

   3: {

   4:     private User selectedUser;

   5:  

   6:     /// <summary>

   7:     /// Gets or sets the selected user

   8:     /// </summary>

   9:     public User SelectedUser

  10:     {

  11:         get { return selectedUser; }

  12:         set

  13:         {

  14:             selectedUser = value;

  15:             OnPropertyChanged(() => SelectedUser);

  16:         }

  17:     }

  18:  

  19:     protected override void OnServicesInjectedOverride()

  20:     {

  21:         mediator = GetService<IMediator>();

  22:         if (mediator != null)

  23:             mediator.Register(this);

  24:     }

  25:  

  26:     [MediatorMessageSink(MediatorMessages.SelectedUser, ParameterType=typeof(User))]

  27:     public void OnSelectedUserChanged(User selectedUser)

  28:     {

  29:         SelectedUser = selectedUser;

  30:     }

  31:  

  32:  

  33:     #region IDataContextAware Members

  34:  

  35:     public void DesignTimeInitialization()

  36:     {

  37:         SelectedUser = new User

  38:         {

  39:             Name = "Marlon", Surname = "Grech", Age = 24

  40:         };

  41:     }

  42:  

  43:     #endregion

  44: }

This will render like this in Blend

image

What if the DataContext is set because I am in a DataTemplate? How can I get Services injected and some design time data as well?

Very well. Sometimes we have scenarios when you have a DataTemplate that has a UserControl inside. This UserControl will still have a ViewModel set as its DataContext but it must not be set from MEFedMVVM ViewModelLocator.ViewModel attached property since the ContentControl or the ItemsControl should be setting the DataContext.

You can still do this with MEFedMVVM! In the ExportService you can have an additional parameter stating that this ViewModel should be “DataContextAware”. Something like this

   1: [ExportViewModel("UserVM", true, typeof(IMediator))]

   2: public class UserViewModel : BaseViewModel, IDesignTimeAware

   3: {

The second parameter passed set to true is where you specify that this ViewModel needs to be “DataContextAware”.

What is this gonna do?

Well at Runtime it will not create an instance of the ViewModel, instead it will wait until the DataContext is set on the UIElement. When DataContext is set, it will inject the services that you requested in the ExportViewModel.

At DesignTime it will create the ViewModel instance and inject it in the DataContext of the UI element so that you can still design your UI seamlessly.

Conclusion

These are only some of the features that MEFedMVVM has to offer. We are working on expanding more functionality. We are also working hard to test as many scenarios as possible but without your feedback and help we cannot cover all of them.

Please let us know if you encounter any issues so that together we can continue building an awesome and easy to use library, and have loads of fun creating cool WPF and SL applications :)

Download the source

http://mefedmvvm.codeplex.com/

Peace

An introduction to MEFedMVVM – PART 1

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

Intro

This is a small introduction to MEFedMVVM, a library that I built with the help of some fellow WPF Disciples, Peter O’Hanlon and Glenn Block (aka Mr.MEF). This library will enable you to quickly create ViewModels that consume services and inject these ViewModels in your View’s DataContext. It will also enable you to work better with your fellow friend, “The Designer” by leveraging Design time data and many other UI friendly stuff. With this library you can create WPF/Silverlight applications seamlessly since the API is common for both WPF and Silverlight.

This framework works for SL 4, WPF (.NET4.0 ). And we only support Blend 4 RC or newer. MEFedMVVM does not work in Blend 4 Beta .

MEFedMVVM-Logo2

Goals

- Write code that works for SL and WPF.

- Enable Design time data.

- Enable loosely coupled bridge between View and ViewModel.

- Enable easy ViewModel discovery and injection mechanism.

- Make composition super easy by leveraging MEF capabilities (without coupling your code with MEF).

How do I use this thing?

Ok so these are the first 3 basic steps.

1. Add a reference to MEFedMVVM.WPF/MEFedMVVM.SL (you also have to add a reference to dlls that are located in the Dependencies folder of the Source code if you are not including the library source code in your solution.)

image

2. Add an attribute somewhere in your project to mark the assembly as a “MEFedMVVM” Assembly, [assembly: DesignTimeCatalogAttribute]. This is used so that MEFedMVVM only looks for exported items in the marked assemblies. This makes initialization faster.

Now begins the MEFedMVVM fun….

3. Make your ViewModel discoverable by decorating it with [ExportViewModel(“MyMEFedViewModel”)] and instruct the view to go find that ViewModel by setting an attached property meffed:ViewModelLocator.ViewModel="MyMEFedViewModel"

So the View looks like this

   1: <UserControl x:Class="MEFedMVVMDemo.Views.UsersScreen"


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


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


   4:              xmlns:meffed="http:\\www.codeplex.com\MEFedMVVM"


   5:              meffed:ViewModelLocator.ViewModel="MyMEFedViewModel">

and the ViewModel like this

   1: [ExportViewModel("MyMEFedViewModel")]


   2: public class TestViewModel { }

and viola that is it…. You run the project and magically the ViewModel gets injected in the View…

I must say, I cannot take the credit for this magic, it’s all powered by the mighty MEF!

Ok so we injected the ViewModel in the View, but where the hell is the Design time data???

well should I tell you or should I go to sleep ? mmmm…. thinking… still thinking… aa well might as well tell you now that I started right :P

When creating ViewModels usually the data is coming from some service which is injected to the VM via Dependency injection. What MEFedMVVM will do for you is let you expose services and include meta data that gives extra information to the service. MEFedMVVM uses this Meta data to decide which service to give to the VM at runtime and which service to inject at Design time.

This is how you expose services (for runtime)

   1: [ExportService(ServiceType.Runtime, typeof(IUsersService))]


   2: public class UsersService : IUsersService

This is how you expose services (for design time)

   1: [ExportService(ServiceType.DesignTime, typeof(IUsersService))]


   2: public class DesignTimeUsersService : IUsersService

P.S you can also specify ServiceType.Both if you want the same service to be injected at runtime and design time.

Once you make your Services discoverable it’s time to start using them in your ViewModel. In order to do this, you must have your VM implement the IServiceConsumer interface, or if you are lazy like me just inherit from BaseViewModel. You also need to specify which services you want injected by specifying the different types in the ExportViewModel attribute. Something like this

   1: [ExportViewModel("VM1", typeof(IUsersService), typeof(IVisualStateManager), typeof(IDispatcherService))]


   2: public class TestViewModel : BaseViewModel

In the above code I am importing the IUserService, the IVisualStateManager and the IDispatcher service into my view model. These services are injected when MEFedMVVM creates an instance of the ViewModel into a ServiceLocator so you can get them by calling GetService<T>() from the OnServicesInjected method. the code for this looks something like this

   1: protected override void OnServicesInjectedOverride()


   2: {


   3:     var usersService = GetService<IUsersService>();


   4:     var dispatcherService = GetService<IDispatcherService>();


   5: }

You might ask yourself why can’t I just import the services by using a standard [Import] like in normal MEF. Basically when the MEFedMVVM is looking for the correct services it is also doing some extra stuff that I will talk about in following blog posts (but I know you are curious so I’ll give you a hint…. IVisualStateManager for example gets injected with the UIElement that is requesting the ViewModel so that then the ViewModel can execute state without coupling to the VSM)

What comes out of the box?

Out of the box this library supplies a number of things… here is a list of most of the stuff

Common Services

- IMediator (use this to communicate from one ViewModel to another.

- IViewStateManager (User this to invoke VisualStates from the ViewModel)

- IContainerStatus (Provides a loaded event and unloaded event, these are hooked to the loaded and unloaded events of the UIElement that is consuming the ViewModel)

- IDispatcher (Provides a way so that you can call BeginInvoke on the Dispatcher in a loosely coupled way so that you can mock this when doing unit tests)

- and many many many more to come….

- and many more you can create yourself.

Basically this library is still learning how to walk, its still a cute little baby… but the basics are in (so yea its a healthy cute baby)… I will talk more on how you can create your own services that BRIDGE the ViewModel and the View in my next post (yet yea I know, I know, you are curious… Implement IContextAware in your service and you get injected with the View that requested the ViewModel and then you can do what the hell you want :). but don’t tell anyone I told you :P )

Other stuff

DelegateCommand<T> (Used to create commands without having to create a separate class that implements ICommand)

BaseViewModel (Implement INotifyPropertyChanged and you can raise PropertyChanged notifications in a strongly typed manner i.e OnPropertyChanged(() => Users); . BaseViewModel also has some other benifits that I will discuss in my next post)

More stuff coming up … don’t don’t worry … we just built the basics here :)

Conclusion

Why do I think this library has a lot of potential? Well right now there are some things missing but the basics are there and it is really easy to add new stuff now that we have a solid base. There are loads of things that I did not mention in this post since I wanted this post to be just a mini introduction. I will have Part 2,3 n of this post coming up shortly where I will go into more dept of the library and how you can extend it and bend it to your will.

I suggest you download the code from CodePlex and start playing with it. Right now I really need your help and get as much feedback / bug reports as possible … WARNING: Right now I am doing loads of changes to the code so please do not use this in production projects.

I hope you like this new library… just a word of caution when using this library…. it can get really addictive :P myself am suffering this side effect right now … hehe :)

Part 2 here

Part 3 here

Part 4 here

Download source and MEF it up! http://mefedmvvm.codeplex.com/

Working with the WPF VSM in an MVVM friendly manner

Lately I have been working a lot with Silverlight. While working on my first Silverlight project I encountered my first problem… There are no Triggers in SL!!! At first I was frustrated and started hitting my self in the head but hey SL is not that bad… SL has the Visual State Manager aka VSM which is a pretty awesome tool I must say. I still think SL should have Triggers for some tasks such as ControlTemplates and other tasks yet with VSM you can still get some cool stuff done :)

What really strikes me with the VSM is the way it is supported in Blend, and YES designers love VSM! With the VSM they can define states in an easy way (and yes these states transition and the designer has full control on the transitions done). They can navigate easily through states in Blend and even see the transitions being done in Blend there and then.

image

Going back to WPF one thing that is missing in WPF is a way how a designer can define animations that get Triggered when something happens… Or let me re phrase that…. There is no easy way, or better not as easy as the VSM :)

Triggers in WPF can invoke Storyboards yet still it feels like the WPF animation system does not have a nice way to dispatch animations… Enter the VSM for WPF.

Yes, VSM is available for WPF as well, and yes it is supported in Blend (you just have to do a little trick that you can find over here)

I created a sample project that leverages the VSM for its animations and yes its all MVVM (in the sample app you’ll see that I am also using design time data for blend and I also included a mini MVVM Libarary that I use to develop my everyday WPF projects :) ).

 

Let’s Get Started

So let’s start by defining a state in Blend. In order to do so (assuming you followed the instructions to enable the VSM for WPF projects) you need to navigate to the States Tab and create a new state. Once the state is created and selected you’ll see that Blend will go to recording mode (just like it does when you are doing a normal WPF animation). Now you can change any property of any element and the Blend will record that and create the appropriate transitions for it.

image

Ok, now that we have the states defined in Blend what is next? well we need a way how to invoke these states for starters!

The Blend team were so kind to give us a Behavior called GoToStateAction. This behavior will basically invoke a state when an event is raised, for example if you have a button that should dispatch a new state, you simple find the GoToStateAction form the Asset tab and drag it on the button

image

Then you can set the properties for this behavior in the properties tab. There you can specify which state to select.

image

By doing these steps (define a state and use the GoToStateAction to invoke the state) you are already good to go. You can press F5 and you can see that when you click the button you get transitioned from one state to another. (P.S it’s important that you set a default transition time span otherwise you end up with no transition since the default is 0s).

 

This is all cool but what about MVVM ??

I hear you I hear you…. What if I have a ViewModel which needs to invoke a state change ?? Unfortunately this is not so straight forward… BUT of course there is a solution… I extended the GoToStateAction so that it can be hooked up from a ViewModel. Here is my extended version

   1: public class VisualStateManagerInvoker : GoToStateAction

   2: {

   3:     #region CurrentState

   4:  

   5:     /// <summary>

   6:     /// CurrentState Attached Dependency Property

   7:     /// </summary>

   8:     public static readonly DependencyProperty CurrentStateProperty =

   9:         DependencyProperty.RegisterAttached("CurrentState", typeof(string), typeof(VisualStateManagerInvoker),

  10:                                             new PropertyMetadata((string)null,

  11:                                                                  new PropertyChangedCallback(OnCurrentStateChanged)));

  12:  

  13:     /// <summary>

  14:     /// Gets the CurrentState property.  This dependency property 

  15:     /// indicates ....

  16:     /// </summary>

  17:     public static string GetCurrentState(DependencyObject d)

  18:     {

  19:         return (string)d.GetValue(CurrentStateProperty);

  20:     }

  21:  

  22:     /// <summary>

  23:     /// Sets the CurrentState property.  This dependency property 

  24:     /// indicates ....

  25:     /// </summary>

  26:     public static void SetCurrentState(DependencyObject d, string value)

  27:     {

  28:         d.SetValue(CurrentStateProperty, value);

  29:     }

  30:  

  31:     /// <summary>

  32:     /// Handles changes to the CurrentState property.

  33:     /// </summary>

  34:     private static void OnCurrentStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

  35:     {

  36:         if (GetGoToStateAction(d) == null)

  37:         {

  38:             var command = new RelayCommand(x => //where x is the state name passed as parameter

  39:             {

  40:                 var stateAction = new VisualStateManagerInvoker();

  41:                 stateAction.Attach(d);

  42:                 stateAction.UseTransitions = GetShouldUseTransition(d);

  43:                 stateAction.StateName = (string)x;

  44:                 stateAction.Invoke(null);

  45:             });

  46:             SetGoToStateAction(d, command);

  47:         }

  48:     }

  49:  

  50:     #endregion

  51:  

  52:     #region GoToStateAction

  53:  

  54:     /// <summary>

  55:     /// GoToStateAction Attached Dependency Property

  56:     /// </summary>

  57:     public static readonly DependencyProperty GoToStateActionProperty =

  58:         DependencyProperty.RegisterAttached("GoToStateAction", typeof(ICommand), typeof(VisualStateManagerInvoker),

  59:                                             new PropertyMetadata((ICommand)null));

  60:  

  61:     /// <summary>

  62:     /// Gets the GoToStateAction property.  This dependency property 

  63:     /// indicates ....

  64:     /// </summary>

  65:     public static ICommand GetGoToStateAction(DependencyObject d)

  66:     {

  67:         return (ICommand)d.GetValue(GoToStateActionProperty);

  68:     }

  69:  

  70:     /// <summary>

  71:     /// Sets the GoToStateAction property.  This dependency property 

  72:     /// indicates ....

  73:     /// </summary>

  74:     public static void SetGoToStateAction(DependencyObject d, ICommand value)

  75:     {

  76:         d.SetValue(GoToStateActionProperty, value);

  77:     }

  78:  

  79:     #endregion

  80:  

  81:     #region ShouldUseTransition

  82:  

  83:     /// <summary>

  84:     /// ShouldUseTransition Attached Dependency Property

  85:     /// </summary>

  86:     public static readonly DependencyProperty ShouldUseTransitionProperty =

  87:         DependencyProperty.RegisterAttached("ShouldUseTransition", typeof(bool), typeof(VisualStateManagerInvoker),

  88:                                             new PropertyMetadata((bool)true));

  89:  

  90:     /// <summary>

  91:     /// Gets the ShouldUseTransition property.  This dependency property 

  92:     /// indicates ....

  93:     /// </summary>

  94:     public static bool GetShouldUseTransition(DependencyObject d)

  95:     {

  96:         return (bool)d.GetValue(ShouldUseTransitionProperty);

  97:     }

  98:  

  99:     /// <summary>

 100:     /// Sets the ShouldUseTransition property.  This dependency property 

 101:     /// indicates ....

 102:     /// </summary>

 103:     public static void SetShouldUseTransition(DependencyObject d, bool value)

 104:     {

 105:         d.SetValue(ShouldUseTransitionProperty, value);

 106:     }

 107:  

 108:     #endregion

 109:  

 110: }

This class contains 2 attached properties CurrentState (which is a string) and a GoToStateAction which is an ICommand (It also has another property ShouldUseTransition which instructs the VSM weather to use transitions or just change the properties for the new state).

The CurrentState property will attach itself to the DepenedencyObject which is being decorated with this property and hook to its VSM (please note that the attach will crawl up the Logical Tree to find the first available VSM). This operation creates an RelayCommand that is set in the GoToStateAction attached property.

Now the interesting part happens. I created a base class for ViewModels that want to invoke states called StateBaseViewModel. Here is the code…

   1: /// <summary>

   2: /// Base view model that has a property for state changes

   3: /// </summary>

   4: public class StateBaseViewModel : BaseViewModel

   5: {

   6:     private string currentState;

   7:  

   8:     /// <summary>

   9:     /// Gets or sets the current state of the ViewModel

  10:     /// </summary>

  11:     public string CurrentState

  12:     {

  13:         get { return currentState; }

  14:         set

  15:         {

  16:             currentState = value;

  17:             RaisePropertyChanged("CurrentState");

  18:         }

  19:     }

  20:  

  21:     /// <summary>

  22:     /// Changes the CurrentState property to the spcified state

  23:     /// </summary>

  24:     public ICommand GoToStateCommand { get; protected set; }

  25:  

  26:  

  27:     /// <summary>

  28:     /// Specify a command to be fired when state changes

  29:     /// </summary>

  30:     public ICommand OnGoToState { get; set; }

  31:  

  32:  

  33:     public StateBaseViewModel()

  34:     {

  35:         GoToStateCommand = new RelayCommand(

  36:             x =>

  37:             {

  38:                 CurrentState = (string)x;

  39:                 if (OnGoToState != null && OnGoToState.CanExecute(CurrentState))

  40:                     OnGoToState.Execute(CurrentState);

  41:             },

  42:             x => !String.IsNullOrEmpty((string)x)

  43:             );

  44:     }

  45: }

This base view model has the same 2 properties of the VisualStateManagerInvoker. We can make these 2 in sync together by using standard TwoWay databinding. By doing so the VisualStateManagerInvoker will feed the View Model with a command that is hooked up to a UI element VSM and when invoked this will ask the VSM for that element to transition to the state passed as parameter.

Here is the binding for this

   1: <local:Checkout  

   2:     mvvmStateManagement:VisualStateManagerInvoker.CurrentState="{Binding CurrentState}"

   3:     mvvmStateManagement:VisualStateManagerInvoker.GoToStateAction="{Binding OnGoToState, Mode=TwoWay}" />

Assuming that the element local:Checkout has a datacontext set to a view model that is inheriting from StateBaseViewModel, you can see how the VisualStateManagerInvoker is feeding this View model a GoToStateAction by simple two way databinding.

Since this command is now ready to be used from our ViewModel we can invoke a state by simple executing the command like so.

   1: CancelCommand = new RelayCommand(x =>

   2:                 {

   3:                     GoToStateCommand.Execute("CancelState");

   4:                 });

This is super awesome isn’t it :)

Another cool thing about this is that you can use this trick so that you can invoke a state from a child to its parent. Lets say that you have a Window that contains a usercontrol (which has a StateBaseViewModel set as its datacontext) and a button. You want the button to show the UserControl. Ok easy Just drag and drop a GoToStateAction behavior and set its state to the state which makes the user control visible. But now lets say you have a button inside the user control and this button needs to invoke a state defined in the Window. The VSM works with namescopes thus you cannot invoke a state that is out of your namescope. BUT with the approach of uses VisualStateManagerInvoker we can do this since we can set the binding in the same XAML line that declares the usercontrol in the Window thus being in the same namescope as the Window :) We can then make a normal command that executes the GoToStateCommand in out StateBaseViewModel (this example is in the sample application to Cancel the check out of the shopping list and to show the thank you message when someone checks out the shopping cart)

Please note that the same code works for Silverlight.

Conclusion

I think that by using VSM one makes the Developer Designer workflow a happier thing. Designers love VSM and I learnt to love it as well. Now that I can invoke states easily from my ViewModel. Besides that since the implementation gets the VSM instance in an attached behavior and then feeds it to the ViewModel via databinding, the ViewModel never touches the VSM thus unit testing is much easier like this.

I found this way of working with the VSM awesome… OK I still need to make it cooler but as it is right now you can just grab the code and start working without any problems…. hope it helps :D

 

Download sample application (P.S Open this in Blend 3 to get maximum pleasure :) )

(Sample application contains MVVMHelper a small library I built for MVVM. It contains loads of goodies… have a look and enjoy)