MVVM Light, Ninject in a mostly notification area application

[亡魂溺海] 提交于 2019-12-04 18:50:58

...At this point a heartbeatManager instance is created just left to hang in the memory...

If it is registered with your kernel, it isn't any magic that causes it to hang in memory - it will stick around as long as the kernel/container does. That container should probably be a member of your App class, since your app class sticks around as long as the (compiler generated) Main method does, and you should dispose it on app shutdown anyhow.

...Following the MVVM Light ViewModelLocator pattern the MainWindow tries to resolve it's data context from the static ViewModelLocator instance defined in App.xaml...

I'm not sure this will mix well with NInject. It is a Dependency Injection container, not a Service Locator container (even though it uses one under the hood). The main purpose of NInject (and similar frameworks) is to avoid requiring you to use the Service Locator pattern, and instead to inject all your dependencies.

...ViewModelLocator instance is created and in the constructor it initializes another StandardKernel...

Unless your scenario is quite complicated (which it really isn't for this app), then I suggest sticking to a single NInject kernel.

Suggested Solution

The view model locator class itself doesn't do much for you other than let you split up your initialization logic, and do selective initialization depending on whether you're in design mode or runtime mode. You could achieve the same with NInject modules (which the view model locator article you linked in comments already uses).

I suggest that instead of using a view model locator, you specify all your components in your module class, and do the IsInDesignMode logic in the Load method.

This might be a bit tricky with MVVM though, since the view model needs to bind to an object property you didn't create, and can't annotate.

There are a few ways to solve this directly in NInject, instead of resorting to a service locator:

  • Use Dependency Injection on your view, making it require a view model.
    If this doesn't work using constructor injection (as you mentioned in your comments), use property injection instead, with a custom property that forwards its setter to DataContext.
  • Use NInject factory methods (ToMethod) to create your view, and bind the view model to the view in each factory method.
    E.g. Bind<MainView>().ToMethod(context => new MainView() { DataContext = new MainViewModel() });

If you can, I'd go for the second method. This way your view doesn't have to handle data binding, and doesn't have to have any code behind. It is also simple to understand, would let you avoid having to register both views and view models in the kernel, and would let you avoid making any sort of well known interface for your view model.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!