Now is a good time to walk through the code that implements the MVVM pattern in the Windows Phone 7 application in more detail. As you go through this section, you may want to download the Microsoft Visual Studio® development system solution for the Windows Phone 7 Tailspin Surveys application; it is available on the Windows Phone 7 Developer Guide community site on CodePlex (http://go.microsoft.com/fwlink/?LinkId=205602).
There are several ways to connect the view model to the view, including direct relations and data template relations. The developers at Tailspin chose to use a view model locator because this approach means that the application has a single class that is responsible for hooking up views to view models. This still leaves developers free to choose to manually perform the hookup within the view model locator, or by using a dependency injection container.
Inside the Implementation
The mobile client application uses a view model locator to connect view models to views. The following code example from the App.xaml file shows how the view model locator class is identified and made available to the application. The application declares the TailSpin. PhoneClient.ViewModels ViewModelLocator class in the <Application. Resources> section of the App.xaml file.
XAML
<Application
x:Class=”TailSpin.PhoneClient.App”
…
xmlns:viewmodels=
“clr-namespace:TailSpin.PhoneClient.ViewModels”
… >
<!–Application Resources–>
<Application.Resources>
…
<viewmodels:ViewModelLocator x:Key=”ViewModelLocator”/>
</Application.Resources>
…
</Application>
The following code example from the SurveyListView.xaml file shows how a view can then reference the ViewModelLocator class as a static resource in its data context bindings.
XAML
<phone:PhoneApplicationPage
x:Class=”
TailSpin.PhoneClient.Views.SurveyList.SurveyListView”
…
DataContext=
“{Binding Source={StaticResource ViewModelLocator},
Path=SurveyListViewModel}”
…
>
…
</phone:PhoneApplicationPage>
The Path attribute identifies the property of the ViewModel Locator instance that returns the view model associated with the current page.
The following code example shows the parts of the ViewModel Locator class that return the SurveyListViewModel instance.
C#
public class ViewModelLocator : IDisposable
{
private readonly ContainerLocator containerLocator;
…public SurveyListViewModel SurveyListViewModel
{
get
{
return this.containerLocator.Container
.Resolve<SurveyListViewModel>();
}
}
}
Notice how the Tailspin phone client uses the Funq dependency injection container to instantiate the view model.
The following code example shows the parts of the ViewModel Locator class that return the TakeSurveyViewModel instance when the user selects a survey from the survey list. In this example, the view model is instantiated with details of the currently selected survey so that the application can display the survey questions on the Take SurveyView page.
C#
public TakeSurveyViewModel TakeSurveyViewModel
{
get
{
var templateViewModel =
this.SurveyListViewModel.SelectedSurveyTemplate;
var vm = new TakeSurveyViewModel(
this.containerLocator.Container
.Resolve<INavigationService>())
{
SurveyStoreLocator = this.containerLocator.Container
.Resolve<ISurveyStoreLocator>(),
LocationService = this.containerLocator.Container
.Resolve<ILocationService>(),
TemplateViewModel = templateViewModel,
SurveyAnswer = this.containerLocator.Container
.Resolve<ISurveyStoreLocator>().GetStore()
.GetCurrentAnswerForTemplate(templateViewModel.Template)
?? templateViewModel.Template.CreateSurveyAnswers(
this.containerLocator.Container
.Resolve<ILocationService>())
};
vm.Initialize();
return vm;
}
}Note: The view locator is also responsible for instantiating the store and passing it to the view model, which in turn passes it on to the model.