Xaml ViewModelLocator MVVM灯光中的ViewModels

Xaml ViewModelLocator MVVM灯光中的ViewModels,xaml,mvvm-light,Xaml,Mvvm Light,将所有视图模型存储在SimpleIoc中是否正确?例如,我有三个页面主页、照片、目录(因此有三个ViewModels->MainVM、PhotoVM、DirectoriesVM)。我应该在每个页面中设置DataContext以查看ViewModelLocator中的模型属性,还是将ViewModels嵌套为MainVM中的属性,并将每个页面DataContext绑定到Main.PhotosVMProperty、Main.DirectoriesVMProperty等?有人能给我解释一下IoC的概念

将所有视图模型存储在SimpleIoc中是否正确?例如,我有三个页面主页、照片、目录(因此有三个ViewModels->MainVM、PhotoVM、DirectoriesVM)。我应该在每个页面中设置DataContext以查看ViewModelLocator中的模型属性,还是将ViewModels嵌套为MainVM中的属性,并将每个页面DataContext绑定到Main.PhotosVMProperty、Main.DirectoriesVMProperty等?有人能给我解释一下IoC的概念和目的吗?

首先,让我们看看ViewModelLocator的功能以及我们使用它的原因:

ViewModelLocator在我们的App.xaml页面上声明为一个对象,是一个应用程序单例。我们将有一个,并且只有一个在应用程序运行时可用

ViewModelLocator是MVVM Light中所有ViewModel的源代码。对于每个ViewModel,ViewModelLocator上都有一个属性,允许我们获取视图的ViewModel。此代码如下所示:

public class ViewModelLocator
{
    public MainPageViewModel MainPage
    {
        get { return new MainPageViewModel(); }
    }
}
public class ViewModelLocator
{
    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        if (ViewModelBase.IsInDesignModeStatic)
        {
            SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
        }
        else
        {
            SimpleIoc.Default.Register<IDataService, DataService>();         
        }

        SimpleIoc.Default.Register<MainViewModel>();
    }

    public MainViewModel Main
    {
        get { return SimpleIoc.Default.GetInstance<MainViewModel>(); }
    }
}

public class MainViewModel
{
    public ObservableCollection<Foo> Foos { get; set; }

    public MainViewModel(IDataService dataService)
    {
        _dataService=dataService;
        Foos=_dataService.GetFoos();
    }
}
这是我的App.xaml的一部分:

<Application.Resources>
    <vm:ViewModelLocator
        x:Key="ViewModelLocator" />
</Application.Resources>
到目前为止还不错。要回答第一个问题,您是否必须在MVVM灯光下使用Ioc?不需要,因为ViewModelLocator将为您的视图提供完全构建和实例化的viewmodel

现在,谈谈你的第二个问题:国际奥委会的目的是什么

国际奥委会旨在让你做到以下几点:

使用Mvvm Light,您可以按如下方式执行上述操作:

public class ViewModelLocator
{
    public MainPageViewModel MainPage
    {
        get { return new MainPageViewModel(); }
    }
}
public class ViewModelLocator
{
    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        if (ViewModelBase.IsInDesignModeStatic)
        {
            SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
        }
        else
        {
            SimpleIoc.Default.Register<IDataService, DataService>();         
        }

        SimpleIoc.Default.Register<MainViewModel>();
    }

    public MainViewModel Main
    {
        get { return SimpleIoc.Default.GetInstance<MainViewModel>(); }
    }
}

public class MainViewModel
{
    public ObservableCollection<Foo> Foos { get; set; }

    public MainViewModel(IDataService dataService)
    {
        _dataService=dataService;
        Foos=_dataService.GetFoos();
    }
}
公共类ViewModelLocator
{
公共ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(()=>SimpleIoc.Default);
if(ViewModelBase.IsIndesignatic)
{
SimpleIoc.Default.Register();
}
其他的
{
SimpleIoc.Default.Register();
}
SimpleIoc.Default.Register();
}
公共主视图模型主视图
{
获取{return SimpleIoc.Default.GetInstance();}
}
}
公共类主视图模型
{
公共可观测集合Foos{get;set;}
公共主视图模型(IDataService数据服务)
{
_数据服务=数据服务;
Foos=\u dataService.GetFoos();
}
}
当我在调用时解析MainViewModel时

SimpleIoc.Default.GetInstance<MainViewModel>()
SimpleIoc.Default.GetInstance()
内部情况是SimpleIoc检查MainViewModel是否有任何依赖项(其构造函数中的参数)。然后,它尝试通过查看已注册的接口来解析这些参数。它以递归方式执行此操作,因此,如果DataService具有依赖关系,则在实例化DataService时,它也会被实例化并传递给DataService构造函数

我为什么要做这些工作

  • 使您的类易于单元测试
  • 使您的代码接口受驱动。这意味着您引用的是接口,而不是具体的类
  • 使代码松散耦合。这意味着有人可以更改接口的实现,而使用该接口的类并不关心,也不必重新编码
  • 以自动方式解决类依赖关系
  • 在MVVM环境中,您将看到它可以判断何时在设计模式下运行(
    ViewModelBase.IsInDesignModeStatic
    ),这意味着您可以创建设计时服务来提供viewmodels数据,以便在Visual Studio中的视图包含实际数据

  • MVVM Light有很多不错的特性,但在我看来,服务定位器在视图模型上创建了不需要的视图依赖性。理想情况下,我希望库A中有ViewModelLocator,库B中有ViewModelLocator,库C中有ViewModelLocator。然后我可以根据未来项目的需要混合和匹配这些视图。然而,在MVVM Light的设计中,据我所见,视图(库C)将始终依赖于ViewModelLocator(这是可以的),但由于ViewModelLocator(库a)将始终依赖于视图模型(库B),因此视图将始终依赖于视图模型(这是不好的,因为视图现在必须包括它在所有产品中使用过的所有视图模型库)

    我相信Prism是通过使用字符串键来解决这个问题的。我是不是遗漏了什么

    哎呀!我想我刚刚回答了我自己的问题。解决方案是使库A,ServiceLocator,特定于特定的解决方案(产品)。然后,它只包含对该解决方案的视图模型的引用。然后,视图依赖于此ServiceLocator,而此ServiceLocator反过来又依赖于该产品的所有视图模型。最终结果是,视图只依赖于它将用于该产品的视图模型。事实上,我们是dupli为每个解决方案定义ServiceLocator,因为此模块仅包含特定于该解决方案的代码。ServiceLocator的组件(如SimpleIoc类)当然对所有解决方案都是通用的,但这些组件已分解为我们在ServiceLocator中调用的可重用类


    总而言之,我试图解决的问题是假设一个解决方案有6个视图模型,其中四个是密切相关的,两个是密切相关的。因此,我们创建了两个程序集,每个程序集都包含密切相关的视图模型。假设我们设计一个使用一组视图模型的产品,解决方案是designed运行Windows 8。现在视图都不同了,我们只想重复使用一组(程序集)视图模型的。因此,我们只需创建一个新的ServiceLocator程序集,该程序集指向此视图模型程序集以及我们需要的任何其他程序集。我们的新Windows 8视图现在依赖于此新ServiceLocator程序集,并且仅依赖于新产品(解决方案)中使用的视图模型.

    我希望这能对您有所帮助:您能提供一些与第二种方法相关的代码吗?如何在MainViewModel中定义PhotosVMProperty…您的问题非常有趣…非常好的分解