WPF app with Ninject
Asked Answered
L

2

6

I'm lost with Ninject in WPF.

I'm initializing it in App.xaml but the ITest property in MainWindow.xaml (even with the InjectAttribute) is not getting resolved and remains null.

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {    
        IKernel kernel = new StandardKernel();
        kernel.Bind<ITest, Test>();
        base.OnStartup(e);
    }
}

I googled a bit and found out that it doesn't work that way. In trying to find a solution, I ended up with creating IMainWindow with nothing else but "void Show();" and adding it to the MainWindow.

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {    
        IKernel kernel = new StandardKernel();
        kernel.Bind<ITest, Test>();

        kernel.Bind<IMainWindow, MySolution.MainWindow>();
        kernel.Get<IMainWindow>().Show();

        base.OnStartup(e);
    }
}

For this, I'm getting a NullReferenceException on the line with .Get

I also tried this:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {    
        IKernel kernel = new StandardKernel();
        kernel.Bind<ITest, Test>();

        MainWindow = new MySolution.MainWindow(kernel);
        //then kernel.Inject(this); in the MainWindow constructor 
        MainWindow.Show();

        base.OnStartup(e);
    }
}

Now I'm getting a NullReferenceException at the .Inject line in the MainWindow.

I found another various solutions but they seemed heavyweight and I gave up testing all of them and trying which one works.

Any help please?

Lozengy answered 17/11, 2012 at 15:49 Comment(1)
What exactly is your NullReferenceException is?Vertigo
S
6

You are not registering your types correctly that is why the second example throws an execption. The correct syntax is: kernel.Bind<SomeInterface>().To<SomeImplementation>()

So the correct usage:

protected override void OnStartup(StartupEventArgs e)
{
    IKernel kernel = new StandardKernel();
    kernel.Bind<ITest>().To<Test>();

    kernel.Bind<IMainWindow>().To<MainWindow>();
    var mainWindow = kernel.Get<IMainWindow>();
    mainWindow.Show();

    base.OnStartup(e);
}

And you need to mark your property with the [Inject] attribute:

public partial class MainWindow : Window, IMainWindow
{
    public MainWindow()
    {
        InitializeComponent();
    }

    [Inject]
    public ITest Test { get; set; }
}

public interface IMainWindow
{
    void Show();
}
Semiprofessional answered 17/11, 2012 at 16:22 Comment(4)
Huh, I thought Bind<T1, T2>() is the same as Bind<T1>().To<T2>(). Evidently not. Thanks!Lozengy
No with Bind<T1, T2>() you can bind two interfaces to one implementation but you still need to provide the implementation with .To<>.Semiprofessional
I know this is old but when I do this, I get two Main Windows showing, as opposed to one. Any thoughts?Erg
@Erg Have you removed the StartupUri="MainWindow.xaml" from your app.xaml?Semiprofessional
A
0

I'm sure you got a solution, but you can use constructor injection instead of property injection on MainWindow, if you want.

This avoids creating a Dummy interface IMainWindow and creating a unnecessary public property for all your injected classes.

Here's the solution:

MainWindow.cs

public partial class MainWindow : Window, IMainWindow
{
    private readonly ITest test;

    public MainWindow(ITest test)
    {
        this.test = test;
        InitializeComponent();
    }

}

App.xaml.cs:

protected override void OnStartup(StartupEventArgs e)
{
    IKernel kernel = new StandardKernel();
    kernel.Bind<ITest>().To<Test>();

    var mainWindow = kernel.Get<MainWindow>();
    mainWindow.Show();

    base.OnStartup(e);
}
Axial answered 25/11, 2013 at 15:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.