在MVVM Light中访问其他ViewModel的属性

8
我有一个主要的ViewModel,包含一系列项目,我在一定数量的UserControl中使用这些项目,这些UserControl显示在主视图的ContentControl中。我当前的数据交换方式是在主ViewModel中对每个ViewModel进行引用,并在每个UserControl中引用一个主ViewModel。然而,我不确定这是否是正确的方法,因为我有一个ViewModelLocator,我希望这个类有一些功能支持类似这样的操作。
请问有人能告诉我我正在做的是否正确,或者在MVVM Light中是否有更好的方法?
编辑:
当我搜索其他内容时,我发现了这个,它会是更好的解决方案吗?
private ViewModelLocator locator = new ViewModelLocator();

然后使用定位器属性来引用每个ViewModel?

编辑2:

显然我认为会起作用的方法并没有起作用,一开始我只在主ViewModel中引用,这个方法可以工作,但是当我尝试在UserControls中尝试此方法时,我的应用程序崩溃了。目前我正在尝试第一个编辑中提出的可能解决方案。

MainViewModel.cs(其他ViewModel类似,只有对主ViewModel的引用)

public class MainViewModel : ViewModelBase
{
    private ItemAddViewModel itemAddViewModel;
    private ItemsViewModel itemsViewModel;

    /// <summary>
    /// Initializes a new instance of the MainViewModel class.
    /// </summary>
    public MainViewModel()
    {
        ItemsList = Item.GetItemsList();

        itemAddViewModel = ServiceLocator.Current.GetInstance<ItemAddViewModel>();
        itemsViewModel = ServiceLocator.Current.GetInstance<ItemsViewModel>();

        ShowItemsView();
    }
...
    private void ShowItemsView()
    {
        CurrentControl = itemsViewModel;
    }
...
3个回答

17
你实际上可以使用 ViewModelLocator。默认情况下它使用反转控制容器,因此即使创建了 Locator 的新实例,也将从容器中获取相同的单例视图模型实例。
Locator 类:
static ViewModelLocator()
{
    ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
    SimpleIoc.Default.Register<ViewModel1>();
    SimpleIoc.Default.Register<ViewModel2>();
    SimpleIoc.Default.Register<ViewModel3>();
}

public ViewModel1 ViewModel1
{
    get
    {
        return ServiceLocator.Current.GetInstance<ViewModel1>();
    }
}

public ViewModel2 ViewModel2
{
    get
    {
        return ServiceLocator.Current.GetInstance<ViewModel2>();
    }
}

public ViewModel3 ViewModel3
{
    get
    {
        return ServiceLocator.Current.GetInstance<ViewModel3>();
    }
}

然后你可以从代码中访问它:

var vm1 = (new ViewModelLocator ()).ViewModel1;

您将获得ViewModel的唯一实例。

从XAML中获取: 资源(默认情况下在App.xaml中的Application.Resources中)

<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />

并且为视图(无论是用户控件、窗口或其他)提供数据上下文

<UserControl
    ... 
    DataContext="{Binding ViewModel1, Source={StaticResource Locator}}"
    ...    >

没错,我刚刚测试了一下,它按照预期工作了,感谢你提供详细的解决方案,非常感激! :) - Kryptoxx
我很高兴它有所帮助 :) 当然,你可以使用更复杂的IOC容器,它可以让你做比单例视图模型和构造函数依赖注入更多的技巧。简单的IOC只是简单... - eMko

1
如果您只需要在内容控件内绑定来自主视图模型的属性,只需使用以下语法:
   ... Binding="{DataContext.mainvmpropertyname, ElementName=xxxx}"

xxxx是附加到内容控件(或任何将主视图模型作为其数据上下文的控件)的名称。或者,您可以使用相对绑定而不是元素名称。


1
您可以通过从应用程序资源中获取定位器来以编程方式访问ViewModel Locator的公共属性:
MyViewModel vm = (App.Current.Resources["Locator"] as ViewModelLocator).MyViewModel

或者通过在ViewModelLocator类中创建另一个静态实例来实现:
public class ViewModelLocator
{
     public static ViewModelLocator Instance = new ViewModelLocator();

     static ViewModelLocator(){ ... }

     public MainViewModel Main
     {
     ...
     }
}

类似的主题


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接