WPF、MVVMIOC:服务定位器模式的替代方案。需要视图中的依赖项代码隐藏

WPF、MVVMIOC:服务定位器模式的替代方案。需要视图中的依赖项代码隐藏,wpf,inversion-of-control,mvvm-light,Wpf,Inversion Of Control,Mvvm Light,遵循几条指南,我使用WPF.NET4.7.1和MVVMLight创建了如下应用程序布局。顺便说一句,我是WPF的新手 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"

遵循几条指南,我使用WPF.NET4.7.1和MVVMLight创建了如下应用程序布局。顺便说一句,我是WPF的新手

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,并从IoC容器中获得解析,但我已经完全放弃并接受了该模式

当然,我更愿意在ctor中注入依赖项,如果可能的话,我也会完全保留ViewModelLocator,并在这里注入ViewModel


所以问题是,是否有一些标准的方法来指示WPF应用程序使用我的容器?如果是的话,那么沿着这条路走下去,不使用ViewModelLocator是明智的吗?

您绝对不必使用ViewModelLocator侧注,服务定位器模式最近作为一种反模式受到了相当多的批评,但我会让您形成自己的观点。MVVMLight和其他库基本上为您提供了一个工具包。您不需要使用所有的工具,您应该只使用特定领域所需的工具

在ViewModelLocator之外,有两种模式称为ViewModel First和View First,它们都有各自的优缺点。然而,两者都提供了一种方法来解耦代码,这意味着以后切换并不困难

至于在不使用服务定位器的情况下使用MVVM Light构建应用程序,我对View First方法的实现如下所示

我听过这样的观点,ViewModel-First是首选的,但是我发现ViewModel-First对于测试驱动的开发TDD来说更简单

App.xaml.cs应用程序代码隐藏

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();
    }
}
//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();
    }
}
MainWindow.xaml.cs主窗口代码隐藏

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();
    }
}
//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();
    }
}

您绝对不必使用ViewModelLocator侧注,服务定位器模式最近作为一种反模式受到了相当多的批评,但我将让您形成自己的观点。MVVMLight和其他库基本上为您提供了一个工具包。您不需要使用所有的工具,您应该只使用特定领域所需的工具

在ViewModelLocator之外,有两种模式称为ViewModel First和View First,它们都有各自的优缺点。然而,两者都提供了一种方法来解耦代码,这意味着以后切换并不困难

至于在不使用服务定位器的情况下使用MVVM Light构建应用程序,我对View First方法的实现如下所示

我听过这样的观点,ViewModel-First是首选的,但是我发现ViewModel-First对于测试驱动的开发TDD来说更简单

App.xaml.cs应用程序代码隐藏

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();
    }
}
//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();
    }
}
MainWindow.xaml.cs主窗口代码隐藏

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();
    }
}
//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();
    }
}

谢谢,vrey对我很有帮助,而且是一种更干净的方法。但是假设我在MainView.xaml中有这样一种方法:。WPF需要一个默认的无参数构造函数。我是否会绑定到MainView.cs中的属性,并将ISubView注入MainView中?我想这样,我的设计师就不会工作了。我希望WPF通过CommonServiceLocator或类似的方式支持容器。。。您的应用程序有多复杂?有多少子视图?这些子视图是否需要沟通?如果您希望编辑新的Viewctor并使其不那么丑陋,那么现在就让它工作,并让它成为一个合理的窗口,重构总是可以在事情变得更清楚的时候进行。打破设计器,然后发现您的用户不喜欢按钮lol的位置,这真的是一件痛苦的事情。我明白了,所以,一般来说,不在视图中开始使用依赖项注入是明智的吗?随着时间的推移,应用程序将变得相当庞大。我在这里寻找最佳实践。我们第一次开始使用WPF,但我们没有打破常规WPF使用的经验,因为我们已经习惯了到处使用DI。不,我不是这么说的。我添加了条件,如果您只是想让它暂时起作用。因为我不知道你的应用程序的大小和范围。我把决定权留给你了。对于视图,您绝对应该使用DI,但是对于一个牵强的示例,如果您现在让它工作,您可能会发现您不希望在MainView中使用子视图。相反,您需要更多的复合应用程序。或者,您可能会发现MVVM灯光太“亮”,并切换到Prism Library。谢谢,vrey非常有用,而且是一种更干净的方法。但假设我在MainView.xaml中有此选项:。WPF需要一个默认的无参数构造函数。我是否会绑定到MainView.cs中的属性,并将ISubView注入MainView中?我想这样,我的设计师就不会工作了。我希望WPF通过CommonServiceLocator或类似的方式支持容器。。。您的应用程序有多复杂?有多少子视图?这些是吗
子视图需要沟通吗?如果您希望编辑新的Viewctor并使其不那么丑陋,那么现在就让它工作,并让它成为一个合理的窗口,重构总是可以在事情变得更清楚的时候进行。打破设计器,然后发现您的用户不喜欢按钮lol的位置,这真的是一件痛苦的事情。我明白了,所以,一般来说,不在视图中开始使用依赖项注入是明智的吗?随着时间的推移,应用程序将变得相当庞大。我在这里寻找最佳实践。我们第一次开始使用WPF,但我们没有打破常规WPF使用的经验,因为我们已经习惯了到处使用DI。不,我不是这么说的。我添加了条件,如果您只是想让它暂时起作用。因为我不知道你的应用程序的大小和范围。我把决定权留给你了。对于视图,您绝对应该使用DI,但是对于一个牵强的示例,如果您现在让它工作,您可能会发现您不希望在MainView中使用子视图。相反,您需要更多的复合应用程序。或者您可能会发现MVVM灯光太“亮”,并切换到Prism Library。