Free Trial

Safari Books Online is a digital library providing on-demand subscription access to thousands of learning resources.

  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint
Share this Page URL
Help

6. MVVM > Connecting a View to a ViewModel using a ViewModelLocator

Connecting a View to a ViewModel using a ViewModelLocator

Connecting a View to a ViewModel using a ViewModelLocator Applies to Silverlight 3, 4, 5 and WP7 One of the first things you'll have to decide on when working with the MVVM design pattern is how you're going to connect your Views to your ViewModels. The simplest method by far is by just instantiating the ViewModel in the View's constructor, but this of course breaks the idea that we're trying to work as loosely coupled as possible (even though a View and ViewModel are somewhat coupled by design, as a ViewModel needs to have the properties used in the View's binding syntax). The approach used in MVVM Light is that of the ViewModelLocator. In this recipe, we'll learn how to use this ViewModelLocator to tie your View and ViewModel together. Getting ready We're starting with the solution we completed in the previous recipe, Using MVVM Light to enable MVVM applications. Or alternatively, you can start with the provided starter solution, which can be found at Chapter 6\Connecting_View_ViewModel_ViewModelLocator_Starter. The completed solution can be found in Chapter 6\Connecting_View_ViewModel_ViewModelLocator_Completed. How to do it... We're going to adjust the solution from the previous recipe, Using MVVM Light to enable MVVM applications, or the starter solution, so it uses the ViewModelLocator to tie the View and ViewModel together. To achieve this, we should complete the following steps: Add a new class to the ViewModel namespace by right-clicking the ViewModel directory and selecting Add new class. Name this class ViewModelLocator.Implement the class as such: public class ViewModelLocator { private static PersonViewModel _personVM; /// <summary> /// Initializes a new instance of the ViewModelLocator class. /// </summary> public ViewModelLocator() { CreatePersonVM(); } /// <summary> /// Gets the PersonVM property. /// </summary> public static PersonViewModel PersonVMStatic { get { if (_personVM == null) { CreatePersonVM(); } return _personVM; } } /// <summary> /// Gets the PersonVM property. /// </summary> [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "This non-static member is needed for data binding purposes.")] public PersonViewModel PersonVM { get { return PersonVMStatic; } } /// <summary> /// Provides a deterministic way to delete the PersonVM property. /// </summary> public static void ClearPersonVM() { _personVM.Cleanup(); _personVM = null; } /// <summary> /// Provides a deterministic way to create the PersonVM property. /// </summary> public static void CreatePersonVM() { if (_personVM == null) { _personVM = new PersonViewModel(); } } /// <summary> /// Cleans up all the resources. /// </summary> public static void Cleanup() { ClearPersonVM(); } } Open App.xaml, and add the following xmlns import: xmlns:vm="clr-namespace:MVVM.Client.ViewModels" Add the following code to App.xaml, right below the<ResourceDictionary> statement: <vm:ViewModelLocator x:Key="Locator" /> Open PeopleView.xaml.cs, and change the constructor to this: public PeopleView() { InitializeComponent(); } Open PeopleView.xaml, and add the following code right below the xmlns import statements: DataContext="{Binding Source={StaticResource Locator}, Path=PersonVM}" You can now build and run your application. How it works... The ViewModelLocator allows us to use binding syntax in the View to tie it to the ViewModel. The ViewModelLocator itself has a property PersonVM. When this property's getter is called, it ties back to a static property, PersonVMStatic, in which the PersonViewModel is instantiated. With that in mind, we now make the ViewModelLocator available for binding by adding it as a StaticResource to the application, in the App.xaml ResourceDictionary. If we now use the binding syntax we've added to PeopleView.xaml, the following will happen: The View is instantiated once we navigate to it.The View's DataContext is bound to a property of our ViewModelLocator, PersonVM. This binding works because the ViewModelLocator is made available through the App.xaml ResourceDictionary.PersonVM ties back to PersonVMStatic. This in turn calls the CreatePersonVM() method, which returns a new instance of PersonViewModel. This instance is now the DataContext of our PeopleView, so the bindings all work. Important to know is that, every time we re-navigate to PeopleView, the same PersonViewModel instance is reused. This is different from how it worked in the previous recipe, Using MVVM Light to enable MVVM applications. There, the PersonViewModel was re-instantiated every time. Typically, in a Silverlight application you want to save the state of a View (kept through the ViewModel), so reusing this PersonViewModel instance is expected, and mostly required, behavior. Finally, if you need to clean up the PersonViewModel, you can use the respective Cleanup() method. There's more... In MVVM, there are two ways of binding your View to your ViewModel. What we've done here is called the View First-approach—when the View gets instantiated, the ViewModel gets instantiated (or reused). In this case, a View is quite strictly tied to a specific ViewModel—we're essentially saying 'View A will always have ViewModel A as its DataContext' (have a look at the next recipe, Connecting a View to a ViewModel using MEF, for a more flexible approach). The ViewModel First-approach works just the other way around—the ViewModel is instantiated, and this takes care of instantiating the View for which it is the DataContext. There is no real right or wrong way to do this—both approaches are valid, and the one you'll choose typically depends on the needs of your application or architecture. The View First-approach is often done with Data Binding and a ViewModelLocator (as seen in this recipe). ViewModel First is typically achieved through the use of an Inversion of Control container—the ViewModel is instantiated by passing in the View (or rather, a contract the View must obey) in its constructor. This easily enables you to, for example, reuse the same ViewModel for different Views. Have a look at the following code: public PersonViewModel(IView view) { // execution } This is a ViewModel first-approach in which any View (abiding by the IView contract) can be injected and used. Other approaches and mixes of both exist—for example, to reach the ability to use a View First-approach in which one View can be tied to a variety of ViewModels, depending on certain rules, you can use the approach detailed in the next recipe, Connecting a View to a ViewModel using MEF. See also For more information on MVVM, have a look at the other recipes in this chapter.

  

You are currently reading a PREVIEW of this book.

                                                                                                                    

Get instant access to over $1 million worth of books and videos.

  

Start a Free Trial


  
  • Safari Books Online
  • Create BookmarkCreate Bookmark
  • Create Note or TagCreate Note or Tag
  • PrintPrint