【问题标题】:Accessing Properties in other ViewModels in MVVM Light在 MVVM Light 中访问其他 ViewModel 中的属性
【发布时间】:2013-06-04 08:29:18
【问题描述】:

我有一个主ViewModel,其中包含我正在使用的一定数量的UserControls 的项目列表,这些项目显示在主视图上的ContentControl 中。我目前在ViewModels 之间交换数据的方式是引用主要ViewModel 中的每个ViewModels,以及每个UserControl 中的主要ViewModel 之一。但是我不知道这是不是正确的做法,因为我有一个ViewModelLocator,我有点希望这个类有一些功能来支持这样的东西。

谁能告诉我这样做是否可行,或者在 MVVM Light 中是否有更好的方法?

编辑:

我在寻找不同的东西时发现了这个,这是一个更好的解决方案吗?

private ViewModelLocator locator = new ViewModelLocator();

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

EDIT2:

显然,我认为可行的方法不起作用,起初我在主要的 ViewModel 中只有引用并且这有效,但是当我在 UserControls 中尝试此操作时,它使我的应用程序崩溃。我目前正在尝试第一次编辑的可能解决方案。

MainViewModel.cs(其他类似,仅参考主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;
    }
...

【问题讨论】:

    标签: c# mvvm-light


    【解决方案1】:

    您实际上可以使用 ViewModelLocator。默认是使用 Inversion of Control Container,所以即使你创建一个新的 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" />
    

    和 DataContext 用于视图(用户控件或窗口或其他)

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

    【讨论】:

    • 是的,您是对的,我刚刚对此进行了测试,并且可以正常工作,感谢您提供详细的解决方案,非常感谢! :)
    • 我很高兴它有帮助:)。你当然可以使用更复杂的 IOC 容器,它可以让你做比单例视图模型和构造函数依赖注入更多的技巧。简单的 IOC 就是简单...
    【解决方案2】:

    如果您只需要在主视图模型中绑定一个属性,在内容控件中,只需使用以下语法:

       ... Binding="{DataContext.mainvmpropertyname, ElementName=xxxx}"
    

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

    【讨论】:

      【解决方案3】:

      您可以通过从应用程序资源获取定位器以编程方式访问 ViewModel 定位器的公共属性:

      MyViewModel vm = (App.Current.Resources["Locator"] as ViewModelLocator).MyViewModel
      

      或通过在 ViewModelLocator 类中创建另一个静态实例:

      public class ViewModelLocator
      {
           public static ViewModelLocator Instance = new ViewModelLocator();
      
           static ViewModelLocator(){ ... }
      
           public MainViewModel Main
           {
           ...
           }
      }
      

      Similar Thread

      【讨论】:

        猜你喜欢
        • 2011-02-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-07
        • 1970-01-01
        相关资源
        最近更新 更多