Model-View-ViewModel (MVVM) is a very useful pattern for organizing scalable and constantly evolving phone applications. In MVVM, Each view is backed by a view-model and a model. Models are loaded from storage or the network often as pages are displayed to the user.
Joe Healy co-author of the Teach Yourself Windows Phone 7 Application Development in 24 Hours comments that many phone developers are not using nor are familiar with MVVM and that this pattern is applicable for any app that is sharing global app data across multiple pages. |
In Phone applications it is desirable for the performance of page navigation to be as fast as possible. Users do not have the tolerance for waiting several seconds between pages as they do on web applications. To remedy this, phone applications often place their models at the application scope so that they may be accessed by all the pages. This does not mean that all the data is loaded at application start though. The application model acts as a cache for that data that has been loaded.
One implementation might be to define an ApplicationModel class and define it as a resource in the app.xaml file. Then Any data binding can be trivially done within XAML. An issue occurs this that approach.
<Application.Resources>
<app:ApplicationModel x:Key="ApplicationModelK" />
</Application.Resources>
<TextBlock Text="{Binding Source={StaticResource ApplicationModelK}, Path=SomeData}"/>
Both One-Way and Two-Way data binding rely on INotifyPropertyChanged event on the binding. The Binding also has a reference to the bound UI control which has a reference to the page. When the user navigates back (exiting the page), the page stack no longer holds a reference to the page and the page would normally get garbage collected.
But since a reference still exists from App->ApplicationModel->SomeData->Binding->UI Control->Page then the page never gets garbage collected. This page reference leak results in all the resources of the page being held in memory. Further, when the user returns to the page, a second page instance is created and all the resources reallocated again. Also, when the ApplicationModel data changes both the old and new instances of the page are notified.
One solution to this is to not bind directly to the global ApplicationModel but instead set the page.DataContext to the ApplicationModel.SomeData when inside of OnNavigatedTo and to set DataContext to null on OnNavigatingFrom. Then in your binding you bind only to the partial object path rather than the global reference.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
DataContext = Application.Current.Resources["ApplicationModelK"];
base.OnNavigatedTo(e);
}
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
DataContext = null;
base.OnNavigatedFrom(e);
}
<TextBlock Text="{Binding SomeData}"/>
With this pattern the binding to global data will be removed when exiting the page and the references back to the page will be release allowing the page to be garbage collected.