在 wpf MVVM 应用程序上使用 Unity 进行依赖注入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36631149/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 13:45:39  来源:igfitidea点击:

Dependency injection with Unity on wpf MVVM application

wpfmvvmdependency-injection

提问by Mikkel

I have been trying to set up dependency injection in a wpf application using Unity, but can't seem to fully understand how the views and viewmodels should be set up.

我一直在尝试使用 Unity 在 wpf 应用程序中设置依赖注入,但似乎无法完全理解应如何设置视图和视图模型。

Have looked into another SO post --> Wpf Unitybut can't seem to understand it quite yet. I have used Unity before, but just in a MVC application, so I know how to inject it in the contructors.

已经查看了另一篇 SO post --> Wpf Unity但似乎还不太理解它。我之前使用过 Unity,但只是在 MVC 应用程序中使用过,所以我知道如何将它注入到构造函数中。

Here is my views and viewModels in the application.

这是我在应用程序中的视图和视图模型。

Views:

意见:

MainWindow.xaml
BookingView.xaml
ContactDetailsView.xaml
ReservationsView.xaml

ViewModels:

视图模型:

MenuViewModel (MainWindow uses this viewModel)
BookingViewModel
ContactViewModel
ReservationsViewModel

My ViewModels all have Interfaces implemented, like IMenuViewModel, should the view also have an interface?

我的 ViewModel 都实现了接口,比如 IMenuViewModel,视图也应该有接口吗?

I guess that since the MainWindow is the starting point, it should be here to register the container right?

我想既然 MainWindow 是起点,那么它应该在这里注册容器吧?

Update:

更新:

Have found something, but not sure if I have done it right. Here is what I have done so far!

找到了一些东西,但不确定我是否做得对。这是我到目前为止所做的!

1: Using startup method in app.cs

1:使用app.cs中的启动方式

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        IUnityContainer container = new UnityContainer();

        container.RegisterType<IViewMainWindowViewModel, MainWindow>();
        container.RegisterType<IViewMainWindowViewModel, MenuViewModel>();

        var mainWindow = container.Resolve<MainWindow>(); // Creating Main window
        mainWindow.Show();
    }

}

2: Remove uri from start up.

2:从启动中删除uri。

3: Make IViewMainWindowViewModel interface in MainWindow class, the interface is empty.

3:在MainWindow类中制作IViewMainWindowViewModel接口,该接口为空。

public interface IViewMainWindowViewModel
{

}

4: Make a reference to this interface in the MainWindow

4:在MainWindow中引用这个界面

public partial class MainWindow : Window, IViewMainWindowViewModel
{
    public MainWindow(IViewMainWindowViewModel viewModel)
    {
        InitializeComponent();
        DataContext = viewModel;
    }

5: Also for the MenuViewModel

5:也适用于 MenuViewModel

public class MenuViewModel : IViewMainWindowViewModel
{
    Code not shown!
}

This will not even start the application..

这甚至不会启动应用程序..

Update 2

更新 2

My MainWindow class look like this:

我的 MainWindow 类如下所示:

public interface IViewMainWindowViewModel
{

}

public partial class MainWindow : Window, IViewMainWindowViewModel
{
    public MainWindow(IViewMainWindowViewModel viewModel)
    {
        InitializeComponent();
        DataContext = viewModel;
    }

App class now look like this:

应用程序类现在看起来像这样:

protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        IUnityContainer container = new UnityContainer();
        container.RegisterType<IViewMainWindowViewModel, MainWindow>();
        container.RegisterType<IViewMainWindowViewModel, MenuViewModel>();
        container.Resolve<MainWindow>().Show();
        //Do the same actions for  all views and their viewmodels
    }

I get an exception on this line when running the application

运行应用程序时,我在这一行遇到异常

container.Resolve<MainWindow>().Show();

Update 3

更新 3

In my MenuViewModel it has two command which will open two views, do I then need to inject those views in the MenuViewModel's constructor or can you just make another empty interface between MenuViewModel and BookingView as an example?

在我的 MenuViewModel 中,它有两个命令可以打开两个视图,然后我是否需要在 MenuViewModel 的构造函数中注入这些视图,或者您可以在 MenuViewModel 和 BookingView 之间创建另一个空接口作为示例吗?

采纳答案by StepUp

Let me show an example with explanations just for your MainWindows, as for the rest views and viewmodels steps to do are the same.

让我展示一个示例,其中仅针对您的 进行解释MainWindows,至于其余视图和视图模型的步骤是相同的​​。

At first, you should create a contract between Viewand ViewModel. It shoud be some interface and let it call IViewMainWindowViewModel (keep in mind that name has to be different for other view and viewModels, for example IViewBookingViewViewModel):

首先,您应该在View和之间创建一个合同ViewModel。它应该是一些接口,让它调用 IViewMainWindowViewModel (请记住,对于其他视图和视图模型,名称必须不同,例如 IViewBookingViewViewModel):

public interface IViewMainWindowViewModel
{
       /*This interface should not have any methods or commands. It is just 
       contract between View and ViewModels and helps to decide to Unity 
       container what it should inject(appropriate viewModel to necessary 
       View)*/
}

then in your viewmodel we should implement this interface:

那么在你的视图模型中,我们应该实现这个接口:

public MenuViewModel:IViewMainWindowViewModel
{}

The view should inject this interface MainWindows.xaml.cs:

视图应该注入这个接口MainWindows.xaml.cs

public partial class MainWindows : UserControl, IContentAView
{
    public MainWindows(IViewMainWindowViewModel viewModel)
    {
        InitializeComponent();
        DataContext = viewModel;            
    }
 }

Delete StartupUriand override a method OnStartupin App.xaml.cs:

删除StartupUri和重写的方法OnStartupApp.xaml.cs

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    IUnityContainer container = new UnityContainer();
    container.RegisterType<IViewMainWindowViewModel, MainWindow>();
    container.RegisterType<IViewMainWindowViewModel, MainWindowViewModel >();
    container.Resolve<MainWindow>().Show();
    //Do the same actions for  all views and their viewmodels
}