Consider the Cow

vache

For a while now, a trope has been going around (I think started by Jesse Liberty) to the effect that if you know Silverlight then you already are a Windows Phone 7 developer.

Having spent a lot of time lately on the Windows Phone 7 forums answering questions, I’m actually amazed at how many posts come through that demonstrate a lack of basic knowledge about Silverlight.

… and that’s kindof cool.

My first emotion, however, is always shock and resentment that people are trying to write Windows Phone apps and yet are asking elementary questions about data binding, about how to template a control, about the purpose of the DataContext, about how to skin a listbox.

Not uncommon are questions such as:

“Please to show me how to write a complete Twitter client with samples and with security built in. Thanks in advance.”

What I find impressive in all this (my second emotional reflex) is that the developers who are trying to do the most with Windows Phone are not experienced Silverlight developers – the people we all originally assumed would adopt the Windows Phone platform.

They are not interested (to my chagrin) in the nuances of the Silverlight platform and the best way to prop up an MVVM framework. 

Instead, they are looking to accomplish a task and then move on.  I suspect that while I am still putting the finishing touches on my tombstoning infrastructure and my comprehensive solution to page transitions in a phone app, they will already each have 20 applications ready for the Marketplace, all of them beautiful, functional and competent.

The philosopher Hegel, at a certain point, extols the virtues of the cow, and recommends that people should consume concepts the way a cow will consume grass, quickly and efficiently.  Nietzsche, in a similar vein, considers the cow’s contentment chewing her cud while the philosopher worries about what will make him happy.

One oddity of modern (by which I mean in the past 5 years) programming is that application development time has not gotten any shorter despite the prevalence of frameworks and syntactic sugar in our languages to make the development process easier.  Is it that with better tools, we simply take greater time to create our software edifices?

Windows Phone applications, by contrast, are small and light.  They certainly gain by sophisticated architectures – and I’ve read many a screed decrying the lack of TDD and IoC experience among the new breed of phone developers – but do they really need it?  Do I need architecture at all for a three page application?  Do I really need unit tests?  Continuous integration?

In the consulting and corporate worlds, being able to talk to TDD, IoC, SCRUM and a host of other acronyms sets an expert developer apart and justifies higher rates.  In those particular environments, it makes sense to hone these skills and to guard them jealously as they give us a competitive advantage in the consulting marketplace and along the corporate ladder.

Phone development, however, is judged by a different marketplace.  A phone application doesn’t have to appeal to architects and CEO’s. It simply has to appeal to the twitchy fingers of a phone marketplace consumer who has no idea what is going on underneath the slick appearance of an app.  It seems unlikely that any phone application will achieve high ratings based on the beauty of its architecture. 

So consider the cow.  As consumers of phone applications, this is what we all are.  An app must catch our interest quickly.  The moment an app loses our interest we forget about it.  An app is either successful in maintaining our attention or it isn’t, and if it isn’t it is soon consigned to oblivion.

And now consider the virtues of the cow developer.  The best ones share common characteristics with and understand their audience.  They have little time for finding the “best” way to skin an app (after all, there’s always more than one way to do that).  Instead, they want a quick solution so they can move on to getting the colors right, the sounds right, the overall experience right.  If someone else can provide the quick solution, all the better. 

There is no particular pride to be taken in coming up with a solution by oneself.  Pride doesn’t feed anyone. The primary objective is to create apps that delight the consumer and make him want to buy (or chew, to extend the cow analogy a little too far).

Perhaps it is time we, as developers, began admiring the cow rather than the architect of our plumbing.

WP7 Tip: tombstoning simplified

In order to prepare your phone app to go into tombstone mode (to make it tomb-worthy) it is necessary to save off state data associated with your app.  My preference is to simply save off view models – but you may want to also save off model objects or even individual field values.

There are two dictionaries for doing this. 

IsolatedStorageSettings.ApplicationSettings is available to save persistent data between runs of the application (whether the application gets tombstoned or simply gets closed down).

PhoneApplicationService.Current.State allows one to save and restore data when the application gets tombstoned.  It is handy if we only want to save off data temporarily – for instance if we do not need it for a fresh run of the application. 

Since State and ApplicationSettings are both dictionaries that automatically handle serialization and deserialization for us, much of the underlying code we are required to write when using them is also very similar.

In my own applications, I use a set of utility classes to ease saving and restoring my application state.

Since I generally only want to use State and ApplicationSettings to save and restore data, I encapsulate the plumbing behind a very simple interface.

    public interface IDataStorage
    {
        bool Backup(string token, object value);
        T Restore<T>(string token);
    }

The concrete classes aren’t particularly sophisticated.  I use this for transient data storage:

    public class TransientDataStorage: IDataStorage
    {

        public bool Backup(string token, object value)
        {
            if (null == value)
                return false;

            var store = PhoneApplicationService.Current.State;
            if (store.ContainsKey(token))
                store[token] = value;
            else
                store.Add(token, value);

            return true;
        }

        public T Restore<T>(string token)
        {
            var store = PhoneApplicationService.Current.State;
            if (!store.ContainsKey(token))
                return default(T);

            return (T) store[token];
        }
    }

And this for isolated storage:

    public class PersistentDataStorage: IDataStorage
    {

        public bool Backup(string token, object value)
        {
            if(null == value)
                return false;

            var store = IsolatedStorageSettings.ApplicationSettings;
            if (store.Contains(token))
                store[token] = value;
            else
                store.Add(token,value);

            store.Save();
            return true;
        }

        public T Restore<T>(string token)
        {
            var store = IsolatedStorageSettings.ApplicationSettings;
            if (!store.Contains(token))
                return default(T);

            return (T) store[token];
        }
    }

You’ll notice that the only real difference between these two code segments is that I need to call Save for isolated storage but do not have to for State updates.

Now when I need to save to isolated storage I simply call:

    var store = new PersistentDataStorage();  
    store.Backup("token", myObject);

While a transient save to State is simply:

    var store = new TransientDataStorage();  
    store.Backup("token", myObject);

No sticky kids mess afterwards.

I like having an interface as it allows me to throw some methods on the VMs themselves:

public static bool Backup(IDataStorage store)
{
    return store.Backup("MainViewModel", this._instance);
}

public static void Restore(IDataStorage store)
{
    this._instance = store.Restore<MainViewModel>("MainViewModel");
}

In this case, each VM is responsible for what actually gets saved to storage: for instance, we might want to save off the VM as well as the  associated model object. 

Whether this state is saved off to IsolatedStorage or State, however, gets determined elsewhere – generally in the ApplicationService lifecycle events: Launching, Closing, Activated and Deactivated.

WP7 Tombstoning Pattern Tip

Customizing App.xaml.cs

If you are familiar with tombstoning on Windows Phone, you know there are four events in the Windows Phone application lifecycle that can be handled: PhoneApplicationService.Launching, PhoneApplicationService.Closing, PhoneApplicationService.Activated and PhoneApplicationService.Deactivated.  The first two are for normal app startup and shutdown, while the latter two are for tombstoning scenarios.

Along with these events are two different property bags that application data can be saved to. 

IsolatedStorageSettings.ApplicationSettings  is typically used for backing up persistent data that you want available every time the application starts up. 

PhoneApplicationService.Current.State is used for transient data that you only want persisted if your Silverlight application gets tombstoned.  It is the equivalent of session data in an ASP.NET web application.

In the Launching and Closing event handlers you would typically save to Isolated Storage, while in handlers for Activated and Deactivated you would want to use Current.State.  The former coding artifacts are for persistent data while the latter are for transient data.

These categories are imperfect, however.  It is possible to go through the Deactivated event but never have Activated called.  This occurs if for memory management reasons your application is permanently terminated (a permanent death scenario rather than the temporary death that tombstoning is supposed to trigger).  This can also happen, of course, if the user for whatever reason just decides not to return to your app after it gets tombstoned.

Another way to look at this is that your application is permanently terminated without ever invoking the PhoneApplication.Closing event.

In order to handle this common scenario, you must save any persistent data in the Deactivated event as well as the Closing event.

A simple pattern for structuring your code to cover all these possibilities is to make sure the code fragment for saving persistent data is called in both the Dectivated and Closing event handlers.  Similarly, the fragment for restoring persistent data should be called in both the Activated and Launching handlers.  We do this by taking care of persistent data backup and restores in two new methods: BackupPersistentData and RestorePersistentData. Those who remember the IDisposible pattern in C# will recognize some of the same coding idioms being used here.

The following code goes in App.xaml.cs:

private void BackupPersistentData()
{
    var store = IsolatedStorageSettings.ApplicationSettings;
    //save persistent data
    store.Save();
}
private void RestorePersistentData()
{
    var store = IsolatedStorageSettings.ApplicationSettings;
    //restore persistent data
}

private void Application_Closing(object sender
    , ClosingEventArgs e)
{
    BackupPersistentData();
}

private void Application_Launching(object sender
    , LaunchingEventArgs e)
{
    RestorePersistentData();
}

private void Application_Deactivated(object sender
    , DeactivatedEventArgs e)
{
    BackupPersistentData();
    var store = PhoneApplicationService.Current.State;
    //save transient data
}

private void Application_Activated(object sender
    , ActivatedEventArgs e)
{
    RestorePersistentData();
    var store = PhoneApplicationService.Current.State;
    //restore transient data
}

Sticking to this pattern has helped me to avoid a lot of unforeseen mistakes in my own phone apps.

 



Getting the current theme in WP7 for Silverlight

Customizing App.xaml.cs

Windows Phone devices allow users two theme options, either dark or light.

In the WP7 beta dev tools, however, there no straight-forward way for Windows Phone Silverlight developers to find out what the current theme is, though there is a hack.  The developer must interrogate the app resources to find the color of the PhoneBackGroundColor.  Under the dark theme it is black, while under the light theme it is white.

The following code can be thrown into App.xaml.cs to add a little elegance to this hack. 

First, a brief enum is needed.  It can be added in App.xaml.cs above the App class, or simply placed in its own cs file in the project:

public enum Theme{Light,Dark}

A CurrentTheme property is added to the App class:

private static Theme _currentTheme;

public static Theme CurrentTheme
{
    get { return _currentTheme; }
    private set { _currentTheme = value; }
}

And then we assign a value to CurrentTheme in the App class constructor by interrogating Resources:

public App()
{
    var bgc = Resources["PhoneBackgroundColor"].ToString();
    if (bgc == "#FF000000")
        CurrentTheme = Theme.Dark;
    else
        CurrentTheme = Theme.Light;

    //etc.

The CurrentTheme is now retrievable from anywhere in the application like so:

    switch(App.CurrentTheme)
    {
        case Theme.Dark:
            MessageBox.Show("Dark");
            break;
        case Theme.Light:
            MessageBox.Show("Light");
            break;
    }

Moreover, if a user presses the Windows button at lower center on a device and resets the theme, the new theme will be assigned to CurrentTheme when the application returns from tombstoning.

There is a rumor that in the RTM of the WP7 dev tools, two new properties will be available for picking up the current theme: DarkThemeVisibility and LightThemeVisibility.

For ease of migration to the RTM, you can add the following two properties to App.xaml.cs for now as placeholders – you should be able to simply switch them out later should the new methods become available:

public static bool DarkThemeVisibility
{
    get { return CurrentTheme == Theme.Dark; }
}

public static bool LightThemeVisibility
{
    get { return CurrentTheme == Theme.Light; }
}

How to Quit a WP7 Silverlight Application

Customizing App.xaml.cs

In the current Beta dev tools for Windows Phone 7, there is no way to exit a Silverlight application (though there is a method to do this for XNA apps).

Currently the best way – and I use the term “best” loosely – to do this is to throw an exception.  An unhandled exception always manages to kill your application.

If we must use a hack, however, we might as well  do it with a bit of finesse.  Below is a simple implementation that can be placed in the App class of a WP7 Silverlight project that clarifies the behavior of the app when we intentionally throw an exception in order to exit rather than simply throwing an exception exceptionally.

This code can be called from anywhere in your app in order to Exit predictably.

Here is the call:
App.Quit();
And here is the implementation in App.xaml.cs:
private class QuitException : Exception { }

public static void Quit()
{
    throw new QuitException();
}

private void Application_UnhandledException(object sender, 
    ApplicationUnhandledExceptionEventArgs e)
{
    if (e.ExceptionObject is QuitException)
        return;

    if (System.Diagnostics.Debugger.IsAttached)
    {
        System.Diagnostics.Debugger.Break();
    }

    //etc.
}
Windows Phone 8 Update

If you are doing Windows Phone 8 development, things get easier.  After having so many apps going through the store using the above method to exit out, the WP Dev\Design team decided to just implement their own escape method.  Sometimes the doctor is right and sometimes the patient just has a better understanding of what the pain feels like.  To exit out of a Windows Phone 8 app, call Application.Terminate .

Patterns of Windows Phone Architecture Part II

When the WP7 beta dev tools were released, developers were pleased to find several new events hanging off of Shell.PhoneApplicationService for managing a phone application’s life cycle: Launching, Closing, Activated and Deactivated.  The first two events are obviously thrown when an application is first launched and when it is closed down (either by hitting the back button past the first page in the app or, interestingly, by throwing an unhandled exception).

The Activated and Deactivated events are thrown when the application is interrupted mid-run – typically by launching a Windows Phone task or by hitting the Windows button on the phone.  This is a scenario known as tombstoning.

If you are not yet familiar with the concept of tombstoning or simply need a refresher, please read Yochay Kiriaty’s post on the subject here.

These new events give Silverlight for WP7 developers a way to manage application state outside of the navigation events on each page.  Two design considerations must be taken into account, however, in order to take advantage of this centralized way of persisting state information.  1. All data that needs to be persisted between application runs or during tombstoning must be accessible from the event handlers for the four lifecycle events.  2. If application data persistence is handled outside of each page, another mechanism is required for persisting page state information as well as model data between page instantiations.

2. Anchor ViewModel

The Pledge

An anchored boat is able to stay in one place while currents wash away unmoored items floating on the ocean.  Anything tethered to the boat, or tethered to something tethered to the boat, is likewise stationary.  This is the main concept behind an Anchor ViewModel phone architecture.

While the developer has little control over the lifespan of a PhoneApplicationPage, he can nevertheless control the life of the state of the page if he is using an M-V-VM pattern.  There are several artifacts in the application that ViewModels can be tethered to and which survive the constant newing up and dereferencing of Views in a Silverlight app for the phone.  The Application itself can serve as an anchor.  It has a RootVisual, the PhoneApplicationFrame, which hosts (typically) a MainPage.xaml PhoneApplicationPage that doesn’t go out of scope until the application is terminated.  ViewModels can be tethered to any of these objects in order to give them a lifespan beyond the lifespan of their respective Views.

The Windows Phone Databound Application Template that is provided with Visual Studio for Windows Phone demonstrates this anchoring technique.  In this sample template, the MainViewModel object hangs off of the App class.  When the MainPage view is instantiated, the App’s MainViewModel instance is assigned to the MainPage view’s DataContext. At this point, the lifecycle of MainViewModel is tethered to the lifecycle of App rather than to the lifecycle of MainPage.

The DetailsPage view, in turn, retrieves its DataContext from a ViewModel hanging off of MainViewModel which hangs off of App.  The lifecycle of the ItemViewModel is tethered to the lifecycle of MainViewModel which in turn is anchored to the App class.

The Turn

This is more evident if we change the default application based on the Windows Phone Databound Application Template a little.  First, MainViewModel can be modified to include a SelectedItem property:

private ItemViewModel _selectedItem;
public ItemViewModel SelectedItem 
{
    get { return _selectedItem; }
    set 
    { 
        _selectedItem = value;
        NotifyPropertyChanged("SelectedItem");
    }
}

Then the ListBox in MainPage.xaml should have it’s SelectedItem attribute bound to this property:

<ListBox x:Name="MainListBox" 
            SelectedItem="{Binding SelectedItem, Mode=TwoWay}" 
            ItemsSource="{Binding Items}"

We simplify the MainListBox’s SelectionChanged event handler like so:

// Handle selection changed on ListBox
private void MainListBox_SelectionChanged(object sender
    , SelectionChangedEventArgs e)
{
    // If selected index is -1 (no selection) do nothing
    if (MainListBox.SelectedIndex == -1)
        return;

    // Navigate to the new page
    NavigationService.Navigate(new Uri("/DetailsPage.xaml"
        , UriKind.Relative));
}

Finally, in our details page, we would set the DataContext in the constructor rather than in the OnNavigatedTo method:

public DetailsPage()
{
    InitializeComponent();
    if (DataContext == null)
        DataContext = App.ViewModel.SelectedItem;
}

The point to remember here is that when the DetailsPage view goes out of scope through a back page navigation, the VM for DetailsPage continues to exist in memory and remains accessible because it is tethered to MainViewModel. 

More importantly, if we change a property on the ItemViewModel we are using for the DataContext of DetailsPage, these changes would be persisted back to MainViewModel after we navigate away from DetailsPage, and would remain persisted for as long as the current App is held in memory.

The Prestige

The payoff to this pattern is that we can now handle tombstoning by persisting all of our VMs centrally in a few lines of code:

string _appToken = "all_vms";

private void Application_Activated(object sender
    , ActivatedEventArgs e)
{
    var store = PhoneApplicationService.Current.State;
    if (store.ContainsKey(_appToken))
        viewModel = store[_appToken] as MainViewModel;
}

private void Application_Deactivated(object sender
    , DeactivatedEventArgs e)
{
    var store = PhoneApplicationService.Current.State;
    if (store.ContainsKey(_appToken))
        store[_appToken] = viewModel;
    else
        store.Add(_appToken, viewModel);
}

Because all view models are anchored to MainViewModel, saving our top level view model will also automatically serialize and later deserialize all the of VMs hanging off of MainViewModel as well as the state of their properties.

We have effectively made the entire default Databound Phone Application sample “tombworthy”.   If you now tombstone the application while navigated to the DetailsPage (for instance by pressing the Windows button at bottom center), it will be restored when you return to the application.

In an application with 5, 10 or more VMs, this will be very handy.

The next post in this series will cover the Satellite ViewModels pattern, which uses many of the same principles but allows greater control over how and what state gets persisted.

 

 

Patterns of Windows Phone Architecture Part 1

The Windows Phone platform introduces several problems for the software architect which, if not completely absent in standard Silverlight applications, are nevertheless more acute. The most important of these revolve around state: the state of data during the running of an application and the state of the data between runs.

Because Windows Phone design is structured around the phone navigation frame, a Silverlight out-of-browser application on the phone behaves more like a web application than a stateful application.  The lifespan of a typical PhoneApplicationPage is uncertain. 

While the first page in a Phone application’s backstack (usually MainPage.xaml) is tied to the lifespan of the application itself, all other pages are only accessible while currently displayed or existing in the backstack.  By existing on the backstack, I here mean accessible 1. by pressing the back button and 2. by calling NavigationService.GoBack() .

Once a page is no longer visible because a user has navigated back, it is no longer accessible whether it has been garbage collected or not.  In this sense, typical concepts of garbage collection are not really relevant. 

Once you have navigated backwards, the same instance of the page cannot be retrieved.  For instance, in the scenario where a user begins at MainPage.xaml and then navigates forward to DetailsPage.xaml, then navigates back to MainPage again, an additional navigation forward to DetailsPage.xaml will create a new instance of Details.  The original instance is lost and is no longer accessible.

To make matters more difficult, if the the application launches a task based on user input, the Details page is once again lost.  When the user clicks back to return to the application from a launcher or completes a chooser task, a new instance of DetailsPage will be created.  When the user clicks back from DetailsPage, a new instance of MainPage will be instantiated.  This termination of the current application in order to run task is known as “tombstoning”.

A final problem regarding state occurs if the phone application makes calls to web services.  Because web services are much more expensive and time sensitive than on typical web applications, it is highly desirable to cache data that has been retrieved from a service.

We’ll categorize these problems as problems of 1. page data state, 2. application data state and 3. model data state, respectively.

In this post I will outline three architectural patterns for solving these three problems of state in a Windows Phone application.  The patterns are View-ViewModel Pairing, Satellite ViewModels and Anchor ViewModels.

In the following posts, I will go in depth into the implementation each approach as well as provide helper classes and recommended coding patterns.  Finally, I will show how they can be incorporated into existing frameworks and techniques such as MVVM Light, Caliburn Micro and IOC.

I. View-ViewModel Pairing (Buddy System)

The View-ViewModel Pairing pattern is based on a persistence pattern recommended during the CTP stage of the Phone Development Tools.  In this pattern, each page or view (MainPage, DetailsPage, etc.) is responsible for the persistence of its data each time the page is added to or leaves the backstack. 

In the CTP, this was often illustrated by saving the data for a particular control on the view (current.State is used here, but isolated storage would work just as well):

string token = "myToken";

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var store = PhoneApplicationService.Current.State;
    if (store.ContainsKey(token))
    {
        string txt = store[token] as string;
        if (txt != null)
            this.textBox1.Text = txt;
    }
}

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    var store = PhoneApplicationService.Current.State;
    if (store.ContainsKey(token))
        store[token] = textBox1.Text;
    else
        store.Add(token, textBox1.Text);
}

This becomes cumbersome, however, if more than a few properties require persistence.  A better approach is possible if the phone application uses M-V-VM in its design (or really any UI Design Pattern that takes advantage of the DataContext property).  In this case, we can simply persist the entire VM rather than iterate through each control.  The above code can be simplified like this:

public Page1()
{
    InitializeComponent();
    this.Loaded += new RoutedEventHandler(Page1_Loaded);
}

void Page1_Loaded(object sender, RoutedEventArgs e)
{
    if (this.DataContext == null)
        this.DataContext = new Page1ViewModel();
}

string token = "myToken";
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var store = PhoneApplicationService.Current.State;
    if (store.ContainsKey(token))
        this.DataContext = store[token] as string;
}

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    var store = PhoneApplicationService.Current.State;
    if (store.ContainsKey(token))
        store[token] = this.DataContext;
    else
        store.Add(token, this.DataContext);
}

This pattern collapses the problems of page data persistence and application data persistence by saving both off at the same time.

On the first navigation to this page, the Loaded event handler news up the datacontext.  On subsequent visits to the page, the DataContext is set in the OnNavigatedTo event handler.  Because Loaded fires after OnNavigatedTo, the DataContext is not set there.  Each visit to this page will always retrieve the same ViewModel data from state, whether the View is itself new or not.

This solution also works in cases where the application has been tombstoned.

If IsolatedStorage is used instead of PhoneApplicationService.Current.State, the ViewModel will even survive between runs of the application.

Finally, because any data retrieved from a web service is typically fed into an ObservableCollection on the ViewModel, the serialization/deserialization process will also typically take care of caching relevant model data.

There is one significant shortcomings to using the Buddy System.  Because there is no way (at least in the beta) to find out in the OnNavigatedTo event handler if we are returning from a tombstoned state or simply returning from a subsequent page through the back button, we may be re-hydrating the ViewModel unnecessarily.

(To be continued …)

DevLink Dynamic Object Code Sample

Several people asked about the Dynamic code I used for making Restful calls at the end of the Dynamic Types and Dynamic Objects talk at DevLink.

I have uploaded the sample to my skydrive.  Please use this code in any way you like.  Just keep in mind that most of the magic going with JSON and XML parsing was written by Nikhil Kothari.

WP7 Tip: don’t use the unlocked ROM for development

One of the frustrations of developing for Windows Phone 7 is that, without a device in hand, it is hard to understand what the phone actually looks like.  It is useful to be able to see how Microsoft implements the built in applications in order to borrow ideas for hubs, transitions, and general look-and-feel.

Enterprising developers quickly built an “unlocked” version of the July emulator image that allows developers to see more of the features and design of the phone in their emulator software.

You should not use the unlocked ROM image for development, however.  One problem that has come up concerns making https service calls from an application running in the unlocked image.

If you try to call an https service from the unlocked ROM, you are likely to receive a variation on the Page Not Found error.  To verify that this is a problem with the ROM image and not with your code, open up Internet Explorer and try to navigate to a site such as https://careers.microsoft.com/ .  If you receive an error, then the issues are likely not with your code but with the emulator image you are using.  Switch back to using the official developer image that is installed with the Windows Phone developer tools beta and your web service issues should go away.