Windows Phone 7 – Application Lifecycle – Ocean for the Phone

travelreport

On October 9th 2010 I did a presentation at the Silicon Valley Code Camp on the Application Lifecycle for Windows Phone 7.  This last week was KA-ray-zeee busy at work and I didn’t want to just post the slides and code I had at code camp.  Better to wait and really do a good job, so here it is.

Introduction

First, I would like to acknowledge the outstanding decks and examples that the Microsoft Windows Phone 7 Evangelism Team has been and continues to publish.  Team members I’ve been working with are Yochay Kiriaty and Jaime Rodriguez.

I created the provided deck from several decks published by the Evangelism Team.  I edited and added content for the session I did.

For the three example applications, I studied the Evangelism Team’s material, samples on the web, added many hours of learning and ported Ocean to the Windows Phone 7.

This was a lot of fun, in-fact more pure fun than I’ve had in a while.  Don’t get my wrong, I love what I do everyday and the opportunities I’ve been blessed with at Microsoft.  Maybe because the phone is new, I didn’t really know much about it, but was able to understand it and get productive quickly.  Additionally, the Visual Studio 2010 tooling worked great. 

No other way to say it, “developing on Windows Phone 7 is a lot of fun.”  Very much looking forward to getting my own device.

I’m encouraged that Microsoft has a commitment to the XAML language and that I was able to leverage my huge investment in WPF with Silverlight 3-4, and now the Windows Phone 7.  The ability to transfer my investment across platforms and devices is a fantastic benefit to developers on Microsoft’s stacks.

Let me now turn our attention to what is in the box (the download).

Presentation Slide Deck

The deck is in the solution folder and explains each topic clearly.  The application lifecycle concepts are repeated several times in different ways so the reader can grasp tombstonning.

The code snippets in the deck come from TravelReporting project and the OceanFramework.Phone project.

ApplicationLifeCycle Project

The purpose of this application is to provide a nice clear log of the application’s constructors, methods and events as they execute.  It is critical to your success that you learn the phone’s application lifecycle.  This program can help with that.

Crack the App.xaml open and look at the CustomHyperlinkButtonStyle.  I use this to make a Hyperlink control look and act like a Button.  I do this so that I can navigate from XAML and not have to wire up a command or click event handler.  You’ll see this style used in all three applications where appropriate.

Notice how clean my debug output window is.  That’s because I’ve turned off the other messages.  To turn off the other messages, right click the debug output window while debugging.  Then unselect messages on the context menu that you do not want to see.  Below, I just want to see my phone messages, so I’ve left Program Output selected.

DebugWindow

Logger

Creating the log messages is very simple, just call Logger.Log();  You can also pass an optional notes string.

void Application_Launching(Object sender, LaunchingEventArgs e) {
    Logger.Log();
}

The magic is in the below Log method.  By creating a StackTrace object, I can extract the calling type and method from the appropriate stack frame.  This type of logging is much better than having to craft each individual log message.  I’ve used this class in each of the projects.

namespace ApplicationLifeCycle.Infrastructure {
    public class Logger {

        public static void Log(String notes = "") {
            StackTrace stackTrace = new StackTrace();

            String typeName = stackTrace.GetFrame(1).GetMethod().DeclaringType.Name;
            String methodName = stackTrace.GetFrame(1).GetMethod().Name;

            if(!String.IsNullOrEmpty(notes)) {
                notes = String.Concat(" - ", notes);
            }
            Debug.WriteLine(String.Format("WP7: {0} - {1}{2}", typeName, methodName, notes));
        }

        private Logger() {
        }
    }
}

LaunchersAndChoosers Project

This project demonstrates 3 launchers and 3 choosers.  It also provides a lot of logging so that you can see what goes on and when.  Spend some time, using the application.  Then predict the sequence of events before executing them, you’ll have the application lifecycle down quickly.

Take a look at the MainPage.xaml and MainPage.xaml.cs.  By using the CustomHyperlinkButtonStyle, I was able to run code-free in the code-behind.

TravelReporting Project

This application allows a user to enter a travel report from their phone.  The travel report has two pages of required data.  The user can’t proceed to the second page unless the first page is valid. 

For validation I’m using the declarative (attribute based) validation offered by the Ocean framework.  The validation API’s allow for multiple rule-sets.  This enabled me to have a set of rules for the first page’s fields and a set of rules to validate the entire object on page two.

IDataErrorInfo is not supported in this release of Silverlight for Windows Phone 7.  I have included the interface so that you can have it in place if and when it is supported.  In this simple application, I’m not bothering the user with messages until they press the Next or Save buttons.  When Next or Saved is pressed, the TravelReport object is validated against the appropriate rules.

To see the validation attributes in action, have a look at the TravelReport.cs file.  You’ll also see several rules added in code.

When the travel report is saved it is added to the history file. 

The History page  is accessed from the main page’s menu.  The history presents a list of travel reports and allows viewing the report in detail.

The history file simulates accessing the cloud for historical data.  When the application starts, two travel reports are added to the history file to give you something to look at.

Extras

TombstoneSupportPhoneApplicationPage (OceanFramework.Phone)

This is the base class for all my pages.  It adds automatic tombstone activating and deactivating support so that I don’t have to repeat this code on each page.

One challenge developers have is this business of focus not changing when the user presses the back, start, application button or menu.  The problem is, control data bindings do not update their source until lost focus occurs.  Since lost focus does not happen when the user does one of these actions, the user could loose that field’s data that was entered but not committed to the source.  Remember, when a user presses the start button, the application will be tombstoned and if the field’s data was not committed to the model or view model before those objects get persisted, then the data that was entered is lost.

Not to worry.  The below method handles this quirk for you.  Take note of the below TODO.  My current application only has TextBoxes that need this help.  Your applications may need additional tests for other controls.

This method also records the name of the currently focused control so that when the application comes back from tombstonning, the focus field can be restored.

protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e) {
    base.OnNavigatingFrom(e);

    // Remove previous focused element
    if (State.ContainsKey(FOCUSED_ELEMENT)) {
        State.Remove(FOCUSED_ELEMENT);
    }

    // If an input control has focus, perform an explict binding update.
    // If the user pressed the back button, start button or application button,
    // the binding expression will not process since focus did not change.
    // So... you need to force the binding expression to update so that the
    // model property will be updated.
    var focusedElement = FocusManager.GetFocusedElement() as Control;
    if (focusedElement != null) {

        if (!String.IsNullOrEmpty(focusedElement.Name)) {
            State.Add(FOCUSED_ELEMENT, focusedElement.Name);
        }

        BindingExpression be = null;

        //TODO - Developers, add additional controls here like a date picker, combobox, etc.
        if (focusedElement is TextBox) {
            be = focusedElement.GetBindingExpression(TextBox.TextProperty);
        }

        if (be != null) {
            be.UpdateSource();
        }
    }
}

IsolatedStorageFacade (OceanFramework.Phone)

This facade class provides a simple interface for interacting with the IsolatedStorageFile and IsolatedStorageSettings.  You’ll want to modify this to meet you specific needs.

I made all the methods static for ease of use.  If I was using an IOC container, I would provide an interface and inject an implementation.  This would also make testing easier since the implementation could be swapped out.

TombstoneFacade (OceanFramework.Phone)

This facade class provides a simple interface for interacting with the PhoneApplicationService temporary storage state bag.  You’ll want to modify this to meet you specific needs.

I made all the methods static for ease of use.  If I was using an IOC container, I would provide an interface and inject an implementation.  This would also make testing easier since the implementation could be swapped out.

Globalization

I met with my great friend Laurent Bugnion of MVVM-Light fame this week and spent time taking about Windows Phone 7.  I asked him about globalization of the phone apps.  He explained his solution for using .resx files and I’m sharing it with you.

The Localizer class is a front end that we can instantiate in XAML, then controls can data bind directly to the properties in the .resx file.  This wrapper is required because the .resx class, can’t be instantiated in XAML, even if it is marked public.  This may be a bug, I’ll check up on this.

// Many thanks to Laurent Bugnion http://www.galasoft.ch/ for this cool tip.
// This wrapper around the Strings.resx allows us to data bind to values in XAML
// See App.xaml and MainPage.xaml to see the moving parts.  Very simple solution.
public class Localizer {

    Strings _strings;

    public Strings Strings {
        get { return _strings; }
    }

    public Localizer() {
        _strings = new Strings();
    }
}

This XAML is from App.xaml.

<infrastructure:Localizer x:Key="LocalizedStrings" />

The below TextBlock displays a globalized string for the application title.  All strings in the TravelReports application are resources.

<TextBlock Style="{StaticResource PhoneTextNormalStyle}"
    Text="{Binding Source={StaticResource LocalizedStrings}, 
           Path=Strings.Application_Title, Mode=OneTime}" />

Download

The download is on my sky drive here.

Remember after downloading a .zip file, you’ll want to right click on the file and “Unblock” the file.  This is the mark-of-the-web that Visual Studio 2010 respects.

Have a great day.

Just a grain of sand on the worlds beaches.

6 Responses to Windows Phone 7 – Application Lifecycle – Ocean for the Phone

  1. [...] This post was mentioned on Twitter by Karl Shifflett, Karl Shifflett. Karl Shifflett said: Posted on #WP7 Application Lifecycle http://tinyurl.com/29x3zfq includes three applications, Ocean for the Phone and WP7 tips. [...]

  2. Windows Phone 7 – Application Lifecycle – Ocean for the Phone…

    Thank you for submitting this cool story – Trackback from DotNetShoutout…

  3. [...] you can bind the Text Property of your TextBlock controls to your resources (see the blog of Karl Shifflet for the code of the manager [...]

  4. [...] Windows Phone 7 – Application Lifecycle – Ocean for the Phone – Karl Shifflett discusses the application lifecycle of Windows Phone 7 applications, exploring and sharing a sample application which logs the key method calls in the applications lifecycle. Karl also looks at using his port of the Ocean Framework to the Windows Phone 7 to provide validation, access to isolated storage, and additionally some helpers for tombstoning the application [...]

  5. inquisitorjax says:

    Check this out to solve your resource binding issues:

    http://sites.google.com/site/dmytrokryvko/

  6. [...] I’ve already ported Ocean to C#, Windows Phone 7 and released it here. [...]

Follow

Get every new post delivered to your Inbox.

Join 247 other followers