4

Building a WP7 app using MVVM light for my view models. I'm using the ViewModelLocator that gets added when you add the library through NuGet. Works great but now I need to get access to a ViewModel from code.

In my code the user clicks a button and I need to search the MainViewModel (which contains several view models) and find one based on the criteria the user entered.

Normally I would just response to the Click event of the button but I don't have an instance variable of the ViewModelLocator class to get a hold of the MainViewModel to perform the search. With the default template (non-MVVMLight) for Windows Phone 7, the App class has a static variable to the main view model so you can access it anytime with App.ViewModel.

There's some talk from twitter about using commands which would be good, but at some point I have to perform a code search across multiple vms to get the results I need. Probably need to inject a ISearchViewModel service into the View or something to make this work.

Here's the implementation of ViewModelLocator that is provided:

public class ViewModelLocator
{
    private static MainViewModel _main;

    public ViewModelLocator()
    {
        _main = new MainViewModel();
    }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
    "CA1822:MarkMembersAsStatic",
    Justification = "This non-static member is needed for data binding purposes.")]
    public MainViewModel Main
    {
        get
        {
            return _main;
        }
    }
}

So from the code behind of another view, how do you get access to Main (MainViewModel contains all the lists of data and has a search method I call)? Or Should you?

Just wondering how people are solving this type of problem?

Thanks.

John Gardner
  • 24,225
  • 5
  • 58
  • 76
Bil Simser
  • 1,713
  • 1
  • 19
  • 27
  • I'm not sure how this would impact your application or the MVVM-Light structure or code but I followed the default implementation of WP and created all my ViewModels as static and then reference them as needed from the App class. -Again not sure how this will work with your specific project set up. – evasilchenko Aug 12 '11 at 20:01
  • Yes, the default setup creates them all as static which is fine but the ViewModelLocator class (which provides blendability of the VMs for use in both design and runtime) isn't a static class and doesn' have static view models. – Bil Simser Aug 12 '11 at 20:05

4 Answers4

14

In MVVM-Light the ViewModelLocator is provided as an application resource. Therefore you can still directly access it, but the syntax is different. If you look at your App.xaml you should see this piece of code somewhere.

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

From anywhere in your application you can access the App's resources and therefore also the MainViewModel with this piece of code:

(App.Current.Resources["Locator"] as ViewModelLocator).Main

This works for any application resource.

Tom Verhoeff
  • 1,270
  • 6
  • 12
4

If you created the ViewModelLocator as in the template you have static references to the ViewModels. The mvvmlocatorproperty-snippet creates ViewModel-properties like this. This means that you could just instantiate a new ViewModelLocator to locate the ViewModels in your code behind button click. It will always be the same viewmodels independent of the different instances of the ViewModelLocator

Martin
  • 106
  • 5
  • Looking into this. The snippet output doesn't match what you get when you create a new project so I might have to adjust things a little. There's a static reference to each ViewModel you create in the locator so this might work. Back later tonight to see if it does. – Bil Simser Aug 12 '11 at 20:47
  • Just checked it and once the correct code is in place with the ViewModelLocator then Martin is correct. Creating any instance of the ViewModelLocator allows you to access the static properties of it while maintaining the blendability of it in design mode. – Bil Simser Aug 12 '11 at 21:05
2

To access the MainViewModel from your code you can add this property to your class:

public ViewModel.MainViewModel myContext { get { return (DataContext as ViewModel.MainViewModel); } }

Then you can just use myContext.[whatever]

theChrisKent
  • 15,029
  • 3
  • 61
  • 62
  • This might work, going to try using the snippet to adjust the main view model first but will try this out too. Of course now the question which technique is better? – Bil Simser Aug 12 '11 at 20:48
  • I used this in my App.xaml.cs as a static reference, it will let you access your MainViewmodel instance from any code behind file that has a using statement for the app. – Lance McCarthy Jan 17 '14 at 17:56
0

You can just use ViewModelLocator.MainViewModelStatic. Default template for MVVMLight have a static property for each your viewmodel.

Sinh Pham
  • 246
  • 1
  • 2
  • 7