How to use Ninject in WPF application

novian kristianto picture novian kristianto · Dec 16, 2013 · Viewed 15.2k times · Source

I'm familiar with MVC but I'm trying to learn WPF with Ninject. Can some one give me some example or reference?

Answer

user1548266 picture user1548266 · Dec 17, 2013

As I said in my comment to your OP, all the information you require is available within the Ninject documentation. That said it could be argued that it is easy to get lost within its vast documentation if you are unfamiliar with Ninject and/or DI.

There are a few tutorials online of which this one I thought was particularly informative. Whilst it provides an example using a console application, the principles of how Ninject works remain the same.

Irrespective of your application type you configure your container at your application entry point;

  • Console app - Main
  • WPF - App (unless you are using a framework in which case you may provide a custom bootstrapper)
  • ASP.NET - No idea, perhaps someone could enlighten me

DISCLAIMER I do not claim to be an authority on Ninject or DI, below is simply a quick example of how I understand these two objects can be used in conjunction with one another.

For example sake, let us work with the examples provided in the Ninject documentation.

1) Create a WPF application named NinjectIoC

2) Use Nuget to add a reference to the Ninject project

3) Open App.xaml and remove the StartupUri property from the Application element so that your App.xaml looks like below:

<Application x:Class="NinjectIoC.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>

    </Application.Resources>
</Application>

The reason we do this is because the StartupUri property informs the WPF application which UI control to initially display when the application starts. We are going to use Ninject to display our initial UI control.

4) Open App.xaml.cs. This is where we are going to configure the Ninject container, or Kernel to use Ninject terminology. We override the application OnStartup method so that we may configure our container and subsequently initialise the application as we would like. Update the content of your App.xaml.cs to look as follows:

namespace NinjectIoC
{
    using Ninject;
    using System.Windows;

    public partial class App
    {
        private IKernel container;

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            ConfigureContainer();
            ComposeObjects();
            Current.MainWindow.Show();
        }

        private void ConfigureContainer()
        {
            this.container = new StandardKernel();
            container.Bind<IWeapon>().To<Sword>().InTransientScope();
        }

        private void ComposeObjects()
        {
            Current.MainWindow = this.container.Get<MainWindow>();
            Current.MainWindow.Title = "DI with Ninject";
        }
    }
}

A brief explination:

4.1) OnStartup - Override theOnStartupmethod so that we may configure ourcontainer` and initialise the application as we desire.

4.2) ConfigureContainer - Inform our container of how we would like to resolve our concrete types. There is far more to this than I have displayed in this example, however, there is far more to this than I have shown. There are topics such as Multi Binding, Binding Conventions and Kernel Modules for which you are best learning about it from the official documentation.

4.3) ComposeObjects - Having removed the StartupUri property from App.xaml we must inform the application which UI control we would like it to use for the MainWindow. Alongside asking our container to use MainWindow as our MainWindow we set the Title property too. Again you might want to do other tasks here for manual object composition.

You do not have to separate out the steps as I have above, for this contrived example it would make more sense not to bother. As your application grows and you start to do more sophisticated things with the container, separating some of the stages out begins to make the container configuration more manageable. The choice is yours.

5) Next open MainWindow.xaml, then copy and paste the following:

<Window x:Class="NinjectIoC.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="78" Width="362">
    <Grid>
        <Button Content="Button" HorizontalAlignment="Left" Margin="269,10,0,0" VerticalAlignment="Top" Width="75" Click="Attack"/>
        <TextBox x:Name="Target" HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" VerticalAlignment="Top" Width="254"/>
    </Grid>
</Window>

I shall not bother explaining the above as it should be obvious what is going on.

6) Finally open MainWindow.xaml.cs and update it as follows:

namespace NinjectIoC
{
    using System.Windows;

    public partial class MainWindow
    {
        private readonly IWeapon weapon;

        public MainWindow(IWeapon weapon)
        {
            this.weapon = weapon;
            InitializeComponent();
        }

        private void Attack(object sender, RoutedEventArgs e)
        {
            this.weapon.Hit(this.Target.Text);
        }
    }

    public class Sword : IWeapon
    {
        public void Hit(string target)
        {
            MessageBox.Show(@"I swing and thrust my sword about like a mad man at " + target);
        }
    }

    public interface IWeapon
    {
        void Hit(string target);
    }
}

Again I will make this brief as what is happening above has nothing to do with the configuration of Ninject and it should once again be obvious what is happening.

The main thing to notice in the above is the argument that the MainWindow constructor expects; IWeapon. You might be asking yourself How does that get resolved as I am not creating a concrete implementation of Weapon anywhere?

Well during the ConfigureContainer method in App.xaml.cs we informed the container how we would like it to resolve dependencies for IWeapon:

container.Bind<IWeapon>().To<Sword>().InTransientScope();

The above tells the container that anywhere it encounters a dependency for IWeapon we would like it to provide an instance of Weapon. Upon requesting the container resolve (Get) our initial MainWindow control, using the following:

Current.MainWindow = this.container.Get<MainWindow>();

The container took a look at its constructors and determined the constructor with the most arguments it understood. In this example it was the constructor that required an implementation of IWeapon and oh look, the container knows how to resolve this dependency because we told it how to do so earlier in ConfigureContainer.

Assuming neither you nor I have made any mistakes with the above code, pressing F5 should launch the application and you should see a small window with a TextBox and Button. Enter something in to the TextBox then press the Button and you should see a MessageBox control informing you that you swang your sword like a "mad man" at whoever or whatever you entered in the TextBox.


There is far more to both Ninject and DI than I have described here. For example there are entire books on the subject of DI such as this one by Mark Seeman.

Hopefully the above will give you at basic starting point of where to look and where to go to progress further with your adventures with Ninject and DI.