Wednesday, December 30, 2009

PRISM, MEF, and MVVM Part 2 of 3: Making PRISM MEF Friendly

In the first part of this series, we explored using the Unity container to bind the view model to the view. The next logical step is to explore how to use MEF. PRISM provides several useful mechanisms that relate directly to views and modules, such as the region manager and the module manager. This allows us to dynamically assign views to regions on the display and dynamically load modules.

Logically, it seems we could create a MEF module, dynamically load it through PRISM, and glue its parts together as well. We'd probably start with a view model that looks like this:


[Export]
public class MEFViewModel 
{
    [Import]
    public IService { get; set; }

    public DelegateCommand<object> Command { get; set; }
}

And then easily pull it into a view like this:


public partial class MEFView : UserControl
{
   [Import]
   public MEFViewModel ViewModel { get; set; }

   public MEFView() 
   {
      InitializeComponent();
      PartInitializer.SatisfyImports(this);
      LayoutRoot.DataContext = ViewModel; 
   }
}

That is the essence of how it works, right?

Unfortunately, if you try this (like I did) you'll quickly find that your parts won't compose. You'll receive errors, and the view won't render. The view model won't get instantiated. Why is this? Where did we go wrong?

Stable Composition

The first thing to understand before we can start fixing things is a concept known as "Stable Composition." This feature, which is described in detail in Glenn Block's blog entry Stable Composition in MEF, is a fail-safe used to prevent unstable parts from being composed into your application. The pro is that if a failure exists somewhere down the chain of imports and exports, the part is simply discarded and not considered for import. The con is that it takes a little bit more debugging and troubleshooting to discover exactly why the composition failed. In this case, we were unable to find an import for IService, so the view model could not be imported into the view, which caused the PartInitializer to complain because, well, it couldn't "get no satisfaction."

If you recall in part 1, we flagged our service implementation with the Export property. What went wrong?

MEF and Silverlight XAP files

One frustration I've had with a lot of online examples of using MEF with Silverlight is that everything is contained within a single XAP file. For larger, scalable, and pluggable applications, this simply won't be the case. This makes straightforward examples suddenly break when you start to distribute your classes between various projects or PRISM modules.

The PartInitializer class is a helper class in MEF that helps compose parts where they might not normally be seen. By this I mean in pages like user controls that are constructed by the XAML parser. The XAML parser doesn't understand MEF, so it is unaware of how to reach out and satisfy imports. By including the PartInitializer in the constructor and calling the SatisfyImports method with the view, this allows MEF to inspect the view and XAML-generated parts and begin composition.

By default, however, the PartInitializer only "knows" about the current XAP file. It has no way of knowing what other assemblies and XAP files exist in the project. In our example, because the interface for the service and implementation both exist in separate projects (and XAP files), MEF choked on the import because it did not know where to find the export.

The Silverlight 4 toolkit includes the PackageCatalog. This facilitates dynamic loading of XAP files as well as composition using different XAP files. In Silverlight 3, without the benefit of this type of catalog (which may become available in future previews), we must build our own infrastructure to facilitate the composition across XAP boundaries. (Tip: if you want to use the package catalog in Silverlight 3, the source is available for the toolkit).

Introducing the Catalog Service

To begin, we need a service for the modules to communicate with and help aggregate catalogs between XAP files. This is the piece that Glenn Block helped build and explained to me, so many thanks to him. Be sure to subscribe to his blog and Twitter feed, lots of useful information there!

We start with a simple definition:


public interface ICatalogService 
{
   void Add(ComposablePartCatalog catalog); 
}

The ComposablePartCatalog is the base catalog class that allows us to add catalogs to our service.

In the implementation of the service, we use an AggregateCatalog to hold the other catalogs in one place:


public class CatalogService : ICatalogService
{
    private AggregateCatalog _catalog;

    public CatalogService(AggregateCatalog catalog)
    {
        _catalog = catalog;
    }

    public void Add(ComposablePartCatalog catalog)
    {
        _catalog.Catalogs.Add(catalog);
    }
}

Notice that the constructor expects us to pass a catalog. Where does this catalog come from?

This is where things will start to get a little interesting, so bear with me.

First, in our bootstrapper, we'll want to aggregate all of the existing parts into one catalog. Let's take a look at a new method GetHostCatalog that creates a new AggregateCatalog and returns it:


private AggregateCatalog GetHostCatalog()
{
    var catalog = new AggregateCatalog();

    foreach (AssemblyPart ap in Deployment.Current.Parts)
    {
        StreamResourceInfo sri = Application.GetResourceStream(new Uri(ap.Source, UriKind.Relative));
        
        if (sri != null)
        {
            Assembly assembly = ap.Load(sri.Stream);        
            catalog.Catalogs.Add(new AssemblyCatalog(assembly));
        }
    }

    return catalog;
}

So the "deployment" is the active Silverlight application. We iterate each part, then stream the actual assembly. The assembly is then added to the catalog. This will take care of all of the assemblies available when the bootstrapper runs. Let's wire that in and then see how we can grab the dynamic modules as well.


private void InitializeCompositionHost()
{
    var catalog = GetHostCatalog();
    var container = new CompositionContainer(catalog);
    container.ComposeExportedValue<IService>(Container.Resolve<IService>()); 
    container.ComposeExportedValue<IRegionManager>(Container.Resolve<IRegionManager>()); 
    Container.RegisterInstance<ICatalogService>(new CatalogService(catalog));
    CompositionHost.InitializeContainer(container);
}

Now we are starting to see pure play between Unity and MEF. First, we start the catalog. Next, we create a composition container using the catalog. Now we can interface between Unity and MEF using the ComposeExportedValue method. Here, I am providing MEF with an explicit export for a given import, and using the Unity container ("big C") to resolve the dependencies. This will give us the exports for IService and IRegionManager. The Unity container is also given a single instance of ICatalogService.

Finally, a very key step is to tell MEF to use our special container. One of the features of MEF is that it effectively hides the container from your view. You can literally build applications using nothing other than the Import and Export attributes. However, sometimes we need to explicitly manage or configure the container. This is one of those cases: we've built our own container with the aggregate catalogs and even provided explicit hints to the container for marrying imports and exports. To allow the PartInitializer to use our container, we register it through a static method on the composition host. This is the InitializeContainer call you see, passing it the MEF container ("little c").

All of this happens in the bootstrapper. We'll call the InitializeCompositionHost from an override used to configure the Unity container: ConfigureContainer.

Now we've set up the initial application and configured our container. We still need a way to register dynamic modules as they are loaded. For this, we'll go to our common project and make a new base class for modules that will play in the MEF space. Instead of basing these modules on IModule, we'll base them on the new base class that implements IModule, called PartModule. This is what the part module base class looks like:


public abstract class PartModule : IModule
{
    [Dependency]
    public ICatalogService CatalogService { get; set; }

    public virtual void Initialize()
    {
        var assembly = this.GetType().Assembly;

        var types = assembly.GetTypes().Where(t => !typeof(IModule).IsAssignableFrom(t));

        CatalogService.Add(new TypeCatalog(types));
    }
}

First, we go ahead and implement IModule as is required by PRISM for a module. Next, notice that we let Unity provide us our singleton ICatalogService instance by providing a property and decorating it with the Dependency attribute.

Next, we implement Initialize and grab the assembly. We grab all of the types available in the assembly and add them to our aggregate catalog using a type catalog. This literally makes all types in the current assembly available for export. Notice, however, we ignore IModule ... we don't want to create a circular reference or dependency and accidentally import the module itself!

Now we have all of the pieces in place to make PRISM friendly with MEF. We can now export and import across XAP boundaries and even handle dynamically loaded modules (in this case, we're letting PRISM handle loading and managing the modules).

There is no source for this entry because there is nothing to show yet. In the next and final installment, I will create a dynamic module based on MEF and complete the loop by demonstrating yet another dynamically loaded module along with a dynamically inserted view, all using MEF to resolve dependencies for us.

Jeremy Likness

Monday, December 21, 2009

PRISM, MEF and MVVM Part 1 of 3: Unity Glue

PRISM, also known as Composite WPF, has established itself as a very popular framework for building modular, scalable Silverlight applications. A newer contender, the Managed Extensibility Framework (MEF), has also grown in popularity. In fact, these two frameworks have left people scratching their heads wondering which one to use, when, how, and why.

Please feel free to read the rest of this series, but if you are interested in pairing MVVM with MEF in Silverlight, I strongly recommend you check out my Jounce MVVM with MEF framework for Silverlight. The framework was written from the ground up using the Managed Extensibility Framework and has been used in production line of business applications. Visit the link above to learn more, read the case studies of successful projects that have used the framework, and to download and try out the framework for yourself.

Download the source code for this project.

Special note: the source won't run "as is." You need to take two steps: first, right click the PRISMMEF.Web project and choose, "set as start project." Second, right click the PRISMMEFTestPage.aspx and choose "set as start page." Then the project will run fine.

MEF will be packaged with Silverlight 4, and indeed has several preview releases available that will work on Silverlight 3 and 4. PRISM is coming out with newer releases that embrace the MEF framework. In fact, both frameworks work well together and know how to talk to each other's containers.

In this series of posts I want to explore some concepts and aspects of solving the Silverlight application problem using both PRISM and MEF. I will use PRISM primarily for its ability to integrate views into regions, to dynamically load modules, and to provide an abstract messaging contract with the event aggregator. MEF will be used for extensibility and to really tap into the ability to go out, find exports, and glue them into imports.

My primary goal in this short series will be to establish patterns for binding the view model to the view, and to dynamically load views and modules. We'll look at how to do this in the current version of Silverlight 3. It's important to note that future MEF releases may address some of the issues I tackle here and will make some workarounds obsolete, so stay tuned with that. I also want to express my sincere gratitude to Glenn Block (or, if you prefer, @gblock), a key member of the MEF team (and former member of the PRISM team, I believe, as well) for helping me with some of these examples and providing invaluable insights related to the inner workings of MEF.

Today we're going to leave MEF to the side and focus on what PRISM and the IoC container that comes with it, Unity, provide. The challenge is something I see discussed quite often, and that is how to meld the view model and the view together. Some people seem to abhor using code-behind at all, so I want to tackle a few solutions to this while also providing my own pragmatic way that, ahem, does use a little bit of code behind (and explain why I really don't care).

So, let's get started. We're going to have three main views today. The first will be the outer shell, which binds to a message and a button to dynamically load a second module. The module will have a second view that, in turn, will activate a third view. I am also going to show you three ways to bind your view model to your view using Unity. I will use view models with depedencies because these are the ones that cannot be referenced directly in XAML because the XAML parser doesn't implicitly know how to resolve dependencies.

The pattern for establishing a PRISM project is fairly well-established by now. We create a new Silverlight Application, blow away the default user control provided, then make a shell and a bootstrapper class that inherits from UnityBootstrapper.

I'll also add a class project called "common" to hold interfaces, base clases, and other services or parts that are used by the entire application.

In common, we'll define our service behavior. This could be wired to a "real" service but for now is just a mock one to demonstrate how these various methods work. The service contract looks like this:


public interface IService
{
   void GetStuff(Action<List<string>> action);

   void GetMoreStuff(Action<List<string>> action); 
}

I'm using the method outlined in Simplifying Asynchronous Calls in Silverlight Using Action. We call the service, and send it a method to call back on us with the returned value. In this case, it is just two different lists of strings.

I created a separate project "service" to implement the interface. The code is simple, and is also the first place I use a little MEF. I'm simply exporting the service so that if I want to use MEF to import it, I can. Today we'll let Unity wire it up and I'll show you how.

The service implementation is straightforward. Again, we'll add some MEF so it's ready when we look into it. In this case, instead of calling a "real" service, I just hit the callback with a pre-determined list of numbers that most will recognize. The second method does the same, only in Spanish. The class looks like this:


[Export(typeof(IService))]
public class Service : IService
{
    public void GetStuff(Action<List<string>> action)
    {
        action(new List<string> { "One", "One", "Two", "Three", "Five", "Eight", "Thirteen" });
    }

   public void GetMoreStuff(Action<List<string>> action)
    {
        action(new List<string> { "Uno", "Uno", "Dos", "Tres", "Cinco", "Ocho", "Trece" }); 
    }

    #endregion
}

Method 1: Provider

So now we can work on our view models. The main shell simply shows a title and exposes a button to click to dynamically load another module. The model looks like this:


public class ShellViewModel 
{
    const string APPLICATION = "This is the PRISM/MEF project demonstration.";

   public ShellViewModel(IModuleManager moduleManager) 
    {
        ModuleCommand = new DelegateCommand<object>(o =>
        {
            moduleManager.LoadModule("Module");
        });           
    }

    public ShellViewModel()
    {            
    }

    public string Title
    {
        get { return APPLICATION; }
    }

    public DelegateCommand<object> ModuleCommand { get; set; }    
}

Our problem with instantiating this in XAML is that the XAML parser doesn't understand how to resolve the dependency for IModuleManager. This is needed because I am going to dynamically load another module when you click the button bound to the ModuleCommand. As I mentioned, there are several ways to make the glue and one way is to use a provider.

The provider is a base class which has only two purposes. First, it is typed to a class so that multiple view models will generate multiple type instances. We need this so we can have different ways to resolve our classes. Second, it exposes a mechanism to resolve our models. In this way, I'm not tightly coupled to Unity. I recognize that there has to be some external force supplying me with the object to resolve dependencies, but I'll hold off on understanding just what that is.

This leaves me with something like this:


public abstract class ViewModelProviderBase<T> : INotifyPropertyChanged where T: class
{
    public static Func<T> Resolve { get; set; }

    public ViewModelProviderBase()
    {
        T viewModel = Resolve();
        if (viewModel != null)
        {
            _viewModel = viewModel; 
        }
    }

    private T _viewModel;

    public T ViewModel
    {
        get { return _viewModel; }
        set
        {
            _viewModel = value;
            OnPropertyChanged("ViewModel");
        }
    }        

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName)); 
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

So what we have is a base class typed to something. It exposes a static method to resolve that something. This is why the generic type works, so we have one method for resolution per type. It holds a reference to "whatever" and exposes it in the ViewModel property, all the while playing nice with the property changed notifications to update any bindings. What does this buy us?

Now, to resolve my main view model, I can create a provider like this:


public class ShellViewModelProvider : ViewModelProviderBase<ShellViewModel>
{        
}

Fairly straightforward, now we have a typed instance. In my bootstrapper or somewhere that "knows" what I've chosen to manage my objects, I can assign the resolver function like this:


ShellViewModelProvider.Resolve = Container.Resolve<ShellViewModel>;

Now the provider knows how to ask for a new instance of the type, with all dependencies sorted out. Then, in the XAML, we can simply bind the view model with no code behind by pointing to the provider, like this:


<UserControl.Resources>
   <vm:ShellViewModelProvider x:Key="ViewModelProvider"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource ViewModelProvider},Path=ViewModel}">

The resource creates a new instance of the provider. This calls to our resolver (in this case, the Unity container) and returns the view model, then binds it through the exposed ViewModel property.

We've achieved a binding without code behind, but it feels a little "artificial." While there wasn't code behind, we did have to do some extra work up front to glue the resolver to the type. Let's try something a little more natural in our dynamic module.

Method 2: View Injection

To me, this method feels like it makes the most sense. It is able to facilitate giving me objects and resolving dependency trees without the classes really knowing "how" it's done. In the last example, we had a base provider that was a sort of liason and had knowledge of the model and the way the model is resolved. With constructor injection, you simply have a class and are given your concrete instances. You program to the interface, and don't worry about how those interfaces were resolved. It's the pure essence of a Unity pattern where the bootstrapper wires it up, then starts making objects and injecting what they need.

To make our dynamically loaded module, we add a new project as a Silverlight Application (this is important, it's added as an application, not as a class library). I called this just "Module." I can add all of the references that the parent project has, then right click and set "copy local" to false. The references will be there when the module is loaded, so doing this lets you code to the references without having a bloated XAP file. Most of the modular XAPs with dynamic PRISM are a few kilobytes as opposed to the 100K+ "main" XAPs that get generated due to this layering and reuse.

Set up a module catalog by adding a type of "Silverlight Resource Dictionary" which generates a XAML file with no code behind and a content type of "page." You can change this to extend to the PRISM module namespace and declare your modules, like this (mine is in a subfolder called Modules, and I called the file ModuleCatalog.xaml).


<m:ModuleCatalog xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:sys="clr-namespace:System;assembly=mscorlib"
                 xmlns:m="clr-namespace:Microsoft.Practices.Composite.Modularity;assembly=Microsoft.Practices.Composite">
    <m:ModuleInfoGroup Ref="PRISMMEF.Module.xap" InitializationMode="OnDemand">
        <m:ModuleInfo ModuleName="Module"
                      ModuleType="PRISMMEF.Module.ModuleInit, PRISMMEF.Module, Version=1.0.0.0"/>
    </m:ModuleInfoGroup>   
</m:ModuleCatalog>

Here, I'm giving the module all it needs: a name, the XAP it will load from, and how the assembly and types marry in. PRISM wants the type of the module class to call to initialize everything once the XAP file is loaded. You wire this type of catalog into PRISM by doing this in the bootstrapper:


protected override IModuleCatalog GetModuleCatalog()
{
   return ModuleCatalog.CreateFromXaml(
       new Uri("PRISMMEF;component/Modules/ModuleCatalog.xaml", UriKind.Relative));
}

If you don't remember, in the main view model we took in a reference to the module manager and wired a command to do this: moduleManager.LoadModule("Module");. This causes the module manager to look up in the catalog, find the entry, note that it is not yet loaded, then pull in and parse the XAP. This is the dynamic loading.

Let's hop over to the dynamically loaded module. This module is going to use the service and bind a list of controls to the first method (the one that returns numbers in English). The view model looks like this:


public class StuffViewModel : INotifyPropertyChanged
{
    public StuffViewModel(IService service)
    {
        ListOfStuff = new ObservableCollection<string>();
        service.GetStuff(stuff =>
            {
                foreach (string thing in stuff)
                {
                    ListOfStuff.Add(thing);
                }
            });       
    }

    private DelegateCommand<object> _dynamicViewCommand;

    public DelegateCommand<object> DynamicViewCommand
    {
        get { return _dynamicViewCommand; }
        set
        {
            _dynamicViewCommand = value;
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs("DynamicViewCommand"));
            }
        }
    }
 
   public ObservableCollection<string> ListOfStuff { get; set; }


    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

A few things to notice here. First, there is a dependency on the service and when constructed, it will immediately call to the service to get the list of strings. Second, we have a command to dynamically load view (in this case, the view is loaded with the module, so a better term would be dynamically display the view), but we leave the resolution or implementation of the command up to external forces to decide.

Back in our Bootstrapper class, I need to tell Unity how to resolve the service. I override ConfigureContainer and give it this code:


protected override void ConfigureContainer()
{
    base.ConfigureContainer();
    Container.RegisterType&type;IService, Service.Service>();                                                                  
}     

Now Unity knows that when I ask for IService, I want Service.

In my new module, everything is set up in the ModuleInit. This is the type referenced in the catalog, and also implements IModule. We're going to to do two key things here. First, we'll take in a region manager and register the main view for this module. Second, we're going to tell Unity how to give us the view we'll show dynamically when we ask for it. This happens here:


public class ModuleInit : IModule
{
    IRegionManager _regionManager;
                    
    public ModuleInit(IUnityContainer container, IRegionManager regionManager)
    {
        container.RegisterType<UserControl, DynamicView>("DynamicView"); 
        _regionManager = regionManager;          
    }

    #region IModule Members

    public void Initialize()
    {            
        _regionManager.RegisterViewWithRegion("MainRegion", typeof(StuffView));
    }

    #endregion
}

Don't worry about the DynamicView control just let. We set up Unity to say, "If I want a UserControl, labeled DynamicView, give me the DynamicView type." We could just as easily made the label "foo" and provided the type "bar". The module initializer is a great place to configure the parts of the container specific to that module. The StuffView is what is displayed.

You've seen the view model, so let's talk about the view. The XAML looks like this:


<Grid x:Name="LayoutRoot" Background="White">   
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <ListBox ItemsSource="{Binding ListOfStuff}"/>
        <Button Grid.Column="1"
                Content="Add View"
                cal:Click.Command="{Binding DynamicViewCommand}"/>
    </Grid>

Two columns, one for the list of stuff, and the other a button to show the next view.

How do we glue our view model? As I mentioned, this does involve code behind but makes the most sense to me. We take advantage of the way Unity resolves dependencies and code our view like this:


public partial class StuffView : UserControl
{            
    public StuffView()
    {
        InitializeComponent();          
    }

    public StuffView(StuffViewModel viewModel, IUnityContainer container) : this()
    {
        LayoutRoot.DataContext = viewModel;
        viewModel.DynamicViewCommand = new DelegateCommand<object>(o =>
        {
            container.Resolve<IRegionManager>().RegisterViewWithRegion("MainRegion",
                () => container.Resolve<UserControl>("DynamicView")); 
        });
    }      
}

We could do this with properties and attribute them with the Dependency attribute as well. In this case, we reference the view model so it is wired in by Unity with any dependencies. Because we get the container, we're also able to resolve the IRegionManager and tell it to add the dynamic view to the region when the command is executed. Notice that here we are resolving UserControl, which we set up in the module initialization function. The important part is that my view doesn't have to understand how a region manager does what it does or know what the other view is, it simply calls the contract and passes along what the container resolves for us.

Of course, that command is not going to do much unless we have the actual view.

The dynamic view will share the same view model and show the same list for the sake of simplicity, but I wanted to show another way of wiring the view model to the view.

Method 3: Behaviors

Again, our challenge is that XAML doesn't know how to resolve dependencies. So, we can use constructors or decorated properties and let Unity wire them in, or create our own constructs that have to be notified about what to do and then supply the needed classes.

This method uses an attached property to create the view model and attach it to the view. This time instead of keeping it overly generic, I went ahead and referenced the unity container. The behavior needs to be wired up with the container so it can resolve view models, but the view model type is passed dynamically.

The behavior looks like this:


public static class ViewModelBehavior
{
    // this is the part I like the least, could abstract it
    // but this example is long enough already!
    public static IUnityContainer Container { get; set; }

    public static DependencyProperty ViewModelProperty = DependencyProperty.RegisterAttached(
        "ViewModel",
        typeof(string),
        typeof(ViewModelBehavior),
        new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnModelAttached)));

    public static string GetViewModel(DependencyObject obj)
    {
        return obj.GetValue(ViewModelProperty).ToString();
    }

    public static void SetViewModel(DependencyObject obj, string value)
    {
        obj.SetValue(ViewModelProperty, value);
    }

    public static void OnModelAttached(object sender, DependencyPropertyChangedEventArgs args)
    {
        FrameworkElement element = sender as FrameworkElement;

        if (element != null)
        {
            if (args.NewValue is string)
            {
                string viewModelContract = args.NewValue.ToString();
                if (!string.IsNullOrEmpty(viewModelContract))
                {
                    Type type = Type.GetType(viewModelContract);
                    element.DataContext = Container.Resolve(type); 
                }
            }
        }
    }
}

So what's interesting here is that we have a reference to the unity container, and what happens when the property is attached. It is expecting a fully qualified type passed in a string. We use the Type class to resolve the type, then use the containe to resolve the instance and bind it to the data context of the element that had the behavior attached.

This leaves our code-behind clean:


public partial class DynamicView : UserControl
{
    public DynamicView()
    {
        InitializeComponent();
    }
}

And gives us flexibility to use the behavior to wire in whatever we want in the XAML:


<Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <TextBlock Text="This list was bound using the behavior."/>
    <ListBox 
        Grid.Row="1" 
        vm:ViewModelBehavior.ViewModel="PRISMMEF.Module.ViewModel.StuffViewModel, PRISMMEF.Module, Version=1.0.0.0" 
        ItemsSource="{Binding ListOfStuff}"/>


Notice the fully qualified view model type on the ListBox, which uses the behavior to resolve and then bind the view model. Wrapping Up

What we can do now is show a view with a button that was bound with no code behind and let Unity wire in dependencies. Clicking the button dynamically loads a new module that takes in a service reference, calls the service, and shows items returned from the service. This is wired in and bound in the code behind and uses constructor injection. This new view then displays the list next to a button that adds another view, bound to the same list.

All of these scenarios require a bit of work to get where we need to go. Will MEF give us something better? Perhaps. Next post, I will explore why out of the box in Silverlight 3 we can't simply glue pieces together using MEF without digging into the internals and providing some infrastructure. Much of that infrastructure will be out of the box in future versons, but this will help us understand what is going on behind the scenes. We will set up the infrastructure in anticipation of using MEF, then the third and final installment will involve another dynamically loaded module that wires it all together using MEF with a little help from Unity.

Stay tuned!

Download the source code for this project.

Special note: the source won't run "as is." You need to take two steps: first, right click the PRISMMEF.Web project and choose, "set as start project." Second, right click the PRISMMEFTestPage.aspx and choose "set as start page." Then the project will run fine.

Jeremy Likness

Thursday, December 17, 2009

Fractal Koch Snowflakes in Silverlight

So late last night I decided that since I spend most of the day writing software for other companies, it was time to build something for my daughter. I knew right away it would be snowflakes. I'm not much of a "graphic design" guy, but I do know math, so when I can lean on math to make pretty things, I'm all for it.

What I decided to do was create some fanciful "snowflakes" that would drift around the screen. The result is the snowflake scene you can view by clicking here:

Fractal Koch Snowflakes in Silverlight.

The Koch curve made the most sense for a starting point because, well, it's fairly easy! You simply start with a line segment, break it into thirds, then extend the middle into a new triangle. The sequence looks like this:

Koch Curve

Imagine that happening with the three sides of a triangle, and you start to understand how a snowflake will come out of the process. The still picture doesn't give full justice to how it looks in motion with your CPU maxing out:

Koch Snowflake Snapshot

Download the Source

So let's get down to business. The first step was to build a factory to generate the snowflakes for me. Understanding the math is pointless (pardon the pun) unless I can turn it into a shape.

The following method will take a list of points and turn it into a path. There is no optimization or determining how wildly the points jump around ... just takes it and turns it straight into the path object:


private static Path _CreatePath(List<Point> points)
{            
    PathSegmentCollection segments = new PathSegmentCollection();

    bool first = true;

    foreach (Point point in points)
    {
        if (first)
        {
            first = false;
        }
        else
        {
            segments.Add(
                new LineSegment
                {
                    Point = point
                });
        }
    }

    PathGeometry pathGeometry = new PathGeometry();

    pathGeometry.Figures.Add(
        new PathFigure
    {
        IsClosed = true,
        StartPoint = points[0],
        Segments = segments
    });

    return new Path { Data = pathGeometry };            
}

It should be fairly straightforward ... we combine the lines into a set of segments, collapse the segments into a figure that is closed, then add the figure to the path.

Next, we need to be able to take a line segment and divide it. The math is fairly straightforward (you can Bing Koch Curve to find it). I created this little method to return the points in the way I think: one step at a time.


private static IEnumerable<Point> _RefactorPoints(Point a, Point b)
{
    yield return a; 

    double dX = b.X - a.X; 
    double dY = b.Y - a.Y;

    yield return new Point(a.X + dX / 3.0, a.Y + dY / 3.0);

    double factor = _random.NextDouble() - 0.5;

    double vX = (a.X + b.X) / (2.0 + factor) + Math.Sqrt(3.0+factor) * (b.Y - a.Y) / (6.0 + factor*2.0);
    double vY = (a.Y + b.Y) / (2.0 + factor) + Math.Sqrt(3.0+factor) * (a.X - b.X) / (6.0 + factor*2.0);

    yield return new Point(vX, vY);

    yield return new Point(b.X - dX / 3.0, b.Y - dY / 3.0);

    yield return b;
}

The segment will end up being 4 segments, or 5 points. First, we return the first point. Next, we find a point 1/3 of the way from point a to point b. Next we have some fun. The equation approximates finding the point for the apex of a unilateral triangle, but we jiggle it a bit with some randomness to make for unique snowflakes and then return that point. Next, it's 1/3 of the way to point a from point b, and finally it's point b itself.

Easy enough? Now that we can split a side into pieces, we can now write our recursive method to continuously break down segments. It will take in a level (how many iterations to do) and then start hacking away. Keep in mind the levels can't get too high because of the exponential growth (3 points becomes 15, becomes 75, etc). Here is that routine, which ultimately takes in a segment and gives me back a fully iterated collectoin of points that represent the Koch curve:


private static List<Point> _RecurseSide(Point a, Point b, int level)
{
    if (level == 0)
    {
        return new List<Point> { a, b };
    }
    else
    {
        List<Point> newPoints = new List<Point>();

        foreach (Point point in _RefactorPoints(a, b))
        {
            newPoints.Add(point);
        }

        List<Point> aggregatePoints = new List<Point>();

        for (int x = 0; x < newPoints.Count; x++)
        {
            int y = x + 1 == newPoints.Count ? 0 : x + 1;
            aggregatePoints.AddRange(_RecurseSide(newPoints[x], newPoints[y], level-1));                    
        }

        return aggregatePoints; 
    }
}

As you can see, if we hit the iteration target, we return the segment back. Otherwise, we split the segment, then recursively call the method on each new segment and decrement the level.

Now we can spin it all off with three staring points (the vertices of our triangle ... and I know that this isn't a unilateral triangle, but it works):


public static Path Create()
{
    Point a = new Point(0, 0);
    Point b = new Point(_random.NextDouble()*70.0+15.0, 0);
    Point c = new Point(0, b.X); 

    int levels = _random.Next(MIN, MAX);

    List<Point> points = new List<Point>();
    points.AddRange(_RecurseSide(a,b,levels));
    points.AddRange(_RecurseSide(b,c,levels));
    points.AddRange(_RecurseSide(c,a,levels));

    // walk the sides and iterate them
    Path retVal = _CreatePath(points);           
   
    return retVal;  
}

That gets us a snowflake. If you are a stickler for optimizing the code, a good side project would be to kill the second and third calls to recurse the side. Once we have one segment, we can simply reflect/rotate it to complete the triangle without necessarily having to compute the points all over again. I'll leave that up to some math wizard to work out with matrix transformations.

Of course, a snowflake like that is pretty boring. I added a method to colorize it using a random gradient (and random alpha so they are semi-transparent) and also set the path up with a rotate transform and plane projection, so it can be spun and twisted on the screen. Nothing special there; you can inspect those methods in the source code.

My next step was to encapsulate the snowflake in a class that would handle animating and moving it on the screen. The idea is that each snowflake has a unique behavior, and appears, falls gently, then disappears and notifies the world that's gone so we can make a new one.

The class I built, SnowFlakeEntity, is here in it's entirety:


public class SnowFlakeEntity
{
    const double LEFT = 800.0;
    const double TOP = 600.0;
    const double GONE = 700.0;

    private double _affinity; // affects behaviors

    DispatcherTimer _snowflakeFrame; 

    private Guid _identifier = Guid.NewGuid();       

    private static Random _random = new Random();

    private Canvas _surface; 

    public Canvas Surface
    {
        get { return _surface; }
    }

    private double x, y, velocity;

    private Path _snowflake;

    public Guid Identifier
    {
        get { return _identifier; }
    }
   
    public SnowFlakeEntity(Action<Path> insert) : this(insert, false)
    {
    }

    public SnowFlakeEntity(Action<Path> insert, bool fromTop)
    {
        _snowflake = SnowFlakeFactory.Create();

        _affinity = _random.NextDouble();

        velocity = _random.NextDouble() * 10.0;
        x = _random.NextDouble() * LEFT;
        y = fromTop ? -100.0 : _random.NextDouble() * TOP;

        _snowflake.SetValue(Canvas.LeftProperty, x);
        _snowflake.SetValue(Canvas.TopProperty, y); 

        insert(_snowflake);

        _surface = _snowflake.Parent as Canvas;

        _snowflakeFrame = new DispatcherTimer();
        
        _snowflakeFrame.Interval = TimeSpan.FromMilliseconds(_random.NextDouble()*25 + 25.0);
        _snowflakeFrame.Tick += (o, e) => _Frame();
        _snowflakeFrame.Start(); 
    }

    private void _Frame()
    {
        y = y + velocity + 3.0 * _random.NextDouble() - 1.0;

        if (y > GONE)
        {
            _snowflakeFrame.Stop();
            _snowflakeFrame = null;

            _surface.Children.Remove(_snowflake);                

            EventHandler handler = SnowflakeDied;
            if (handler != null)
            {
                handler(this, EventArgs.Empty); 
            }
        }
        else
        {
            double xFactor = 10.0 * _affinity;
            if (_affinity < 0.45) xFactor *= -1.0;
            x = x + _random.NextDouble() * xFactor;
            
            if (x < 0)
            {
                x = 0;
                _affinity = 1.0 - _affinity;
            }

            if (x > LEFT)
            {
                x = LEFT;
                _affinity = 1.0 - _affinity;
            }

            _snowflake.SetValue(Canvas.LeftProperty, x);
            _snowflake.SetValue(Canvas.TopProperty, y);
        }

        RotateTransform rotate = (RotateTransform)_snowflake.GetValue(Path.RenderTransformProperty);
        rotate.Angle += _random.NextDouble() * 4.0 * _affinity;

        PlaneProjection plane = (PlaneProjection)_snowflake.GetValue(Path.ProjectionProperty);
        double rotateFactor = 6.0 * _affinity;
        plane.RotationX += _random.NextDouble() * rotateFactor;
        plane.RotationY += _random.NextDouble() * rotateFactor;
        plane.RotationZ += _random.NextDouble() * rotateFactor;
    }

    public event EventHandler SnowflakeDied;

    #region Overrides 

    public override int GetHashCode()
    {
        return Identifier.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        return obj is SnowFlakeEntity && ((SnowFlakeEntity)obj).Identifier.Equals(Identifier); 
    }

    #endregion 
}

Since every snowflake is unique, I give it a unique identifier that I use in the hash code and comparison methods. This makes it easy to remove from a list because it has a unique tag to identify itself. Most of the internal parameters are straightforward: the class itself has a singleton random number generator, we track a velocity (so they fall at different rates) and some coordinates.

When the snowflake is constructed, it can either appear on a random portion of the screen (when the application is first fired up) or get created offscreen at the top so it can drift in (this is when a replacement snowflake is generated for one that fell offscreen). The snowflake sets up a dispatcher timer with frames to update itself. This is a little expensive (with 75 snowflakes, that's 75 timers to keep track of) ... I could probably hook into the composition render event and iterate the list instead for more efficiency. Something to look into!

The _affinity variable gives the snowflake its own unique twist. It controls the direction of drift (left or right, you can see I set it up so slightly more will start out drifting right) and also factors into the rate of spinning and twisting. You can see in each frame that the snowflake updates itself using this, and if it goes off an edge, it flips the affinity to start drifting the opposite direction. This has interesting side effects due to the multipliers in rotation: you'll notice, for example, that a slow snowflake that drifts off the left edge will suddenly move very quickly to the right.

The snowflake delegates getting inserted onto the Canvas to whatever is hosting it, but once it is on the surface, it knows it has a parent and exposes that property. When the snowflake goes off the screen, it shuts down the dispatcher, removes itself from the canvas, then raises an event so the "outside world" knows that its time to create a new snowflake.

Now that we have a snowflake, its time to create the environment for the snowflakes to live in. I decided to implement it as an attachable behavior to a canvas. This snippet defines the behavior as well as a list of snowflakes to manage. Because this is not optimized, I settled on 75 but for your machine you may be able to handle more or less.


public static class SnowFlakeBehavior
{
    const int CAPACITY = 75; 

    private static List<SnowFlakeEntity> _snowflakes = new List<SnowFlakeEntity>(CAPACITY);

    public static DependencyProperty AttachSnowFlakeProperty = DependencyProperty.RegisterAttached(
        "AttachSnowFlake",
        typeof(bool),
        typeof(SnowFlakeBehavior),
        new PropertyMetadata(false, new PropertyChangedCallback(_Attach)));

    public static bool GetAttachSnowFlake(DependencyObject obj)
    {
        return (bool)obj.GetValue(AttachSnowFlakeProperty);
    }

    public static void SetAttachSnowFlake(DependencyObject obj, bool value)
    {
        obj.SetValue(AttachSnowFlakeProperty, value);
    }
}

When we are attached, we check to make sure the flag passed is "true" and then wait for the canvas to get fully loaded:


public static void _Attach(object sender, DependencyPropertyChangedEventArgs args)
{
    Canvas canvas = sender as Canvas; 

    if (canvas != null && args.NewValue != null && args.NewValue.GetType().Equals(typeof(bool)) && (bool)args.NewValue)
    {
        canvas.Loaded += new RoutedEventHandler(Canvas_Loaded);
    }
}

When the canvas is loaded, we can start making snowflakes!


static void Canvas_Loaded(object sender, RoutedEventArgs e)
{
    Canvas canvas = sender as Canvas;
    for (int x = 0; x < _snowflakes.Capacity; x++)
    {
        SnowFlakeEntity snowflake = new SnowFlakeEntity((o) => canvas.Children.Add(o));
        snowflake.SnowflakeDied +=new EventHandler(Snowflake_SnowflakeDied);
        _snowflakes.Add(snowflake);
    }
}

The last piece to wire in is to make a new snowflake when an existing one dies:


static void Snowflake_SnowflakeDied(object sender, EventArgs e)
{
    SnowFlakeEntity snowflake = sender as SnowFlakeEntity;
    
    Canvas canvas = snowflake.Surface; 

    _snowflakes.Remove(snowflake);

    SnowFlakeEntity newFlake = new SnowFlakeEntity((o) => canvas.Children.Add(o), true);
    newFlake.SnowflakeDied += Snowflake_SnowflakeDied;
    _snowflakes.Add(newFlake);
}

If you have a keen eye, you'll probably gripe about the way I cheated a bit using the Surface property. Instead of worrying about state and storing the canvas, I take the old, dead snowflake and simply attach the new one to the same surface. It probably works out fine in the end, but a purist would argue that the snowflake really shouldn't even know or care about its parent. Anyway, we simply register for the new death and send the new snowflake on its way.

Here's a rhetorical question for you: do I need to unregister the event from the old snowflake? We're removing any reference to it by pulling it from the list. Events can be a source of memory leaks when mismanaged. Who "holds" the event reference, my behavior or the SnowFlakeEntity class?

Now we can build a canvas to host the snowflakes. Our main requirement is to attach the snowflake behavior. We also want to clip the canvas so the snowflakes don't go offscreen as they are being added and recycled. The basic layout looks like this:


<Canvas snow:SnowFlakeBehavior.AttachSnowFlake="true"
   x:Name="LayoutRoot"  
   Width="800" 
   Height="600" 
   Margin="5">
   <Canvas.Clip>
      <RectangleGeometry Rect="0,0,800,600"/>
   </Canvas.Clip>
</Canvas>

I embellished with a gradient and a "Merry Christmas" message, all of that is in the source.

There you have it ... a nice little window that displays "drifting" fractal snowflakes. Of course, I wrote it for my daughter, so ... Merry Christmas, Lizzie!

Fractal Koch Snowflakes in Silverlight.

Download the Source

Jeremy Likness

Wednesday, December 16, 2009

Dispatching in Silverlight

Anyone who has been building Silverlight and/or WPF applications for some time understands that there is a single UI thread that has special access requirements if you are going to be updating elements. In other words, if I spin off a new thread, I cannot arbitrarily impact the UI unless I get back to the UI thread using a dispatcher.

Fortunately, Silverlight makes it very easy to find your dispatcher, because it is a property on any UIElement that exists, including your own user control. If I need to make sure a thread executes on the UI thread, I simply do something like this:


this.Dispatcher.BeginInvoke(()=>MyFunc()); 

Things get a little more tricky if you are trying to access the dispatcher from an entity that doesn't know about the UI thread ... for example, a view model.

Let's say you have a view model that needs to kick of a separate thread to do some work, and then update properties that are bound to the UI. By design, the view model interacts with services and exposes properties but it doesn't know about the view. We could sell out by giving it a Dispatcher property, but that could get ugly in scenarios such as unit tests where there simply may not be a UI thread.

Once again I'm happy to go back to the C# keywords that make our lives easier. In the past, I would have simply raised an event, "I need this" and passed some arguments, but with Action at our fingertips, it's so much easier!

In fact, this is all it really takes ... note the use of an action that takes a, um, ahem, action:


public class ViewModel 
{

   public Action<Action> UIAction { get; set; }

   public ViewModel()
   {
      UIAction = ((uiAction)=>uiAction());
   }

}

Seems fairly simple, doesn't it? Any time I am going to update one of my databound properties in a disconncted thread, I simply do this:


UIAction(()=>{ viewModel.Property = "New value";}); 

Right now, this isn't doing anything really interesting, because the action delegate simply calls the action we pass ... very boring, really. It will pass unit tests and all of that jazz ... so why'd I do it?

Because, once I bring the view model into an actual view, then I'll need to give it the dispatcher. Then, I can do something like this:


ViewModel viewModel = new ViewModel();
this.DataContext = viewModel; // or bind it with MEF to make it more fun
viewModel.UIAction = ((uiAction) => Dispatcher.BeginInvoke(()=>uiAction())); 

Now we've set it up so that when you call the action with an action, the action is to perform the action inside the dispatcher thread (got all that?). Now the view model plays equally well in the view and out of the view. It is still ignorant of what the view is or even that there is a dispatcher, and only needs to know that updating protected properties should be wrapped in the UIAction.

Let's save the argument over whether we should even be spinning threads from the view model that modify the UI thread for another day, mmmmm kay?

Jeremy Likness

Friday, December 11, 2009

Unit Tests for ViewModels AND Views in Silverlight

Over the past few posts I've been exploring models for modularized Silverlight applications that follow the MVVM pattern (using Prism/CAL). In this post, I'd like to cover unit testing, and writing appropriate tests not just for the view model, but the view itself.

Before we continue, I'm going to assume you've read:

These articles form the core of what I'm about to discuss. I also want to make sure you're familiar with the Silverlight unit testing framework. You can download it and review some articles about how to use it over at the Unit Test Framework for Microsoft Silverlight page. I highly recommend pulling down the project and class templates as they will make your life easier!

The testing framework for Silverlight sets up a project that you run, and that project will then create a visual page that displays the results of tests. What's important is that the test framework will not only support class tests, but can also host controls and test the hosted controls as well. Do we even want to do this? I think so.

Set up your test project and make it the runnable one by adding a new project to your existing Silverlight solution, using the Silverlight project template, then right-clicking on the project and setting it as the start-up project.

Let's get started with a real example. I want to control the visibility of a control based on a boolean value in the view model, so I create a converter that takes in a boolean and returns visibility. I can bind the visibility like this:


<TextBlock Text="Conditional Text" Visibility="{Binding ConditionFlag,Converter={StaticResource BoolVisibilityConverter}}">

The code for the converter is simple:


public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    return (bool)value ? Visibility.Visible : Visibility.Collapsed;
}

To test that we get what we want, simply add a new class in your test project (use the Silverlight Test Class template). With a little bit of typing you will end up with something like this:


[TestClass]
public class BoolVisibilityConverterTest
{
    BoolVisibilityConverter _target;

    [TestInitialize]
    public void Initialize()
    {
        _target = new BoolVisibilityConverter();
    }

    [TestMethod]
    public void TestTrue()
    {
        object result = _target.Convert(true, typeof(bool), null, CultureInfo.CurrentCulture);
        Assert.IsNotNull(result, "Converter returned null.");
        Assert.AreEqual(Visibility.Visible, result, "Converter returned invalid result.");
    }

    [TestMethod]
    public void TestFalseNoParameter()
    {
        object result = _target.Convert(false, typeof(bool), null, CultureInfo.CurrentCulture);
        Assert.IsNotNull(result, "Converter returned null.");
        Assert.AreEqual(Visibility.Collapsed, result, "Converter returned invalid result.");
    }
}

Not rocket science there ... but it's nice to start out with a few green lights. When you run it, you'll see that your two tests passed and all is well (you can, of course, assert something invalid to see what a failure looks like).

Now let's test a view model. Our view model takes in a IService reference so that it can log a user in. It has bindings for username and password and a login command. The service looks like this:


public interface IService 
{
   void Login(string username, string password, Action<bool> result); 
}

So the view model looks like this:

public class ViewModel : INotifyPropertyChanged 
{
   private IService _service;

   public ViewModel(IService service)
    {
        _service = service;
       
        LoginCommand = new DelegateCommand<object>( o=>CommandLogin );            
    }  

    private bool _isDirty;

    public bool IsDirty
    {
        get { return _isDirty; }
    }

    private string _username, _password;

    public string Username
    {
        get { return _username; }
        set
        {
            if (value != null && !value.Equals(_username))
            {
                _username = value;
                OnPropertyChanged("UserName");                
            }
        }
    }

    public string Password
    {
        get { return _password; }
        set
        {
            if (value != null && !value.Equals(_password))
            {
                _password = value;
                OnPropertyChanged("Password");
            }
        }
    }

   public DelegateCommand<object> LoginCommand { get; set; }

   public void CommandLogin()
    {
        if (string.IsNullOrEmpty(_username))
        {
            throw new ValidationException("Username is required.");
        }

        if (string.IsNullOrEmpty(_password))
        {
            throw new ValidationException("Password is required.");
        }

        _service.Login(_username, _password, (result) =>
        {
            if (result)
            {
                // logic to navigate to a new page
            }
            else
            {
                throw new ValidationException("The username/password combination is invalid.");
            }
        });
    } 

    protected void OnPropertyChanged(string property)
    {            
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(property));
        }
        if (!_isDirty)
        {
            _isDirty = true;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs("IsDirty")); 
            }
        }
    }

    public void ResetDirtyFlag()
    {
        if (_isDirty)
        {
            _isDirty = false;
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs("IsDirty"));
            }
        }
    } 
}

Notice how properties being set should automatically set the "dirty" flag as well. I may want to bind my login button to the flag so it only becomes available when the user has changed something, for example. There is also a public method to reset the flag.

In order to satisfy my service, I'll create a "mock" object. Why a mock, and not a stub? A stub is a piece of code you put in place to allow something to happen. If I wanted to stub my service, I'd do this:


public class ServiceStub : IService
{
   public void Login(string username, string password, Action<bool> result)
   {
      result(true); 
   }
}

This would always call back with a valid user and stubs out the functionality so I don't have to implement a real login. A mock object, on the other hand, changes. To make this a mock, I do this:


public class ServiceMock : IService 
{
   public bool LoginCalled { get; set; }

   public void Login(string username, string password, Action<bool> result)
   {
      LoginCalled = true;
      result(true); 
   }
   
}

The class is a mock because it changes based on how it is used, and then we can query that change to see if our code is doing what we want. So let's set up some tests with the view model:


[TestClass]
public class ViewModelTest
{

    private ViewModel _target;
    private ServiceMock _service;

    [TestInitialize] 
    public void Initialize()
    {
        _service = new ServiceMock();
        _target = new ViewModel(_service);

    }

    [TestMethod]
    public void TestConstructor()
    {
       Assert.IsFalse(_target.IsDirty,"Dirty flag should not be set."); 
       Assert.IsFalse(_service.LoginCalled,"Login should not have been called.");
       Assert.IsNotNull(_service.LoginCommand, "Login command was not set up."); 
    }
}

You can test that the username hasn't been populated, for example. Now we can do a little more. In the example, we throw a ValidationException (a custom class) when the username is invalid. The Silverlight 3 validation framework can capture this based on data binding and show appropriate error messages to the client. We want to make sure if we try to login, we throw the exception, so we can do this:


[TestMethod]
[ExpectedException(typeof(ValidationException))]
public void TestLoginValidation()
{
   _target.CommandLogin(); 
}

Here we call the login command on the empty object and it should throw (and catch) the exception we're looking for.

Finally, to use our mock object, we can set a valid user name and password and call the login command, then verify that the mock object was called:


[TestMethod]
public void TestLogin()
{
   _target.Username = "Valid Username"; 

   //bonus test: check that the dirty flag got set
   Assert.IsTrue(_target.IsDirty, "Dirty flag was not set on update."); 

   _target.Password = "Password"; 
   _target.CommandLogin();

   Assert.IsTrue(_service.LoginCalled); 
}

After testing your view model, you can then begin to work on testing the view itself. In the "required reading" I discussed having a generic view base that would interact with a navigation manager to swap views into and out of view. The views are all contained in an ItemsControl, and register to a view change event. If the view goes out of focus, it moves to a hidden state. If the view comes into focus, it moves to a visible state. While this allows more control over the way the states appear and how to transition between states, there is also the chance someone may add a view and forget wire in the visual state groups. The VisualStateManager won't complain, but it can look ugly. We need to test for things like this!

Fortunately, the testing framework allows for us to host actual views. It provides a testing surface that we add controls to, and those controls are rendered so you can then inspect the visual tree. In this case, we want to emulate a view navigating to a new view and test that it is moved to the correct state.

Create a new test class. This time, however, we will inherit from the base class SilverlightTest which provides our class with a test panel to host controls on. The set up is a bit more involved, because we need to fold the mock services into the view model, then create the view and glue it all together.

Before we do this, we'll create a helper class called QueryableVisualStateManager. This class is one I borrowed from Justin Angel's fantastic blog post about Custom Visual State Managers. In his post, he details how to create a custom visual state manager that holds a dictionary of the control states so they can be queried later on (in case you've been pulling your hair out in frustration, the framework does not provide direct access to query the current visual state of controls).

I created the class verbatim, but don't care to use it in production code. Instead, we'll inject it in our test class. Here's the setup:


[TestClass]
public class LoginTest : SilverlightTest
{
    private Login _login;
    private ViewModel _viewModel;
    private ServiceMock _service;
    private NavigationManager _navigationManager;
    private QueryableVisualStateManager _customStateManager; 

    [TestInitialize]
    public void TestInitialize()
    {
        _login = new Login();
        
        FrameworkElement root = VisualTreeHelper.GetChild(_login, 0) as FrameworkElement;
        root.SetValue(VisualStateManager.CustomVisualStateManagerProperty, new QueryableVisualStateManager()); 

        _service = new ServiceMock();
        _navigationManager = new NavigationManager();
        _viewModel = new ViewModel(_service);
        _viewModel.Navigation = _navigationManager;
        _login.DataContext = _viewModel;
        TestPanel.Children.Add(_login);
    }
}

What happened? Login is my user control ... it is the view I inject into the shell to show the login page. Here I create an instance of it. Then, I use my friend the VisualTreeHelper to parse the the first child, which is going to be the grid or stack panel or whatever "host" control you have inside your user control. Then, I simply set the attached property for the custom view manager to point to the queryable helper class. This will ensure any visual state transitions are recorded in the internal dictionary. Then I wire up my mocks, databind, and finally add the login control to the TestPanel. It now gets hosted on a real test surface and can initialize and display.

Let's assume that the navigation manager I injected is responsible for swapping the view state of the control. The control goes into a HideState when not visible and a ShowState when visible. What I want to test is a simulated login command. We already tested this in the view model, so we can be confident it is going to hit the service and do what it is supposed to do. There is a piece of code that then calls the navigation manager and changes the control's state to hidden. We want to test that this hook actually gets fired when the user clicks login, so the login view disappears. Here's how:


[TestMethod]
public void TestLogin()
{
    const string SHOWSTATE = "VisualStates.ShowState";
    const string HIDESTATE = "VisualStates.HideState";

    // set up this view
    _navigationManager.NavigateToPage(NavigationManager.NavigationPage.Login);
                
    string state = QueryableVisualStateManager.QueryState(_login);
    Assert.IsTrue(state.Contains(SHOWSTATE) && !state.Contains(HIDESTATE), "Invalid visual state."); 

    // trigger login 
    _viewModel.Username = "user";
    _viewModel.Password = "password";
    _viewModel.CommandLogin();
   
    state = QueryableVisualStateManager.QueryState(_login);
    Assert.IsTrue(state.Contains(HIDESTATE) && !state.Contains(SHOWSTATE), "Invalid visual state."); 
}

We first test the pre-condition by navigating to the login page and confirming it has the ShowState and not the HideState. Then, we simulate a login action (this is why command binding and view models are so powerful) and query the state again, testing to make sure we went into a hidden state.

When you run this test, you might actually see the control flicker for a moment on the screen as it gets initialized on the test surface before it is manipulated and then discarded for other tests. With the right architecture, you are now able to test from the view down to the backend services that drive your application. Now that's powerful!

Jeremy Likness

Wednesday, December 9, 2009

Simplifying Asynchronous Calls in Silverlight using Action

This post explores a way to encapsulate web service calls from Silverlight in a way that is easy to use and understand.

As anyone who works with Silverlight knows, Silverlight forces web service calls to be asynchronous. There is a good reason for this, which I won't get into with this post. What I would like to do is demonstrate an approach that advocates a clean separation of the internals of the service from the application that is consuming it.

First, I am assuming you understand web services and WCF. I assume you've called services from Silverlight, and are aware of the nuances of configuring the endpoint, etc. I am also going to assume you are familiar with some frameworks such as Prism, MEF, Caliburn, etc that advocate clean separation of concerns and modular design.

Let's assume I have a service on my web page that is a calculator (oh, where did I get that idea?) It looks something like this:


[ServiceContract(Namespace = "http://www.wintellect.com/sample")]    
public interface ICalculatorService
{
    [OperationContract]
    long Multiply(int x, int y);
}

Simple, correct? The first thing I'm going to do is to create a similar interface on my Silverlight client. This interface will hide the details of how the service is connected and wired. I also want to make it easier to deal with the asynchronous nature of the calls. I've seen some pretty exotic implementations to try to make an asynchronous call look synchronous, and don't quite understand why we'd want to do it. Instead, let's just define a contract like this somewhere in the Silverlight application that is "seen" globally:


public interface ICalculator 
{
   void Multiply(int x, int y, Action<long> result); 
}

As you can see, it's a simple void method ... in fact, all methods we use to abstract the asynchronous calls will most likely be void. But the key is last parameter. This delegate allows me to specify how I want to deal with the result.

Now I create a project that is solely used to implement ICalculator and connect with the web service. First, if you haven't read my post about abstracting WCF service calls, be sure to read it: Abstracting WCF Service Calls in Silverlight. It explains how I use a base class to avoid having to change the ServiceReferences.ClientConfig file everytime I deploy an application, and also will give you the concept for the BaseService class you see below.


public class CalculatorService : BaseService<CalculatorServiceClient,ICalculatorService>, ICalculator
{
    public CalculatorService()
    {
        _GetClientChannel().MultiplyCompleted += new EventHandler<MultiplyCompletedEventArgs>(CalculatorService_MultiplyCompleted);
    }        

    #region Event handlers

    void CalculatorService_MultiplyCompleted(object sender, MultiplyCompletedEventArgs e)
    {
        Action<long> result = e.UserState as Action<long>;
        if (result != null)
        {
            result(e.Result); 
        }
    }

    #endregion 

    #region ICalculator Members

    public void Multiply(int x, int y, Action<long> result)
    {
        _GetClientChannel().MultiplyAsync(x, y, result);
    }

    #endregion
}

The base class preps the channel and credentials, etc for me. In the constructor of the implementation, I simply register for the completion event for the call. When a consumer of the service makes a call, the consumer provides a delegate to call back to when the service is done. This is passed in the user state, then cast back to an action and called once the service returns. If you wanted to have error handling, you'd just extend the action delegate to have an error-related parameter and check the e.Error when the call completed.

Now we can put it into use. In my bootstrapper, I'll bind the service to the contract like this:


Container.RegisterType<ICalculator,CalculatorService>(new ContainerControlledLifetimeManager());
            

Now I can throw a view model together that looks something like this:


public class CalculatorViewModel : INotifyPropertyChanged
{

    private bool _busy = false;

    public bool BusyState
    {
        get { return _busy; }
        set
        {
            if (!value.Equals(_busy))
            {
                _busy = value;
                OnPropertyChanged("BusyState");
                CalculateCommand.RaiseCanExecuteChanged();
            }
        }
    }

   public DelegateCommand<object> CalculateCommand { get; set; } 

    public CalculatorViewModel(ICalculator calculator)
    {
        Calculator = calculator;
        CalculateCommand = new DelegateCommand<object>(o => CommandCalculate(),
            o => !BusyState);
    }

    public ICalulator Calculator { get; set; }

    private int _x;

    public int X
    {
        get { return _x; }
        set
        {
            if (!value.Equals(_x))
            {
                _x = value;
                OnPropertyChanged("X"); 
            }
        }
    }

     private int _y;

    public int Y
    {
        get { return _y; }
        set
        {
            if (!value.Equals(_y))
            {
                _y = value;
                OnPropertyChanged("Y"); 
            }
        }
    }

    private long _answer;

    public long Answer
    {
        get { return _answer; }
        set
        {
            if (!value.Equals(_answer))
            {
                _answer = value;
                OnPropertyChanged("Answer"); 
            }
        }
    }

    public void CommandCalculate()
    {
        BusyState = true;
        Calculator.Multiply(_x, _y, answer => {
              BusyState = false;
              Answer = answer;
         }); 
    }

    private void OnPropertyChanged(string property)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(property));
        }
    }

    #endregion 

    #region INotifyPropertyChanged Members

   public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

Now I can simply data bind my XAML to the X, Y, and Answer properties, and bind a button to the Click command. The button will even disable itself while the client is waiting on the server to return the answer. As you can see, the implementation is very straightforward and I don't have to worry about how the call happens. In fact, using this type of abstraction, I could easily wire in a mock class to satisfy the service for testing like this... or maybe decide that a web service for multiplication is overkill and just satisy the contract locally:


public class MockCalculator : ICalculator 
{
   public void Multiply(int x, int y, Action<long> result) 
   {
      result(x*y);
   }
}

While the Action command is really a different way of expressing a delegate, it also makes the intent of the code clear and allows for a clean separation of mechanism from result when dealing with asynchronous calls.

Jeremy Likness

Tuesday, December 8, 2009

MVVM Composition in Silverlight 3 with Prism

This post explores how to manage multiple view models across modules in a Prism-based Silverlight application.

One powerful feature of Prism is the ability to dynamically load modules. This allows reduction of the XAP file size, as well as encourages a smaller memory footprint as certain modules are not brought into the application until they are needed. A common issue I find developers struggle with is the consistent use of view models. I've seen some elegant solutions that involve storing values in isolated storage to move the values between modules (elegant, but overkill) when in fact a common view model shared between modules would have been fine.

I'm going to assume you are familiar with Prism and know how to build an application that dynamically loads modules as they are accessed. You may want to refer to my article Dynamic Module Loading with Silverlight Navigation if you need more background information.

Assume you have a project that is dynamically loading modules and injecting them into the shell. For my example, I'm going to assume the application does not require deep linking, so it is not based on the navigation framework (it could be fit easily). In order to facilitate my own navigation, I create a navigation service. The navigation service is a singleton and has the module manager injected to it. It contains an enumeration of controls to display, and a "module map" that maps the control to the module the control lives in. It also exposes a "view changed" event that it fires with the enumeration whenever a new view is navigated to.

The logic is quite simple (in this example, my enumeration is passed in as view, and the value of the enumeration maps nicely to the index of an array of modules that host views). MODULEINIT is just a shell based on the module naming convention, for example "MyApp.Module{0}.ModuleInitializer" or similar.

The module manager is injected in the constructor. Each time we navigate to a view, we call this so the module can be loaded if it hasn't been already. Prism keeps track of loaded modules and won't try to pull the XAP across the wire more than once.


_moduleManager.LoadModule(string.Format(MODULEINIT,_moduleMap[(int)view]));
            
EventHandler<ViewChangedEventArgs> handler = ViewChanged;
            
if (handler != null)
{
   ViewChangedEventArgs args = new ViewChangedEventArgs(_currentView, view);
   handler(this, args); 
}

As you can see, very straightforward. We remember the current view and send that with the new view to the event. The views themselves can register to the event. If the views are built with a VisualStateGroup to handle swapping them into and out of view, then the logic is simply: if I am the old view, go to my hidden state, else if I am the new view, go to my visible state. Then the views can live in an ItemsControl with only one view showing at a time.

For my views, I create a ViewBase class that is, in turn, based on UserControl. This lets me manage some common housekeeping for the views that will be bound to view models. First, I exposed a protected method called _ViewBaseInitialize to call after the component is initialized. This takes in the view model and binds it, as well as wires into the navigation change event. I know some people won't like injecting the view model and there are certainly other ways to marry the view and its model, but for our example this will do.

Our logic looks simply like:


protected void _ViewBaseInitialize(object viewModel)
{
   Loaded += (o, e) =>
      {
         MasterModel model = DataContext as MasterModel;
         model.Navigation.ViewChanged += new EventHandler<ViewChangedEventArgs>(nm_ViewChanged);
                
         if (viewModel != null)
         {
            model.ModuleViewModel = viewModel;
         }
      };

      if (currentView.Equals(e.OldView))
      {
         VisualStateManager.GoToState(this, "HideState", true); 
      }
      else if (page.Equals(e.NewView))
      {
         VisualStateManager.GoToState(this, "ShowState", true);
      }
}

You'll note the introduction of the MasterModel. This view model is bound at the shell level, so it is available to all of the views hosted in that shell. Typically, a shell as a Grid or similar item as the root layout panel, so in my bootstrapper I handle wiring up the master view model:

protected override DependencyObject CreateShell()
{
    Container.RegisterType<NavigationManager>(new ContainerControlledLifetimeManager());
    NavigationManager nm = Container.Resolve<NavigationManager>();
  
    Container.RegisterType<MasterModel>(new ContainerControlledLifetimeManager());           
               
    Shell shell = Container.Resolve<Shell>();
    Application.Current.RootVisual = shell;
    
    nm.NavigateToView(NavigationManager.NavigationPage.Login);
    
    return shell; 
}

Because the constructor of the master model takes in a "navigation manager" instance, it receives the instance we just configured. Likewise, the shell will receive the instance of the view model and bind that to the data context of its main grid.

For all practical purposes, the MasterModel definition looks like this:


public class MasterModel : IViewModel
{
   public NavigationManger Navigation { get; set; }

   public MasterModel(NavigationManager nm)
   {
      Navigation = nm;
   }

   public IViewModel SubModel { get; set; }
}

You can see that it takes the navigation manager as well as a sub model where needed. This is key: it doesn't have knowledge about the modules it will be interacting with, so it only knows about the IViewModel. We'll get more specific in a bit. The master module can hold things like settings, static lists, authentication, etc, to pass down to sub modules as needed.

Now let's get down to an actual module that will use this. Let's say I have a module called ModuleUserManager and it has a view model called UserManagerModel. It needs a token for security that is stored in the master module.

First, let's extend the ViewBase to make it easier to grab a model. We can't type the view base because we are basing our controls on UserControl, which isn't typed. We can, however, type methods. I added this method as a simple helper:


protected T _GetViewModel<T>() where T: IViewModel 
{
    MasterModel model = DataContext as MasterModel;
    return model == null ? null : (typeof(T).Equals(typeof(MasterModel)) ? model as T : model.ModuleViewModel as T); 
}

Remember, we bound the master to the shell, so the hierarchical nature of data-binding means the data context will continue to be that until I override it. We'll override it in our view, but at this level we still see the master model. The method simply casts the data context and then either returns it the master model is being requested, or access the ModuleViewModel property and returns that (also typed). This was set earlier in the call to the _ViewBaseInitialize.

Now my view can be based on ViewBase. Simply add a user control, go into the XAML, reference the namespace for the view base and then switch from UserControl to ViewBase. The XAML will look like this:


<vw:ViewBase x:Class="MyApp.ModuleUserManager.Views.UserView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:cal="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation"  
    xmlns:vw="clr-namespace:MyApp.Common.Base;assembly=MyApp.Common"
    >
    <Grid DataContext="{Binding ModuleViewModel}"/>
</vw:ViewBase>

In this example, we've taken the user control and exposed it as a ViewBase because the partial class must have the same base in both XAML and code behind. I've also bound the grid to the "module view model" so it has access to the local view model. In the code behind, we pass the module-specific view model to the initializer:


public partial class UserView : ViewBase
{
    public UserView()
    {
        InitializeComponent();
        _ViewBaseInitialize(new UserManagerModel());
    } 
}

Note that the master model is going to be shared. Even though I dynamically loaded the module and the view with Prism, the data context for the control itself remains bound to the "master" (shell) and therefore can reference all of the properties I've set in previous screens. My new, local view model gets bound as a property to this master view so the local properties can be accessed in the XAML. What if I have a property called Token in my master that I need to reference in my local view model? I can simply add a hook into the loaded event (so I'm sure all of the binds, etc have taken place) and then use my new helper method. I'll add this after the _ViewBaseInitialize call:


        Loaded += (o, e) =>
            {
                MasterModel master = _GetViewModel<MasterModel>();
                UserManagerModel userModel = _GetViewModel<UserManagerModel>();
                userModel.Token = master.Token; 
            };


That's it. Obviously there are more elegant ways to bind the view models together other than the code-behind, but I tend not to be the fanatic purist some others might be when it comes to simple actions and tasks that coordinate views and view models. If that task has "awareness" of an event triggered in the view and the view model, I don't see the issue with tapping into that action to glue things together.

The final thought I'll leave you with is the possibility of the sub modules being a stack. In this scenario, each view would push the view model onto the stack. Then, if you clicked the back button, the previous view could pop its view from the stack and restore the state it was in. This way the master model would help coordinate undo/redo functionality without having knowledge the specific models it collects.

Jeremy Likness

Oh wait, even better...

After posting this, I realized there was even a better way to class the base view. If I do this:


protected void _ViewBaseInitialize<T>(Action<MasterModel,T> onLoaded) where T: IViewModel, new()
{
    // must fire when loaded, as this is when it will be in the region
    // and ready to inherit the view model
    Loaded += (o, e) =>
    {
        MasterModel model = DataContext as MasterModel;
        model.Navigation.ViewChanged += new EventHandler<ViewChangedEventArgs>(nm_ViewChanged);
        
        if (typeof(T) != typeof(MasterModel))
        {
            model.ModuleViewModel = new T();
        }

        if (onLoaded != null)
        {
            onLoaded(model, model.ModuleViewModel as T);
        }
    };
}

Then I simply can simply change my derived view to this:


public UserView()
{
    InitializeComponent();
    _ViewBaseInitialize<UserManagerModel>((masterModel, userModel) =>
        {
            userModel.Token = masterModel.Token;
        });           
}

Even better - now I just call the base method with the type I want and let it new it up, then get a strongly typed delegate to move my data when needed.

Saturday, December 5, 2009

Host WCF as Windows Service without Installing

I am working on a project that involves a centralized UI that then coordinates with agents to send out instructions. The agents will be WCF endpoints and to ease deployment/minimize the install footprint, they will install as windows services with a nice installer rather than hanging onto an IIS webspace directly.

In this post I want to walk you through the process of creating that WCF host programmatically, as well as a small little tweak that will allow you to run and test without having to install the service. It's actually quite easy to do but it's one of those things that can produce an "ah-hah!" moment if you haven't done it before.

To start with, let's create a simple service and operation contract. Create a new interface, call it IHelloWorldService, and add a method, like this:


[ServiceContract(Namespace="http://wintellect.com/sample")]
public interface IHelloWorldService
{
    [OperationContract]
    [FaultContract(typeof(Exception))]
    string Hi();
}

You'll have to add references and usings for System.ServiceModel.

Next, implement the interface:


public class HelloWorldService : IHelloWorldService
{
    const string REPLY = "Hello, world."; 

    public string Hi()
    {
        return REPLY; 
    }

}

That's all it takes to make your WCF service. Now we just need a way to host it. Add another reference to System.ServiceProcess. Create a new class called HelloServiceHost and derive it from ServiceBase. Now we'll get a little interesting:


public class HelloServiceHost : ServiceBase
{
    const string CONSOLE = "console";

    public const string NAME = "HelloWorldService"; 

    ServiceHost _serviceHost = null;

    public HelloServiceHost()
    {
        ServiceName = NAME; 
    }

    public static void Main(string[] args)
    {
        if (args.Length == 1 && args[0].Equals(CONSOLE))
        {
            new HelloServiceHost().ConsoleRun();
        }
        else
        {
            ServiceBase.Run(new HelloServiceHost());
        }
    }

    private void ConsoleRun()
    {
        Console.WriteLine(string.Format("{0}::starting...",GetType().FullName));

        OnStart(null);

        Console.WriteLine(string.Format("{0}::ready (ENTER to exit)", GetType().FullName));
        Console.ReadLine();

        OnStop();

        Console.WriteLine(string.Format("{0}::stopped", GetType().FullName));
    }

    protected override void OnStart(string[] args)
    {
        if (_serviceHost != null)
        {
            _serviceHost.Close();
        }

        _serviceHost = new ServiceHost(typeof(HelloWorldService));
        _serviceHost.Open();
    }

    protected override void OnStop()
    {
        if (_serviceHost != null)
        {
            _serviceHost.Close();
            _serviceHost = null;
        }
    }
}

Let's break it down. We're derived from service base, and need a service host to actually present the WCF end point. In the constructor, we set the service name. In the Main class, which is called for both console applications and service applications, we check the arguments. If you pass in "console" as an argument, it will create a new instance and run it directly. Otherwise, it calls into the ServiceBase to run as a Windows service.

The ConsoleRun is stubbed out to give you a nice message that it is starting, then manually call the start event and wait for a line to be entered. When you hit ENTER, it will close the service and shut down. This is what enables us to take the generated executable, and call it, like:
HelloWorldService.exe console
and then debug interactively without having to install it as an actual service.

The OnStart and OnStop overrides do basic housekeeping for registering the types of the endpoints that will be active (this one process could host several endpoints, if you so desired) and shutting down when finished.

Of course, you'll need to add an app.config file and come up with your end point name. It can run on existing IIS ports, but must have a unique URL. I set mine up like this:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="HelloWorldService.HelloWorldService" behaviorConfiguration="HelloWorldServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:80/helloworld"/>
          </baseAddresses>
        </host>
        <endpoint address=""
                  binding="wsHttpBinding"
                  contract="HelloWorldService.IHelloWorldService"/>
        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="HelloWorldServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="False"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Once this is in place, you should be able to compile, browse to the directory it is in, and run the program with the "console" argument (no dashes or anything special). Once it is waiting for a keypress, go to a web browser and navigate to http://localhost/helloworld?wsdl and you should see the WSDL for your service. At this point you could hook it up to a test harness, use SoapUI, or about any other method for testing and start doing things with the service.

Of course, eventually the goal is to allow it to be installed as a Windows service. For that, add a reference to System.Configuration.Install. Add a new class and call it ProjectInstaller. Derive the class from Installer. The class will look like this:


[RunInstaller(true)]
public class ProjectInstaller : Installer
{
    const string DESCRIPTION = "Hello world service host.";
    const string DISPLAY_NAME = "Hello World Service";

    private ServiceProcessInstaller _process;
    
    private ServiceInstaller _service;

    public ProjectInstaller()
    {
        _process = new ServiceProcessInstaller();
        _process.Account = ServiceAccount.LocalSystem;
        _service = new ServiceInstaller();
        _service.ServiceName = HelloWorldService.NAME;
        _service.Description = DESCRIPTION;
        _service.DisplayName = DISPLAY_NAME; 
        Installers.Add(_process);
        Installers.Add(_service);
    }
}

Now you can navigate to the command line and use installutil.exe to install it as a bona fide Windows service.

I'm not including a demo project because this should be fairly straightforward and I've included 100% of the code in this post ... I bet you might not have known hosting a WCF service outside of an actual web project was so simple!

Jeremy Likness

Wednesday, December 2, 2009

Silverlight MEF: Custom ExportProvider for Attached XAML Exports

I've been enjoying learning more about the Managed Extensibility Framework (MEF) and exploring various ways to integrate it with applications. After toying with MEF on Silverlight for awhile, I began to wonder about using it to export/import UI pieces or even define data elements in XAML. After a tweet to @gblock confirmed there was not native support, I set out to see what I could do. (If you're not familiar with MEF, take a look at my 10 minute walkthrough.)

The result is by no means ideal and is certainly a contrived "proof of concept" solution, but I believe it will help expose some of the custom extension points available with MEF and just how flexible it truly can be.

Download the Source

My goal was to minimize code behind for a common scenario of having pages with groups of widgets. Widgets will most likely be defined as user controls, but we've already seen plenty of examples there. I wanted to be able to define them as resources in pure XAML, no code behind, then import them into something like a StackPanel as child elements.

The Attachable View Model

The first thing I created was an attachable view model. It would get a list of FrameworkElement for binding to a control. To make it even more interesting, I wired in an attached property. This way I can simply attach the view model to a control and it will automatically pull in the parts and populate the children.

The initial shell looked like this:


public class ViewModel
{
    private static List<FrameworkElement> _uiParts = new List<FrameworkElement>();
    
    [ImportMany("UIPart", AllowRecomposition = true)]
    public List<FrameworkElement> UIParts
    {
        get { return ViewModel._uiParts; }
        set { ViewModel._uiParts = value; }
    }

    public ViewModel()
    {
        var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);
    }

    static ViewModel()
    {
        new ViewModel();
    }

    public static readonly DependencyProperty ViewBinderProperty = DependencyProperty.RegisterAttached(
        "ViewBinder", typeof(bool), typeof(ViewModel), new PropertyMetadata(new PropertyChangedCallback(OnViewBound)));

    public static void OnViewBound(object sender, DependencyPropertyChangedEventArgs args)
    {
        // make sure we want this ...
        if (args.NewValue != null && args.NewValue.GetType().Equals(typeof(bool)) && (bool)args.NewValue)
        {
            Panel panel = sender as Panel;
            if (panel != null)
            {
                // iterate the parts
                foreach (FrameworkElement element in _uiParts)
                {
                    // clone it
                    FrameworkElement newElement = Clone(element);
                    
                    // give it a unique name
                    newElement.SetValue(FrameworkElement.NameProperty, Guid.NewGuid().ToString());
                    
                    // inject it
                    panel.Children.Add(Clone(newElement));
                }
            }
        }
    }

    public static bool GetViewBinder(DependencyObject obj)
    {
        return (bool)obj.GetValue(ViewBinderProperty);
    }

    public static void SetViewBinder(DependencyObject obj, bool value)
    {
        obj.SetValue(ViewBinderProperty, value);
    }
}

So far it feels pretty much like a standard class hosting a dependency property. You'll notice it's a bit strange, however, as the class itself is not static. This is because MEF is expecting an instance to compose the parts in. To facilitate that, I have an instance constructor that follows the general MEF pattern ... throw the catalog into the container and compose the parts. The "instance" getter and setter is really a facade that populates the static list of parts, in this case I'm just asking for any type of FrameworkElement. Obviously, those will have to come from somewhere else.

Because my intention is to use a resource dictionary, I must be able to share the elements. Silverlight won't let you take an element that is already the child of another element and then move it somewhere else. I have to assume I may reuse some of these elements as well (for example, this could be extended with a filter to choose the types of elements). So, instead of adding the elements directly to the parent, I am cloning them.

Thanks here goes to Justin Angel for his very functional clone method that I found here. I left it out of the code snippet above to keep it simple, but it is included in the source.

Now we need to tackle the task of exporting the framework elements. Ideally, I just want to put them into a resource dictionary, tag them somehow, and have the magic work. Fortunately, MEF gives us a nice ExportProvider we can derive from to do just that. There's an excellent article I started with by the "Code Junkie" you can access here.

It may have made more sense to split out the dependency properties and the provider to separate classes, but I figured, why not? So here is a custom export provider that also hosts some attached properties to facilitate exporting XAML:


public class XAMLProvider : ExportProvider
{
    private static readonly Dictionary<ExportDefinition, List<Export>> _exports = new Dictionary<ExportDefinition, List<Export>>();

    private static readonly XAMLProvider _provider = new XAMLProvider();

    public static DependencyProperty MEFExportProperty = DependencyProperty.RegisterAttached("MEFExport", typeof(string), typeof(XAMLProvider),
        new PropertyMetadata(new PropertyChangedCallback(OnMEFExport)));

    public static void OnMEFExport(object sender, DependencyPropertyChangedEventArgs args)
    {
        if (args.NewValue != null && !string.IsNullOrEmpty(args.NewValue.ToString()))
        {
            string contract = args.NewValue.ToString();
            _provider.AddExport(contract, sender);
        }
    }

    public static string GetMEFExport(DependencyObject obj)
    {
        return (obj).GetValue(MEFExportProperty).ToString();
    }

    public static void SetMEFExport(DependencyObject obj, string value)
    {
        obj.SetValue(MEFExportProperty, value); 
    }

    private static readonly object _sync = new object();

    public static XAMLProvider GetXAMLExportProvider()
    {
        return _provider;
    }

    public void AddExport(string contractName, object export)
    {
        lock (_sync)
        {
            var found =
                from e in _exports
                where string.Compare(e.Key.ContractName, contractName, StringComparison.OrdinalIgnoreCase) == 0
                select e;

            if (found.Count() == 0)
            {
                ExportDefinition definition =
                    new ExportDefinition(contractName, new Dictionary());

                _exports.Add(definition, new List<Export>());
            }

            Export wrapper =
                new Export(contractName, () => export);

            found.First().Value.Add(wrapper);
        }
    }

    protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
    {
        var contractDefinition = definition as ContractBasedImportDefinition;
        IEnumerable<Export> retVal = Enumerable.Empty<Export>();

        if (contractDefinition != null)
        {
            string contractName =
                contractDefinition.ContractName;

            if (!string.IsNullOrEmpty(contractName))
            {
                var exports =
                    from e in _exports
                    where string.Compare(e.Key.ContractName, contractName, StringComparison.OrdinalIgnoreCase) == 0
                    select e.Value;

                if (exports.Count() > 0)
                {
                    retVal = exports.First();
                }
            }
        }

        return retVal; 
    }
}

The only override provided is to actually get the exports for a provided input definition. Everything else is left to us.

The first thing I did was create a dictionary. The key is the contract name (in MEF, the contract name is just a string ... if you use a type or an interface, then the fully qualified name becomes the string for the contract). The value is a list of all exports attached to that contract.

The dependency property allows me to attach "MEFExport" to any XAML object and give it a contract name. When this property is attached, it will look for the name in the dictionary and then either create a new entry or add the element to the existing list. It's as simple as that!

When the GetExportsCore is called, we are given an import definition. For a more complex example, we could look at attributes and other extensions. In this case, I'm simply extracting the contract name, finding the key in the dictionary and then sending off any exports that were loaded with the key.

Now I can add a resource dictionary and tag my elements for export. Mine looks like this:


<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MEFExtension">
    <TextBlock FontSize="32" Text="This is a text block." x:Key="ui1" local:XAMLProvider.MEFExport="UIPart"/>
    <Rectangle Width="100" Height="100" Fill="Red" x:Key="ui2" local:XAMLProvider.MEFExport="UIPart"/>
    <TextBlock FontSize="16" Text="This won't get imported." x:Key="ui3"/>
    <Ellipse HorizontalAlignment="Left" Fill="Blue" Stroke="Black" Width="100" Height="50" x:Key="ui4" local:XAMLProvider.MEFExport="UIPart"/>
</ResourceDictionary> 

I threw in a dummy text block without tagging it to show that it won't get exported because the property is not attached. So now when that resource dictionary is pulled in, we can parse the XAML and export the elements. We need to let MEF know about our custom provider. Going back to my view model, I'll change the container creation to this:


var container = new CompositionContainer(catalog, XAMLProvider.GetXAMLExportProvider());
            

Notice I now passed in our custom export provider.

Now all of the elements are in place. The custom export provider knows how to scan XAML and load up elements for export, we've added a resource dictionary with some elements to export, and the view model is asking for imports and has its own attached property so that we can push the elements to any type of panel.

Last step: I go into my main page, pull in the resource dictionary and bind the view model:


<UserControl x:Class="MEFExtension.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"
    xmlns:local="clr-namespace:MEFExtension">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Resources.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <StackPanel Orientation="Vertical" Width="Auto" local:ViewModel.ViewBinder="true"/>
</UserControl>

So the resource dictionary will get pulled in. As the keys are processed, it will fire the attached properties and load them into exports. I gave them the "UIPart" contract. When the view model is attached, it will new an instance that fires the composition container for MEF. This will use the custom provider. Because we have the list of elements marked "UIPart", the exports will match and get loaded. The attach event will clone these objects and add them as children to the stack panel.

The result?

Silverlight MEF ExportProvider

There you have it, an example of extending the, ah, Managed Extensibility Framework, to support exporting using attached properties in XAML (I did this in Silverlight 3, so I had to add the reference to the System.ComponentModel.Composition from the download ... it is included in Silverlight 4).

Download the Source

Jeremy Likness