HTML5 CSS3 Javascript vs XAML .net and Silverlight

Introduction >> The clash of the Titans is on

Developers right this second are at some bar / restaurant / lounge / god knows where else being “social” i.e. having geeky discussions about technology, what language/platform is best to use or even better “what’s coolest right now” Smile

I am one of those developers and I must say, when it comes to such discussions I am always biased towards XAML technologies. Yet recently I started diving in what I used to call the “darker side” i.e. HTML5, JS and CSS3 (the “dark side” is reserved for things like Java Smile ). It’s been years (6 to be exact) since I was doing some HTML and Co and I must say; I am really impressed. HTML5 just takes everything to a whole new level BUT what impresses me most is JS and CSS3.

JS because the browsers are natively exposing APIs such as GeoLocation, Canvas drawing, local storage and also indexed DB (and more APIs). BESIDES THAT, what sells JS for me, is the new libraries developers are building such as JQuery and Knockout.js. Working with javascript today is just loads and loads of fun !!

CSS3 because WOW its frekin cool!! The new box modelling with the Flexible box model, the gardients, the transforms, the transitions and I can go on and on…

So yea I must admit, web development (presentation layer) of today is becoming loads of fun! Backend for Web with MVC its also frekin cool! so I guess the questions that readers of my blog / people who know me would ask “Is Marlon turning his back on XAML?” The answer is simple and its NO, my car number plate still says WPF so I guess I cannot change everything now Smile Joking aside, I see both technologies as super awesome and both of them have a different realms (to a certain extend). “to a certain extend” for the reason that WinRT will also support HTML5 JS and CSS3 as a first class citizen just like it will for XAML and C# / C++.

Does this mean we should say bye bye to XAML and just focus on HTML5 and Co?? If it can do web + desktop why bother looking at XAML??

Ok so lets be a bit metaphoric about this and let’s compare technologies with cars. There are many different brands, there is Audi, there is Honda and you can go on and on… They all take you from place A – B. How they take you is a bit different, some are super confortable, some are fast. Some are perfect for one thing some are perfect for another! You buy a car that fits your needs and the same can be said to technology you decide to use. There are those scenarios, for example when you are moving house, where you do not have the luxury to use your “preferred car” because hey; if its a sports car, it will be no good when you are moving, so in such a case you are coerced to use a specific type. Such an example for developers is the web / mobile phones … Yet again just like in real life there are many different trucks for moving Smile there is HTML5, and then there are the plugins (Flash, Silverlight) …

Which one should you go for? HTML5 or Plugins?

Looking at web tech today I would say go for HTML5. It will work on devices such as phones, if done properly it will be super fast. On the other hand I would strongly suggest you consider SL / Flash if your users cannot install/already have a browser that supports HTML5. In that case then yea I would not go for the HTML < 5 because you’re in for nightmares! Maybe mix and match! Some things are better done with plugins some other with HTML. Do not be afraid to try both worlds, it will not hurt.

What about WPF??

WPF will still have a place but I guess we will slowly see it being used lesser and lesser, reason being with WinRT you are not using WPF you are using WinRT, yes its XAML but NO it is not WPF. There are cases such as VS and similar heavy weight products that would require something like WPF. Trading applications and internal banking applications is another example for WPF apps. But yea if you are building a simple app, going forward one would be better off with something Metro style i.e. WinRT based. So should WPF developers say “cr*p I wasted a lot of time learning something I will not use anymore”?? Whoever says that is really talking bull***t! WPF thought us a lot, WPF gave us so many concepts and ideas… WPF will always continue living in other technologies… Its concepts that really are hard to learn not how to use a framework, example DataTemplates, ControlTemplates, Binding and many other concepts … For me WPF showed me what an awesome API should look like! Besides that you learnt XAML that is something that is not a waste of time since XAML is here to stay !

Final verdict – Who will be the last technology standing?

None probably Smile technology evolves … sorry my fellow geeks, I like you used to treat a technology stack (and must admit still do sometimes) as my one and true love and I could not use another technology without feeling that I am being MARLONCHANGE… well its not the case, when it comes to technology you can mix and match as much as you want and no you will not be called a “Cheater” Smile

Take it from me, if you did not have a look at HTML5 and co, maybe its time for you to do so. Maybe you will not use it but I am sure you’ll get something out of it. I am learning so much, getting so many new ideas (that yea I can even apply for WPF) from doing some HTML5 and Co.

Hope I did not bore you to death with this post but I felt I needed to share this with you guys! I’ll be posting more on HTML5 and Co this year but yea of course I will also do the same for XAML and Co.

Long live XAML

Long live HTML5 (and co)

>> No source code to download just thoughts …

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

Making a generic UpdateSourceTrigger for PropertyChanged in Silverlight

In my previous post I explained how Silverlight 4 lacks the UpdateSourceTrigger for PropertyChanged. I focused on how you can overcome this issue for one of the biggest use cases, which is the TextBox.

In this post I will show how one can do this for any Dependency Property of any Framework element. Please note that this post is quite an experimental one. Probably the use case you are looking for is for the textbox scenario, if that is the case I would suggest that you use the more explicit approach i.e the one I show in my previous post. The take away from this post should be more the idea of how things work rather than the actual code I am using here, this code was never tested in production thus it might contain memory leaks and other issues.

The key for updating the binding when a property changes is to actually know when the property has changed and then force the binding to update the source. In WPF there are multiple ways of doing this, one of which is to use the DependencyPropertyDescriptor class. This class allows you to hook an event handler for when the specified property has changed. Unfortunately in Silverlight there is no DependencyPropertyDescriptor class thus one has to resort to some ninja trick Smile After doing some internet crawling I found an interesting approach using attached property creating and hooking to the property changed. The idea is that you create an attached property and you bind the newly created attached property to the property that is consuming the binding.

Let’s dig a bit deeper

Let’s say you have the following binding

<TextBox Text=”{Binding SomeText, Mode=TwoWay}”

The Text dependency property is consuming a binding and you want to update the source of the binding as soon as the property changes.

You create an attached property and you bind it to the Text property of that TextBox. This will get you notified when the text changes because when creating the attached property you can have a property changed handler. In the property changed handler you update the source of the binding.

You would create the attached property and the binding for notifications like so

// Create attached property

var listeningProperty = System.Windows.DependencyProperty.RegisterAttached(

    "ListenAttached" + propertyName,

    typeof(object),

    typeof(UpdateSourceTriggerProxy),

    new System.Windows.PropertyMetadata(OnPropertyChanged));


//Create a binding that will be updated when the property changes

var listeningBinding = new Binding(propertyName) { Source = element };

element.SetBinding(listeningProperty,

    listeningBinding);

Ok so I showed how you can workaround the lack of DependencyPropertyDescriptor in Silverlight for property changed notification, now how do we update the binding?

In order to do this we will need to get the instance of the Text Dependency Property. Unfortunately we will need to resort to reflection in order to get the instance of the Dependency property. We can do this by name

var propertyFieldInfo = frameworkElement.GetType().GetField(newPropertyName + "Property");

if (propertyFieldInfo == null)

    throw new InvalidOperationException(String.Format(

        "The property {0} does not exist in the element {1}. Make sure you specified the correct property.",

        newPropertyName, frameworkElement.GetType().FullName));

//Get the dependency property the binding is applied to

var property = (DependencyProperty)

    propertyFieldInfo.GetValue(frameworkElement);

As you can see I am attaching a string “Property” to the actual property name (in this case Text) when I try to get the dependency property by reflection. Even though in XAML you specify “Text” as the property name, the actual dependency property name is TextProperty (which is a coding standard for dependency properties), “Text” is how the property is registered to the framework.

So why did we need to get the actual instance of the Dependency property? We had to do this in order to get the Binding Expression so that we can force the binding expression to update the source of the binding with the new property value. This would look like this

_bindingExpression = element.GetBindingExpression(BoundProperty);

And to update the source (i.e in the property changed handler of the attached property) we would do this

_bindingExpression.UpdateSource();

How is this approach generic?

Well let’s see what we did in the “Dig Deeper” section.

- We are getting a dependency property by name

- We get the Binding Expression from that dependency property

- We create an attached property which will be our way of hooking to property changes of a specific dependency property.

mmm… So as such we can have 1 attached property of type string that will generate this hook and update the source for us. If we do this we would have something like this in our XAML

<TextBox Text=”{Binding SomeText, Mode=TwoWay}” local:UpdateSourceTrigger.PropertyName=”Text” />

Not great but not too bad, it will do the trick for now… So here is the code for the attached property (you have to download the sample project)… Its exactly what I explained in the section above.

Please note that I am creating the hook inside a separate class UpdateSourceTriggerProxy. I am doing that so that the operation is atomic and everytime you use this approach we have a different instance of UpdateSourceTriggerProxy doing the hook for updates and the actual update. The object instance we be kept alive because of the property changed delegate.

Download sample project here.

UpdateSourceTrigger PropertyChanged for Silverlight 4 Binding ?

Problem Definition

In Silverlight 4 there is no way out of the box to specify that a certain binding should update the source on PropertyChanged, the options for the UpdateSourceTrigger are LostFocus and Explicit.

These options are more or less what you really need for most scenarios, yet sometimes you want to have the ability to update the binding while a property is changing. A use case would be, you have a textbox and you want to apply some validations while the user is typing, maybe you enable a button if the text entered is correct or disable it if it is not correct.

Many times developers end up writing code behind in order to achieve this. Problem with this is that if you need it in multiple places you end up copying and pasting code for code behind. In this article I will show how one can workaround this problem by resorting to the mighty Attached Properties.

Using an Attached Property to workaround this problem

By using an attached property we can have the code to update the source on property changed. For this demo I will focus on how to make this work for a TextBox in Silverlight. In future posts I will show how you can have a generic way of dealing with this issue.

The attached property will give us the instance of the object the attached property is being applied to, with the reference of the object (in our case the TextBox) at hand we can hook to the TextChanged and update the binding. In order to update the binding you can use the GetBindingExpression method of the UI element. Then we can simple call the UpdateSource on the BindingExpression and viola the trick is done…

The Attached Property would look like this

using System.Windows;

using System.Windows.Controls;

 

namespace SilverlightUpdateSourceTrigger

{

    public class UpdateSourceTrigger

    {

        #region TextChangeUpdateSourceTrigger

 

        /// <summary>

        /// TextChangeUpdateSourceTrigger Attached Dependency Property

        /// </summary>

        public static readonly DependencyProperty TextChangeUpdateSourceTriggerProperty =

            DependencyProperty.RegisterAttached("TextChangeUpdateSourceTrigger", typeof(bool), typeof(UpdateSourceTrigger),

                new PropertyMetadata((bool)false,

                    new PropertyChangedCallback(OnTextChangeUpdateSourceTriggerChanged)));

 

        /// <summary>

        /// Gets the TextChangeUpdateSourceTrigger property. This dependency property 

        /// indicates ....

        /// </summary>

        public static bool GetTextChangeUpdateSourceTrigger(DependencyObject d)

        {

            return (bool)d.GetValue(TextChangeUpdateSourceTriggerProperty);

        }

 

        /// <summary>

        /// Sets the TextChangeUpdateSourceTrigger property. This dependency property 

        /// indicates ....

        /// </summary>

        public static void SetTextChangeUpdateSourceTrigger(DependencyObject d, bool value)

        {

            d.SetValue(TextChangeUpdateSourceTriggerProperty, value);

        }

 

        /// <summary>

        /// Handles changes to the TextChangeUpdateSourceTrigger property.

        /// </summary>

        private static void OnTextChangeUpdateSourceTriggerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

        {

            TextBox textBox = d as TextBox;

            if (textBox == null)

                return;

 

            bool newTextChangeUpdateSourceTrigger = (bool)d.GetValue(TextChangeUpdateSourceTriggerProperty);

 

            if (newTextChangeUpdateSourceTrigger)

                textBox.TextChanged += OnTextChanged;

            else

                textBox.TextChanged -= OnTextChanged;

        }

 

        static void OnTextChanged(object sender, TextChangedEventArgs e)

        {

            TextBox textBox = sender as TextBox;

            var binding = textBox.GetBindingExpression(TextBox.TextProperty);

            binding.UpdateSource();

        }

        #endregion

        

    }

}

Enjoy and Happy XMAS Smile

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.

MEF DeploymentCatalog and Reference assemblies

In the Silverlight version of MEF one of the most powerful catalogs is the Deployment catalog. The Deployment catalog enables you to do some really cool stuff because you can download parts of the application when you need them.

I am using the Deployment Catalog on one of my projects and today I hit an issue that made me bang my head for over 30 minutes! The error was clear but it was a mystery why it was happening… 

The Error

I could see the error I was getting inside the event arguments of the DownloadCompleted event (e.Error) of the Deployment catalog. It was saying I had an import that could not be resolved since I had more then 1 export matching that requested import >> “More than one export was found that matches the constraint ”

The Import I had looked like this

[Import(AllowRecomposition=true)]
public ILogService Logger { get; set; }

But I had a single export like this

[Export(typeof(ILogService))]
public class Loger : ILogService

The Logger class was not in the assembly that I was trying to download it was in an assembly called CommonServices. I had a reference to the CommonServices assembly.

The main application that was using the Deployment Catalog to download the other assembly also had a reference to the CommonServices. Besides that it was also creating an Assembly Catalog for the CommonServices and put it in the aggregate Assembly that had the Deployment Catalog. I was doing this since the Main application was also using the ILogService as an import.

Why the Error?

After reading this post I immediately knew why the error was happening and how to solve it. Deployment Catalog will load all assemblies inside the XAP file thus all the assemblies that it references (The referenced assembly will be in the XAP file if you set Copy Local=true and by default VS does that for you). So in my case the Deployment Catalog was creating an Assembly Catalog for the CommonServices but I had already created that in my main application since I was importing ILogService in my main application.

The Solution

image The solution is easy set Copy Local to false for the referenced assemblies you do not want DeploymentCatalog to load at runtime. Your imports inside the assembly will still be staisfied since the Deployment Catalog is in the same Aggregate Catalog where you loaded the assembly as an AssemblyCatalog.

Hope this may help anyone having the same issue.

Enjoy your daily MEFing :)

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/

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