WPF,MVVM IoC:服务定位器模式的替代方案.在后面的View代码中需要依赖 [英] WPF, MVVM IoC: Alternative to Service Locator Pattern. Need dependency in View code behind

查看:137
本文介绍了WPF,MVVM IoC:服务定位器模式的替代方案.在后面的View代码中需要依赖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

按照几本指南,我使用WPF .NET 4.7.1和M​​VVM-Light进行如下应用程序布局.我对WPF btw完全陌生.

Following several guides I have a application layout like below using WPF .NET 4.7.1 and MVVM-Light. I'm totally new to WPF btw.

App.xaml:

<Application x:Class="My.App" 
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
         xmlns:viewmodel="clr-namespace:My.ViewModel" 
         StartupUri="View\MainView.xaml">
<Application.Resources>
    <ResourceDictionary>
        <viewmodel:ViewModelLocator x:Key="Locator" />
    </ResourceDictionary>
</Application.Resources>

将"ViewModelLocator"类注册为资源,并将WPF启动设置为"View/MainView.xaml".

That registers the "ViewModelLocator" class as a resources and sets the WPF startup to "View/MainView.xaml".

MainView.xaml:

MainView.xaml:

<Window x:Class="My.View.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Window.DataContext>
    <Binding  Path="Main" Source="{StaticResource Locator}"/>
</Window.DataContext>

在使用ViewModelLocator时,就像服务定位器模式一样.这里将DataContext设置为我的"MainViewModel"(未显示).尽管我不喜欢它,但我可以在WPF XAML上下文中使用它.但是现在事实证明,我需要在视图的代码背后有一个依赖关系(而不是ViewModel).

Where the ViewModelLocator is used like a Service Locator Pattern. Here setting the DataContext to my "MainViewModel" (not shown). As much as I do not like this, I can live with it in the WPF XAML context. However now it turns out that I need a dependency in the code-behind of the view (not the ViewModel).

MainView.cs:

MainView.cs:

public partial class MainView : INotifyPropertyChanged
{
   public MainView()
   {
       // Need to access dependency here.          
   }
}

现在,我可以直接在该构造函数中直接调用ViewModelLocator并从我的IoC容器中进行解析-但是,我已经完全接受并接受了该模式.

Now I could just call the ViewModelLocator directly in that constructor and have that resolve from my IoC container - but then I've completely given in and accepting that pattern.

我当然希望将依赖项注入ctor中,如果可能的话,我也将完全离开ViewModelLocator并在此处注入ViewModel.

I would prefer to have the dependency injected in the ctor of course, and if that is possible, I would also leave the ViewModelLocator entirely and inject the ViewModel here.

问题是,是否有一些标准的方法来指示WPF应用程序使用我的容器?如果是的话,建议您沿着那条路而不使用ViewModelLocator东西吗?

So question is, are there some standard way of instructing WPF application to use my container? And if yes, is it adviceable to go down that path and not use the ViewModelLocator thing?

推荐答案

您绝对不必使用 ViewModelLocator (请注意,服务定位器模式最近受到了很多批评,因为反模式,但我会让你发表自己的看法).MVVM Light和其他库基本上使您可以使用工具套件.您无需使用所有工具,而仅应使用特定域所需的工具.

You absolutely do not have to use the ViewModelLocator (Side note, the service locator pattern has had it's fair share of criticism lately as an anti-pattern, but I'll let you form your own opinion). MVVM Light and other Libraries basically give you access to a tool kit. You don't need to use all of the tools, and you should only use what is necessary for your specific domain.

ViewModelLocator 之外,有两种称为 ViewModel First View First 的模式各有优缺点.但是,两者都提供了一种使代码解耦的方法,这意味着以后进行切换并不困难.

Outside of the ViewModelLocator, there are two patterns known as ViewModel First and View First both have their pro's and cons. However both provide a means to decouple your code, which means it's not difficult to switch later.

对于使用不带服务定位器的MVVM Light来构建应用程序的情况,我对View First方法的实现看起来像这样.

As for constructing an application using MVVM Light without the service locator, my implementation of the View First method looks something like this.

我已经听说过首选 ViewModel First 的观点,但是我发现View First对于测试驱动开发(TDD)更为简单

I've heard the opinion that ViewModel First is preferred, however I find View First to be more simplistic for Test Driven Development (TDD)

App.xaml.cs(后面的应用代码)

App.xaml.cs (Application Code Behind)

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        var bootStrapper = new BootStrapper();
        //Container Builder
        var container = bootStrapper.BootStrap();
        var mainWindow = container.Resolve<MainWindow>();
        mainWindow.Show();
    }
}

BootStrapper.cs(在这种情况下,我使用的是AutoFac,但您可以轻松地替换它.)

BootStrapper.cs (I'm using AutoFac in this case, but you can easily substitute.)

public class BootStrapper
{
    public IContainer BootStrap()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<MainWindow>().AsSelf();
        builder.RegisterType<MainWindowViewModel>().AsSelf();
        return builder.Build();
    }
}

MainWindowViewModel.cs

MainWindowViewModel.cs

//I rolled my own ViewModelBase, but you can use MVVM Light's ViewModelBase
public class MainWindowViewModel : ViewModelBase
{
    public string DisplayProgram
    {
        get { return _displayProgram; }
        //MVVM Light's ViewModelBase uses RaisePropertyChanged();
        set { _displayProgram = value; OnPropertyChanged(); }
    }

    public void Initialize()
    {
        //Called from view code behind.
    }
}

MainWindow.xaml.cs(后面的MainWindow代码)

MainWindow.xaml.cs (MainWindow Code Behind)

//When MainWindow.Show()..
public partial class MainWindow : Window
{
    private readonly MainWindowViewModel _viewModel;
    //Container resolves dependencies
    public MainWindow(MainWindowViewModel viewModel)
    {
        //Let base Window class do its thing.
        InitializeComponent();

        //Handle loaded event
        Loaded += MainWindowLoaded;

        //Hold on to the MainWindowViewModel, and set it as the windows DataContext            
        _viewModel = viewModel;
        DataContext = _viewModel;
    }

    private void MainWindowLoaded(object sender, RoutedEventArgs e)
    {
        _viewModel.Initialize();
    }
}

这篇关于WPF,MVVM IoC:服务定位器模式的替代方案.在后面的View代码中需要依赖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆