How to use Ninject in WPF application
Asked Answered
T

1

21

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

Tiltyard answered 16/12, 2013 at 15:54 Comment(2)
i don't think this has anything to do with WPF, except in case you want to instanciate ViewModels using ninject. One of the things the first page(s) of ninject doc skip are the instanciation a Kernel: `var kernel = new StandardKernel(); kernel.Bind<IFoo>().To<Foo>(); kernel.Get<IFoo>();" <-- this is kernel instanciation, binding, and instanciating in one tiny example.Knobloch
About file placement: Which file are you talking about? The ninject library (dll)? Your source code? The ninject library is best integrated by using the Nuget package manager and your source code can be located wherever you want, provided you can access it from application (referenced as project / library).Knobloch
R
72

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.

Rigamarole answered 17/12, 2013 at 10:28 Comment(5)
@noviankristianto - I am glad to be of help. If you found my answer useful, please consider either an upvote or marking it as the answer both for myself and the community. [:Rigamarole
Good and Simple. I am using similar approach but I also need to access the container in other parts of my application. I know passing it as a parameter is not a good idea. Is there something better?Glazier
I'm sorry but this is too simplistic for me to upvote. We know that we can manually resolve a component from the kernel. The challenge in the WPF world would be to automatically resolve resources via IOC in XAML.Strigil
Uh, this was a good quality post that explained the ins and outs of the basic use. If its not useful to you, then just move on. No need for belittlement.Maclay
The recommended Ninject tutorial link above was dead. I found it on the Internet Archive Wayback Machine, here: web.archive.org/web/20150328180847/http://…Wivestad

© 2022 - 2024 — McMap. All rights reserved.