Accessing Properties in other ViewModels in MVVM Light
Asked Answered
B

3

8

I have a main ViewModel containing a List of items which I'm using in a certain amount of UserControls, which are displayed in a ContentControl on the main view. My current way of exchanging data between the ViewModels exists of making a reference to each of the ViewModels in the main ViewModel, and one of the main ViewModel in every UserControl. However I do not know is this is the right way of doing this, since I have a ViewModelLocator and I kind of expect this class to have some functionality to support something like this.

Can anyone please tell me if what I'm doing this OK, or if there is a better way of doing this in MVVM Light?

EDIT:

I found this when I was searching for something different, would this be a better solution?

private ViewModelLocator locator = new ViewModelLocator();

And then using the locator Properties to reference each ViewModel?

EDIT2:

Apparently what I thought would work doesn't, at first I had only references in the main ViewModel and this worked, but when I try this in the UserControls it kind of crashes my app. I'm currently trying the possible solution of first edit.

MainViewModel.cs (others are similar, with reference only to the main 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;
    }
...
Bloodshed answered 4/6, 2013 at 8:29 Comment(0)
W
17

You can actually use the ViewModelLocator. Defaultly is uses the Inversion of Control Container, so even if you create a new instance of the Locator, you will get the same instance of singleton viewmodels from the container.

The Locator class:

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

then from code you can access it as

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

you get the one and only instance of viewmodel.

from xaml: Resources (defaultly is in Application.Resources in App.xaml)

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

and DataContext for views (either user controls or windows or whatever)

<UserControl
    ... 
    DataContext="{Binding ViewModel1, Source={StaticResource Locator}}"
    ...    >
Willyt answered 4/6, 2013 at 8:45 Comment(2)
Yep you're right, I've just tested this and it works as it should, thanks for the detailed solution, it's much appreciated! :)Bloodshed
I am glad it helped :) . And you can of course use more sophisticated IOC container, which lets you do much more tricks than singleton viewmodels and constructor dependency injection. Simple IOC is just simple...Willyt
B
1

If all you need is to bind a property from the main viewmodel, while inside the content control, just use this syntax:

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

where xxxx is the Name attached to the content control (or any control that has the main viewmodel as its DataContext). Alternatively, you can use relative binding instead of element name.

Batsheva answered 4/4, 2015 at 22:44 Comment(0)
C
1

You could access the public properties of the ViewModel Locator programatically by getting the Locator from the Apps resources:

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

or by creating another static instance in the ViewModelLocator class:

public class ViewModelLocator
{
     public static ViewModelLocator Instance = new ViewModelLocator();

     static ViewModelLocator(){ ... }

     public MainViewModel Main
     {
     ...
     }
}

Similar Thread

Cyclopentane answered 3/1, 2017 at 23:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.