Monthly Archives: August 2011

WP7: Upgrading Your App From 7.0 to Mango (FAS / Tombstoning)

While upgrading an existing Windows Phone 7.0 application to Mango and all its multitasking and performance improvement glory is a pretty easy task (simply go to the Project properties and change the target from Windows Phone 7.0 to Windows Phone 7.1), there are a few things you need to watch out for when upgrading that you might have to fix manually.

One of the bugs I came across in Noborizaka was that when my application was first launched, everything would operate as normal – but whereas in the old Windows 7.0 version if my application got tombstoned and reactivated everything would work fine, in Mango, after my app was rehydrated, the databinding for my listboxes etc. didn’t seem to be valid any more so new items wouldn’t appear on the main page until I reset the application fully.

It turns out the reason for this is that as part of Mango and Fast Application Switching (FAS), the OS automatically stores your application’s entire state while it’s in the “multitasking backstack”. So therefore, you need to check the .IsApplicationInstancePreserved proeprty in the Application_Activated of your App.xaml.cs, and if it’s true, you should not restore your state from IsolatedStorage. Example:

[sourcecode language="c-sharp"]
//Windows Phone 7.0
private void Application_Activated(object sender, ActivatedEventArgs e)
{
RestoreStateFromTombstone();
}

//Windows Phone 7.1/7.5/Mango
private void Application_Activated(object sender, ActivatedEventArgs e)
{
if (!e.IsApplicationInstancePreserved)
{
RestoreStateFromTombstone();
}
}
[/sourcecode]

Everything else should work as normal – good luck to all the devs out there making Mango apps! (p.s. if you’d like to read more on the Execution Model of WP7, and what the lifecycle of an application looks like, you can take a look at the MSDN documentation here.)

WP7: Updating Live Tiles Locally In Mango

As you’ll no doubt be aware if you’ve been looking at any of the information around Mango released over the past few months, there’s a large number of additional APIs available in the upcoming update release to Windows Phone 7. One of the ones I’m very excited for is the ability to update the live tile for your application locally! This means that for Noborizaka, I no longer have to host an Azure service to generate an image when I can simply do so from the phone itself.

Updating Live Tiles programmatically is extremely simple, too. The basic steps are:

  • Get the main Application Tile. Every app you create has this tile, and this is the tile users see when they pin your application to the Start screen. You can do so like this:

    [sourcecode language="c-sharp"]
    ShellTile defaultTile = ShellTile.ActiveTiles.First();
    [/sourcecode]

  • Update the application tile, providing a StandardTileData object. Once you have a reference to the main application tile, you can call the Update() method, providing a StandardTileData object which can contain a BackgroundImage, Title, Count (as well as some other properties for the back of the tile, which is also new to Mango).

    [sourcecode language="c-sharp"]
    defaultTile.Update(new StandardTileData { BackgroundImage = new Uri("isostore:" + sTilePath, UriKind.Absolute), Title = "Noborizaka" });
    [/sourcecode]

  • Note that instead of pointing to a BackgroundImage with a Uri to an online image, I’m pointing to an image that I’ve stored in local isolated storage – I’ve set up my app so that when it’s exiting or being deactivated, it quickly generates the tile image and saves it to isolated storage before the live tile is updated, and it all seems to work quite well. Note that the tile image needs to be stored in a folder ‘\Shared\ShellContent’ for it to be available for tile updates.

    If you’d like to read more on live tile updating (such as updating the back of the live tile and secondary tiles), check out this MSDN Article. You can also check out how to generate live tile images without using the visual tree here (ie, elements that aren’t being rendered directly onto your application).

PreSaveAction() – Custom JavaScript when submitting SharePoint ListForms

Here’s a short but quick SharePoint 2010 tip if you’re looking to easily hook into the save event on list item forms (either New or Edit forms). All you need is a custom javascript function named PreSaveAction() – as part of the out of the box saving procedure in SharePoint 2010, this method will automatically be called prior to the item being committed.

This is useful for fields that you’ve set to read-only when loading the form (since you need the form input elements enabled for the values to be set properly), or custom form validation – if your PreSaveAction method returns true, SharePoint proceeds with the item save action, but you can cancel this by returning false.

The easiest way to include your custom javascript in SharePoint 2010 is probably with a Visual Web Part, although you could also create a custom form template (see my previous post on this here) or a full custom .aspx form.

ASP.NET DropDownList and optgroup

It’s been a bit quiet in here, but here’s a short and sharp tip – for some reason (backwards compatibility, most likely), the standard DropDownList control doesn’t support adding <optgroup> elements in order to nicely group your list item options. There’s lots of workarounds for this (roll your own “dropdown” with jQuery, insert some dummy list items and bold them etc) but the best way is probably to just subclass the DropDownList control and override the RenderContents method. A quick google should come up with heaps, but here’s one that I found that works off StackOverflow:

[sourcecode language="c-sharp"]
using System;
using System.Web.UI.WebControls.Adapters;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.Generic;
using System.Web;

//This codes makes the dropdownlist control recognize items with "–"’
//for the label or items with an OptionGroup attribute and render them’
//as instead of .’
public class DropDownListAdapter : WebControlAdapter
{

protected override void RenderContents(HtmlTextWriter writer)
{
DropDownList list = Control as DropDownList;
string currentOptionGroup;
List renderedOptionGroups = new List();

foreach(ListItem item in list.Items)
{
if (item.Attributes["OptionGroup"] != null)
{
//’The item is part of an option group’
currentOptionGroup = item.Attributes["OptionGroup"];
//’the option header was already written, just render the list item’
if(renderedOptionGroups.Contains(currentOptionGroup))
RenderListItem(item, writer);
else
{
//the header was not written- do that first’
if (renderedOptionGroups.Count > 0)
RenderOptionGroupEndTag(writer); //’need to close previous group’
RenderOptionGroupBeginTag(currentOptionGroup, writer);
renderedOptionGroups.Add(currentOptionGroup);
RenderListItem(item, writer);
}
}
else if (item.Text == "–") //simple separator
{
RenderOptionGroupBeginTag("–", writer);
RenderOptionGroupEndTag(writer);
}
else
{
//default behavior: render the list item as normal’
RenderListItem(item, writer);
}
}

if(renderedOptionGroups.Count > 0)
RenderOptionGroupEndTag(writer);
}

private void RenderOptionGroupBeginTag(string name, HtmlTextWriter writer)
{
writer.WriteBeginTag("optgroup");
writer.WriteAttribute("label", name);
writer.Write(HtmlTextWriter.TagRightChar);
writer.WriteLine();
}

private void RenderOptionGroupEndTag(HtmlTextWriter writer)
{
writer.WriteEndTag("optgroup");
writer.WriteLine();
}

private void RenderListItem(ListItem item, HtmlTextWriter writer)
{
writer.WriteBeginTag("option");
writer.WriteAttribute("value", item.Value, true);
if (item.Selected)
writer.WriteAttribute("selected", "selected", false);

foreach (string key in item.Attributes.Keys)
writer.WriteAttribute(key, item.Attributes[key]);

writer.Write(HtmlTextWriter.TagRightChar);
HttpUtility.HtmlEncode(item.Text, writer);
writer.WriteEndTag("option");
writer.WriteLine();
}

}
[/sourcecode]

TechEd is coming up soon! Can’t wait for Jeff Wilcox’s WP7 sessions!