MVVM

Dependency Injection, MVVM, Ninject and Silverlight

Intro

The MVVM patterns is pretty popular these days. In Silverlight and WPF it is used a lot. Dependency Injection is also used very often. In this tutorials I would like to show you how to use Dependency Injection when building a Silverlight application using the MVVM pattern.

There are numerous Dependency Injection Frameworks. For this tutorial I’ve chosen Ninject. The main idea on how to implement DI in your application is pretty much the same for all frameworks. In this tutorial I hope I can give you a small introduction in using Ninject in you projects.

Ninject is an open source project which can be found at www.ninject.org. Ninject is also available through the NuGet tool in Visual Studio. Have look at my NuGet tutorial on how to get it through that.

Demo project

The demo project is a very simple game. The objective of the game is to guess a number. There will be a web service that can be requested to provide a random number. The game consists of three screens or Views. The first, StartView, asks the player for the maximum number. The second screen, GameView, ask the player to guess a number between 0 and the maximum number given on the first screen. The last screen, ResultView, shows whether the guess number equals the randomly chosen number and provides the user with two options, try again or restart. These views are displayed inside a fourth view, ShellView, that handles the navigation.

Each view contains one or more commands and one or more properties to handle interaction with the user. The views contain only the most basic controls to interact. On the StartView there’s a textbox to set the maximum number to guess for and a button to start playing. The GameView contains a textbox to get the guess from the user and a button that triggers navigation to the ResultView. The ResultView contains a styled checkbox to show if the guess was correct and two buttons. One to navigate to the GameView, to try guessing again, and one to navigate to the StartView, to start the game all over.

The generation of a random number takes place on the server. A proxy class is placed between the calls to the service and the caller of the methods. This implementation of the custom IProxyService interface will be replaced when unit testing to be able to use a dummy implementation.

The navigation works by calling a method on shared class between the viewmodels.The INavigator interface contains the method. It also contains an event the ShellViewModel is listening to. Calling the method would fire the event and causes the ShellViewModel to update the visible view.

Setup the IOC

Ninject uses a Kernel to setup the Inversion of Control, or IOC, container. The IOC container is filled with classes and interfaces that go together. We the program asks the Kernel for a specific type, this will be returned by the container. By default you can instantiate the StandardKernel class. The constructor of the StandardKernel class takes a NinjectModule as a parameter.

To separate the construction of the Module and the construction of the Kernel, the NumberGameModule class is created. The class inherits from the NinjectModule class. It has to implement the abstract Load method.

private IKernel Kernel;
...
Kernel =
    new StandardKernel(new NumberGameModule());

The binding of classes together for the IOC container happens in the Load method of the NumberGameModule class. The method is called automatically when the Kernel is created.

public class NumberGameModule : NinjectModule
{
    public override void Load()
    {
        //todo: Inititialize the IOC.
    }
}

Often an interface is bound to a class that implements that interface. This way alternative uses of that interface can be used if needed, when Unit Testing for example. The binding uses a fluent syntax and looks like this:

this.Bind<IServiceProxy>().To<ServiceProxy>();

This literally Binds the IServiceProxy interface To the ServiceProxy class. This means that every time you need a ServiceProxy you call the Get method on the kernel, like this:

kernel.Get<IServiceProxy>();

In this case the kernel instantiates a new ServiceProxy for you. If, in case of testing for example, you bind a TestServiceProxy to the IServiceProxy interface. The TestServiceProxy will be returned, without changing the call to the Get method. In the next section you will see the true power of this.

Sometimes you don’t want to use an interface for a class. You just want to have an instance when asking for it. In situations like this you can bind a class to itself. The syntax for this is straight forward again:

this.Bind<GameViewModel>().ToSelf();

This sounds pretty useless, but to get all the nice features of dependency injection you’ll have to let the framework instantiate your classes, and never use the new keyword.

Lifetime

One of these features is using singletons. There a lot’s of reasons not to use the singleton pattern, they are hell to unit test for example. When using dependency injection you can have the framework manage the singletons. Which means that every time you ask the kernel to give you a specific type, you always get the same instance. But, in case of unit testing you can have it return a new instance every time. Without any changes to the code under test. For example, say you want to bind the INavigator interface to the Navigator class using a Singleton scope:

this.Bind<INavigator>().To<Navigator>()
    .InSingletonScope();

Without specifying a scope the InTransientScope() variation is used. If you need it, you can also have Ninject instantiate a new instance once every thread by using the InThreadScope() method.

Context

Often you find the need to use different implementations of classes in different contexts. For example, when using Expression Blend to create your views. You don’t want to call web services and do complex calculations, but only a simple implementation to work with. You can have Ninject create different instances based on the context. In this example the normal implementation is created in Singleton scope. When using this class in a designer, like Blend, a new instance is created on every call. A delegate method is used. The method should return a boolean. In the example below a lambda is used to shorten the syntax.

bool designContext =
    DesignerProperties.GetIsInDesignMode(
        App.Current.RootVisual);

this.Bind<IGame>()
    .To<Game>()
    .When(x => !designContext)
    .InSingletonScope();

this.Bind<IGame>()
    .To<AlternativeGame>()
    .When(x => designContext);

 

Constructor Injection

When having Ninject instantiate your classes Ninject automatically resolves the parameters of the constructor. This means that if your constructor takes two interfaces and Ninject knows how to resolve these, the implementation of the interfaces is injected into the constructor. For example, the constructor of the ResultViewModel takes two parameters. The IGame interface and the INavigator interface. Both these interfaces are known to Ninject and therefore can be resolved when a ResultViewModel is created.

public ResultViewModel(IGame game,
                       INavigator navigator)
{
...
}

Without using Dependency Injection you probably would new a game and a navigator inside the constructor, and thus create a dependency on these classes. When using injection you only have a dependency on an interface, and can use different implementations when needed. Which makes testing a lot easier.

There are occasions however where you want to have control over which constructor is used for injection. Ninject looks for the constructor that takes the most known parameters and tries to use that when resolving the class. If it can’t find any it will use the default parameterless constructor.  You can mark a constructor with the Inject attribute to force Ninject to use that one when resolving. Marking multiple constructors with the attribute will result in an exception. 

Binding the VM to the V

The last step would be to glue it all together. The kernel must be build and filled somewhere, and the viewmodels must be bound to the Views somehow. To do all this one could use the View Model Locator pattern. The ViewModelLocator class contains properties that represent the viewmodels used. The class has a static constructor so it can be constructed in Xaml. By doing this the ViewModelLocator can be defined a resource and be used throughout the application. The implementation of the constructor is described earlier. Only a null-check is added. The ViewModelLocator looks like this:

public class ViewModelLocator
{
    public ShellViewModel ShellViewModel
    {
        get {
            return Kernel.Get<ShellViewModel>();
        }
    }

    // other ViewModels are defined
    // the same way.

    private static readonly IKernel Kernel;

    static ViewModelLocator()
    {
        if (Kernel == null)
        {
            Kernel = new StandardKernel(
                new NumberGameModule());
        }
    }
}

To get the ViewModelLocator known in Xaml you’ll have to define it as a resource. The best place to do this is directly in your App.xaml. In the Resources section define a new resource with and use a key like “ViewModelLocator”, like this:

<Application
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:Common="clr-namespace:NumberGame.Common"
  x:Class="NumberGame.App">

    <Application.Resources>
        <Common:ViewModelLocator
            x:Key="ViewModelLocator"/>
    </Application.Resources>
</Application>

When the application is started the resource is created, and the static constructor is executed. You can use the ViewModelLocator as a StaticResource now.

To get the right viewmodel in a view the DataContext of that particular view has to be bound to a property of the ViewModelLocator resource. In case of the ShellView you would like use the ShellViewModel property of the ViewModelLocator. Add a line like below to the definition of your view in xaml:

DataContext="{Binding ShellViewModel,
    Source={StaticResource ViewModelLocator}}"

All this is saying that you would like to set the path of the binding to the ShellViewModel property of the ViewModelLocator StaticResource.

 

Wrap up

There are a lot of situations where you might want to have Ninject do more than what is explained in this tutorial. Ninject can do a lot more, which is left out for the sake of simplicity. Sometimes you’ll need specific custom factory methods to create your objects or you might have separated your classes into a different assembly. Ninject can be used in situations like this too. If something isn’t supported right out of the box, Ninject is extensible and open source. 

You can find the demo project that goes with this tutorial here.

If you have any questions, suggestion or just want to leave a comment you can use the area below, feel free to send me an email or contact me through twitter. To be the first to know when there’s a new tutorial online you can also subscribe to the RSS feed.

Unit testing MVVM in Silverlight – SDN Event–Code and Slides

Yesterday I gave a talk at the SDN Event in Zeist about Unit testing MVVM in Silverlight. I talked briefly about how MVVM works in Silverlight and dove deeper into the Unit Testing Framework which is available in the Silverlight Toolkit. After going through the various attributes used in the framework I gave a demonstration on how to use StatLight, a command line tool for running tests.

I would like to thank anyone who attended my session for coming and SDN for organizing and hosting this great and informative day.

 

PivotViewer and MVVM

PivotViewer series

  1. Building your first PivotViewer application
  2. Runtime PivotViewer collection creation
  3. PivotViewer – Working with Facets
  4. Handling PivotViewer events
  5. PivotViewer – Custom actions
  6. PivotViewer and MVVM

Intro

The MVVM patterns is a commonly used pattern in Silverlight. Because of databinding MVVM suits perfectly for WPF and Silverlight. But use it only if appropriate. Often the pattern is used when it isn’t necessary. The usage of any pattern should be a helping tool, not an enforced law. Having that of my chest, lets look at the Silverlight PivotViewer control in combination with the MVVM pattern.

To make a long story short, the PivotViewer control isn’t suitable for use in MVVM out of the box. But there are a few ways you can make it work.

 

Wrapping the PivotViewer in a UserControl

The most simple way to get the control to work in an MVVM application is to place the control in a UserControl. You can use this control in your View and bind to properties you add to the UserControl. You’ll have to add dependency properties to the UserControl for each property you want to data bind to. The downside of wrapping the PivotViewer control in a UserControl is that you will have to add code to the CodeBehind of the UserControl.

 

For example a URL where the .CXML file is located. If this value changed you would like to load the collection. In the current version of the PivotViewer the only way to do this is to call the LoadCollection method on the PivotViewer control. By adding a dependency property to the UserControl you can bind a property of the ViewModel to this and have it load a collection on changes.

This dependency property  with its “OnChange” method might look something like this:

public string UrlSource{
    get { return (string)GetValue(UrlSourceProperty); }
    set { SetValue(UrlSourceProperty, value); }
}

public static readonly DependencyProperty UrlSourceProperty =
    DependencyProperty.Register("UrlSource",
                                typeof(string),
                                typeof(PivotViewerUserControl),
                                new PropertyMetadata(string.Empty,
                                                        OnUrlSourceChanged));
 
private static void OnUrlSourceChanged(DependencyObject d,
                                        DependencyPropertyChangedEventArgs e)
{
    if (!DesignerProperties.GetIsInDesignMode(d))
    {
        var userControl = (PivotViewerUserControl) d;
        userControl.Pivot.LoadCollection((string) e.NewValue,
                                             string.Empty);
    }
}

A logical next step would be to add a dependency property for the ViewerState parameter of the LoadCollection method and call it only when both are set or if the UserControl is Loaded.

To get notified when the selected item changed you can use an ICommand. Add a dependency property of type ICommand to the UserControl to be able to bind an implementation of the ICommand from the ViewModel to it. The property changed event on the PivotViewer control is handled. When the “CurrentItemId” property changes, thus the selected item changes, the event is executed. As a small extra feature the item is looked up on the PivotViewer and the whole PivotItem is passed as a parameter to the execute method.

public PivotViewerUserControl()
{
    InitializeComponent();
    Pivot.PropertyChanged += Pivot_PropertyChanged;
}

public ICommand SelectedItemChangedCommand
{
    get { return (ICommand)GetValue(SelectedItemChangedCommandProperty); }
    set { SetValue(SelectedItemChangedCommandProperty, value); }
}

public static readonly DependencyProperty SelectedItemChangedCommandProperty =
    DependencyProperty.Register("SelectedItemChangedCommand",
                                typeof(ICommand),
                                typeof(PivotViewerUserControl),
                                new PropertyMetadata(null));

private void Pivot_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "CurrentItemId")
    {
        if (this.Pivot.CurrentItemId == null)
        {
            // deselection
            this.SelectedItemChangedCommand.Execute(null);
        }
        else
        {
            // selection
            PivotItem item = Pivot.GetItem(Pivot.CurrentItemId);
            this.SelectedItemChangedCommand.Execute(item);
        }
    }
}

Extending the PivotViewer control itself

Another way to get to PivotViewer to work in an MVVM application is to extend the PivotViewer itself. The dependency properties you’ll be adding to the control are pretty much the same as the ones shown in the previous section, with the extend that you have better access to the guts of the PivotViewer control. This way you have access to the Custom Actions for example.

Where to go next

You could start by implementing all properties of the PivotViewer control as dependency properties and add a ICommands to event handlers. Maybe you can find constructions where you can extend the control with your own needs

I just hope that in the next version of the PivotViewer Microsoft did this boring work for us so we don’t have to.

I don’t have plans for a next tutorial on the PivotViewer, yet. If you have question or requests just let me know and I’ll see if I can help you. If you want to be the first to when a new tutorial is available, you can subscribe to the RSS-Feed or follow me on twitter.

Technorati Tags: ,

Share

 

MVVM Project and Item Templates

Intro

This is the first in a series of small articles about what is new in Silverlight 4 and Expression Blend 4. The series is build around a open source demo application SilverAmp which is available on http://SilverAmp.CodePlex.com.

 

MVVM Project and Item Templates

Expression Blend has got a new project template to get started with a Model-View-ViewModel project  easily. The template provides you with a View and a ViewModel bound together. It also adds the ViewModel to the SampleData of your project. It is available for both Silverlight and Wpf.

clip_image002To get going, start a new project in Expression Blend and select Silverlight DataBound Application from the Silverlight project type. In this case I named the project DemoTest1.

clip_image004

The solution now contains several folders:

  • SampleData; which contains a data to show in Blend
  • ViewModels; starts with one file, MainViewModel.cs
  • Views; containing MainView.xaml with codebehind used for binding with the MainViewModel class.
  • and your regular App.xaml and MainPage.xaml

The MainViewModel class contains a sample property and a sample method. Both the property and the method are used in the MainView control. The MainView control is a regular UserControl and is placed in the MainPage.

You can continue on building your applicaition by adding your own properties and methods to the ViewModel and adding controls to the View.

Adding Views with ViewModels is very easy too. The guys at Microsoft where nice enough to add a new Item template too: a UserControl with ViewModel. If you add this new item to the root of your solution it will add the .xaml file to the views folder and a .cs file to the ViewModels folder.

image

Conclusion

The databound Application project type is a great to get your MVVM based project started. It also functions a great source of information about how to connect it all together.

 

Twitter