Fighting the Lock Screen in Windows Phone 7 by disabling IdleDetectionMode

Fighting the Lock Screen in Windows Phone 7 by disabling IdleDetectionMode

One of the things you may experience with your Windows Phone application is that it will get suspended when the lock screen is displayed. As the lock screen appears after a relatively short period of time this can be particularly frustrating if you have to synchronize a large quantity of data, or you have created a game that only requires the accelerometer (no user input on the screen can result in the application appearing to be idle). To get around this you can disable idle detection by setting one of two properties.

Microsoft.Phone.Shell.PhoneApplicationService.Current.ApplicationIdleDetectionMode

Or

Microsoft.Phone.Shell.PhoneApplicationService.Current.UserIdleDetectionMode

Essentially setting the UserIdleDetectionMode to disabled will prevent the lock screen automatically appearing, whilst setting ApplicationIdleDetectionMode to disabled will allow the application to continue to operate whilst the lock screen is active. Note that there is a clause in the application certification requirements that stipulate the conditions with which you must comply when setting these properties.

Windows Phone 7 and Compression using Accept-Encoding Header

Windows Phone 7 and Compression using Accept-Encoding Header

As a few of my readers have commented on my post  Windows Phone 7 Data: Json WCF Data Service with IIS 7 Compression, there is a breaking change between the CTP and Beta versions of the Windows Phone developer tools that prevents you from setting the Accept-Encoding header. One could argue that the fact you could set this at all in the ctp was a bug, since Silverlight 3 doesn’t permit this. Unfortunately not being able to set this header is a major pain if you want to take advantage of the built in IIS dynamic and/or static compression. I would really like to see this fixed before the tools ship but given we’re only a couple of weeks away from the ship date of the tools I doubt very much if it will be.

Having spent a few days at TechEd Australia thinking about this issue I went digging to see if we could either force IIS to compress all data (ie that way we wouldn’t have to set the Accept-Encoding header) or better still try to apply compression based on some other request attribute. In the end the fix was actually surprisingly simple.

Firstly, I have to call out a post by Ted Jardine on IE6 gzip bug solved using IIS7’s URL Rewrite Modulewhich put me on the right track. Essentially the process goes like this:

– In the request we set a different header (I chose one called “Compress-Data” and set it to a value of  “true”)
– On the server we define a rewrite rule that will detect this header and set the Accept-Encoding header to gzip,deflate for all matching requests.
– The server would then serve up compressed data – Woot!

Ok, so these are the steps you need to follow:

1) Update the applicationHost.config file to allow you to modify the allowedServerVariables element. This file is typically found at C:WindowsSystem32inetsrvconfig

<configuration>
    <configSections>
        <sectionGroup name="system.webServer">
            <sectionGroup name="rewrite">
                <section name="allowedServerVariables" overrideModeDefault="Allow" />

2) Add a rewrite rule to the web.config file for your application. Note that you have to include allowedServerVariables element in order for the HTTP_ACCEPT_ENCODING server variable to be set by the rule.

<configuration>
    <system.webServer>
        <rewrite>
            <allowedServerVariables>
                <add name="HTTP_ACCEPT_ENCODING" />
            </allowedServerVariables>
            <rules>
                <rule name="RewriteUserFriendlyURL1" patternSyntax="Wildcard" stopProcessing="false">
                    <match url="*" />
                    <conditions>
                        <add input="{HTTP_COMPRESS_DATA}" pattern="true" />
                    </conditions>
                    <action type="None" />
                    <serverVariables>
                        <set name="HTTP_ACCEPT_ENCODING" value="gzip,deflate" />
                    </serverVariables>
                </rule>
            </rules>
        </rewrite>

This will match all urls, looking for the HTTP_COMPRESS_DATA variable set to true. When working with rewrite rules you have to remember that headers are converted to variables by a) making them upper case, b) replacing “-“ with “_” and c) adding HTTP_ as a prefix. In this case when a match is found the HTTP_ACCEPT_ENCODING variable (ie the Accept-Encoding header) is set to gzip,deflate, as if you had specified this in the header when making the request.

3) Now all we need to do is to call this from our Windows Phone application, specifying the appropriate header.

private void MakeRequestButton_Click(object sender, RoutedEventArgs e){
    var request = HttpWebRequest.Create("<request url>”) as HttpWebRequest;
    request.Accept = "application/json";
    request.Headers["Compress-data"] = "true";
    request.BeginGetResponse(RequestCallback, request);
}

private void RequestCallback(IAsyncResult result){
    var request = result.AsyncState as HttpWebRequest;
    var response = request.EndGetResponse(result);
    using(var strm = response.GetResponseStream())
    using (var reader = new StreamReader(strm)){
        var data = reader.ReadToEnd();
        // data will be compressed
    }
}

Although this example specifies the Accept header to request JSON (as per my previous post on compression), this is not required and you can apply the Compress-data header to any request you make. Of course you should also examine the Content-Encoding header on the response to make sure you only decompress a response that is compressed. If the server ignores the Compress-data header (which will be the default case if the rewrite rule is missing or fails) you will get back uncompressed data.

Windows Phone 7 Sessions at TechEd Australia with Prizes

Windows Phone 7 Sessions at TechEd Australia with Prizes

As a reminder – come check out my two sessions at TechEd Australia. The Windows Phone sessions will have a number of giveaways including three copies of the Professional Visual Studio 210and two MSN Subscriptions.

DEV354     Shake, Rattle and Roll with Windows Phone 7
Thursday 09:45 – 11:00 : Breakout Session : Nick Randolph : 300

What distinguishes a Windows Phone 7 application from a regular desktop application is that it can make use of the features of the phone. In this session you’ll learn how to initiate tasks to capture photos from the camera, save a phone number, make a call and send an sms. The hardware integration goes much further with built in support for an accelerometer and FM radio tuner. When combined with the rich media aspects of Silverlight on the device, your Windows Phone 7 application will be set to keep you rocking all night long. .

DEV356     Advanced Windows Phone Services
Thursday 17:00 – 18:15 : Breakout Session : Nick Randolph : 300

Building Windows Phone 7 applications is all about combining the power of Silverlight on the device with services in the cloud. You can offload long running processes to a worker process hosted in Windows Azure, and receive a push notification when it completes. Your application can also leverage the location services to provide more context rich information. This session walks through how you can consumer a number of cloud-based services such as Messenger Connect, Windows Azure storage and OData WCF Data Services from within your Windows Phone 7 application. Of course, this wouldn’t be complete without the mandatory discussion on how to handle connectivity issues, such as caching and synchronization.

Windows Phone 7 and Image Overlays

Windows Phone 7 and Image Overlays

If you’ve taken a read through the interaction and design guidelines that Microsoft has published on building for Windows Phone 7, or if you’ve listened to some of the recordings from the recent developers days, you may have picked up on a little trick that they use on the Start screen that you might want to take advantage of. On the Start screen the text on the tiles is white but what’s interesting is that no matter what you set the background image to, the text is always readable. How do they do this, well they apply an overlay to the image before applying the text. Depending on whether you are using white (light) or black (dark) you will use either a light or dark overlay.

Let’s look at what happens if you don’t apply an overlay. The following image contains a dark image (ie the TV on the left) and a light image (ie the modem on the right). The top row has text in white, whilst the bottom has text in black. As you can see white text on a dark image works well, as does black text on a light image. One option would be to do some fancy analysis of the image and then determine what color text to use – this is both requires a lot of precious cycles and ends up with a non-uniform (aka messy) interface.

lightdark

The other alternative is to pick either white or black for the text and then apply an appropriate overlay to the images. In the following image we’ve applied a 20% black overlay to the top row (making the white text readable on both images) and a 20% white overlay to the bottom row (making the black text readable on both images).

lightdark_overlay

So, enough of the mocked up images, show me how to do this in XAML:

<Grid Width="200" Height="200" >
    <Image Source="{Binding SourceImage}" />
    <Border Background="Black" Opacity="0.2"/>
   <TextBlock Text="{Binding ImageTitle}" Foreground=”White”/>
</Grid>

Relatively straightforward – all we need to do is add a Black overlay (in this case I’ve used a Border element) with 20% opacity between the image itself and the White text.

Windows Phone 7: Monitoring Application Startup Performance

Windows Phone 7: Monitoring Application Startup Performance

If you’ve taken a look at the guidance for Windows Phone 7 applications you might be aware of the requirement for your application to startup within a certain period of time and for it to be responsive within another time period (I’m intentionally being vague he as I don’t want to be misquoted – you want the details, go checkout the marketplace requirements via http://developer.windowsphone.com). In addition to it being a requirement, you should always seek to minimise the startup time of your application. But during your development cycle, how do you ensure that the startup time of your application doesn’t slowly creep up? If you get to the end of the development and realise that your application takes a minute to load, you’re going to have to do a lot of work to cut this back to an acceptable level.

The answer to this question is to have a way to automatically time how long your application takes to launch. Of course you’d want to run this multiple times to get an average startup time. The Windows Phone emulator supports automation which you can use to deploy and launch your application. All you need is a way to start a timer before launching your application and then for it to stop when the application is launched.

Let’s take a console application and use that to deploy and launch our Windows Phone application. We can start a StopWatch before we launch the application but how are we going to know when to stop it? One way would be to simply stop the clock when the Launch() method returns. Unfortunately this probably won’t give us the flexibility we need to be able to record how long it takes for the application to be responsive. What we need is a way for the application itself to indicate that it has finished loading.

To solve this we add a simple WCF Service to our console application. The Windows Phone application will call this service to let it know that startup is complete. Although this will add a little overhead to the startup time itself, because we are really only interested in the regression analysis of the startup time (ie how it varies over time) this isn’t important. To make it easy to add and remove this functionality from your application  I’ve moved the service reference into a separate assembly.

The steps for measuring startup time for your application:

– Add a reference to BuiltToRoam.StartupTime.dll to your Windows Phone application
– Add the ServiceReference.ClientConfig file to your Windows Phone application which includes the BasicHttpBinding_IStartupTimeService endpoint information
– Call Startup.EndStartupTimer when your application has finished loading. For example in the Loaded event handler:

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e){
    BuiltToRoam.StartupTime.Startup.EndStartupTimer();
}

– Update the ProductId, XAPFileName and AppIconFileName settings in the app.config file of the BuiltToRoam.StartupTimeRunner console application to match your Windows Phone application.

<setting name="ProductId" serializeAs="String">
    <value>b6e9b714-2d78-4ce7-8d34-b2eb9e7b9fb7</value>
</setting>
<setting name="XAPFileName" serializeAs="String">
    <value>……TestApplicationBinDebugTestApplication.xap</value>
</setting>
<setting name="AppIconFileName" serializeAs="String">
    <value>……TestApplicationApplicationIcon.png</value>
</setting>

NB: The ProductId comes from the WMAppManifest.xml file under the Properties node in your Windows Phone application.

– Run the BuiltToRoam.StartupTimeRunner application

Output

When you run the StartupTimeRunner you should see a console window launched showing the progress of the runner. It will launch the emulator and then deploy your XAP file to it (Assuming you got the path right). Once deployed it will attempt to launch your application 20 times (this can be adjusted in the app.config file too), each time recording how long it takes to start (see image for sample output).

image

Once it has finished it will give you an average startup time. As you build out your application I’d suggest that you periodically run this to make sure you aren’t significantly lengthening the startup time.

The Code

Ok, so I guess you want to see how this works. Well I’ll leave you to go through the details but the bulk of it is in the Main method of the console application which is as follows:

static AutoResetEvent endTestRunEvent = new AutoResetEvent(false);
static void Main(string[] args){
    Guid applicationGuid = Properties.Settings.Default.ProductId;
    Console.WriteLine("Application Id: " + applicationGuid);
    string xapFile = Properties.Settings.Default.XAPFileName;
    Console.WriteLine("XAP Filename: " + xapFile);
    if (!File.Exists(Path.Combine(Environment.CurrentDirectory, xapFile))){
        Console.WriteLine("Unable to locate XAP file. Press Enter to exit");
        Console.ReadLine();
        return;
    }
    string iconFile = Properties.Settings.Default.AppIconFileName;
    Console.WriteLine("Application Icon Filename: " + iconFile);
    if (!File.Exists(Path.Combine(Environment.CurrentDirectory, iconFile))){
        Console.WriteLine("Unable to locate Icon file. Press Enter to exit");
        Console.ReadLine();
        return;
    }

    DatastoreManager dsmgrObj = new DatastoreManager(1033);
    Platform WP7SDK = dsmgrObj.GetPlatforms().Single(p => p.Name == "Windows Phone 7");

    Device device = WP7SDK.GetDevices().Single(d => d.Name == "Windows Phone 7 Emulator");

    // Use the following if you want to retrieve a reference to the actual device
    // Device device = WP7SDK.GetDevices().Single(d => d.Name == "Windows Phone 7 Device");

    using (ServiceHost host = new ServiceHost(typeof(StartupTimeService))){
        host.Open();
        Console.WriteLine("Connecting to Windows Phone 7 Emulator/Device…");
        try{
            device.Connect();
            Console.WriteLine("Windows Phone 7 Emulator/Device Connected…");

            device.InstallApplication(applicationGuid, iconFile, xapFile);

            Stopwatch sw = new Stopwatch();
            List<long> startupTimes = new List<long>();
            var exiting = false;
            for (int i = 0; i < Properties.Settings.Default.StartupIterations; i++){
                sw.Restart();
                device.LaunchApplication(applicationGuid);
                if (endTestRunEvent.WaitOne(Properties.Settings.Default.StartupTimeout * 1000)){
                    sw.Stop();
                    startupTimes.Add(sw.ElapsedMilliseconds);
                    Console.WriteLine("Run " + i + " – Startup time(ms): " + sw.ElapsedMilliseconds.ToString());
                    device.TerminateApplication(applicationGuid);   
                }
                else{
                    Console.WriteLine("Unable to startup application within specified startup timeout. Press Enter to exit.");
                    Console.ReadLine();
                    exiting = true;
                    break;
                }
            }

            if (!exiting){
                var averageStartupTime = startupTimes.Average();
                Console.WriteLine("Average startup time (ms): " + averageStartupTime);
                Console.WriteLine("Press Enter to Exit");
                Console.ReadLine();
            }
            device.CleanupApplication(applicationGuid);
        }
        finally {
            device.Disconnect();
        }
        host.Close();
    }
}

public static void ApplicationStarted(){
    endTestRunEvent.Set();
}

Download Source Code

Windows Phone7 Wheel Control – Updated

Windows Phone7 Wheel Control – Updated

Update: The initial source and concept for this control was made available courtesy of FairFax as part of their investment into building applications for the Windows Phone platform.

Here is an update to the Wheel Control that I posted about previously. Big thanks to Clint Rutkas (Microsoft) of Monkey See, Monkey Buildfame for addressing a number of issues such as the flickering of items and the lack of flick scrolling.

Updated August 17 2010: Wheel Control

Perpetual Expression Blend Crashes

Perpetual Expression Blend Crashes

As part of building Windows Phone applications I’m forever flipping between Visual Studio and Expression Blend. Sometimes I encounter issues with Blend that it just can’t deal with and will simply self combust, giving me a text file crash stack. The most common cause is where I’ve accidentally crossed threads, resulting in the following:

System.UnauthorizedAccessException: Invalid cross-thread access.
   at MS.Internal.XcpImports.CheckThread()
   at MS.Internal.XcpImports.CreateObjectByTypeIndex(UInt32 typeIndex)
   at System.Windows.Threading.DispatcherTimer..ctor(UInt32 nativeTypeIndex)
   at System.Windows.Threading.DispatcherTimer..ctor()

Unfortunately the resolution isn’t that simple – I can fix the code ok, but the issue is that Blend won’t load the project again without crashing. This is because Blend uses a compiled version of the application to display the design surface. On startup it attempts to use the version that has already been built (in this case it includes the faulty code that causes the exception) so it crashes again. Unlike Visual Studio that handles this gracefully, there is no capability within Blend to for example open the project without any files open….

The solution: Delete the bin/obj folders from your application and open in Blend (of course after fixing the code issue). Blend will then be forced to do a new build of the application that should no longer raise the exception.

Windows Phone 7 at TechEd Australia

Windows Phone 7 at TechEd Australia

hearmespeakteched2010

With TechEd Australia just over a week away I thought I’d give a quick run down of the Windows Phone 7 sessions that you should head along to. There are six sessions at TechEd Australia this year making up the Windows Phone virtual track. If you want to get started before the event, you can start with the beta of the Windows Phone tools is currently available, and can be downloaded from http://developer.windowsphone.com.  Anyway, here are the sessions spread over four days, starting with an interactive theatre session during the welcome reception.

 

Tuesday

THGTU03     Dynamics CRM Online and Windows Phone 7: A duet made in the cloud
19:00 – 19:30 : Interactive Theatre Session : Dimaz Pramudya : 300

Dimaz Pramudya will do a quick lap around building WP7 application that integrates with Dynamics CRM Online. The demo will show how easy it is to build a service that pulls down the data from CRM Online and automatically convert them to JSON format for consumption within the WP7 app. There will be few interesting UX tips and tricks shown during the demo.

Wednesday

DEV252     Building Windows Phone 7 Applications in Silverlight
09:45 – 11:00 : Breakout Session : Peter Torr : 200

Consistent and predictable user experiences are a core feature of Windows Phone 7, and the application model is a key piece of the puzzle. Windows Phone 7 represents a new approach to smartphone UI, so come and learn how to build innovative new applications that feel right at home on the phone by taking advantage of panoramic views, page-based navigation, tombstoning, and more.

DEV359     From Phone Zero to Phone Hero in 60 minutes
17:00 – 18:15 : Breakout Session : Chris Auld, Chris Klug : 300

Join Chris Squared (Chris Auld & Chris Klug) from Intergen as they build a real Windows Phone 7 app from scratch in 60 minutes. This is a hard core, dual data projector, coding marathon. Chris and Chris will build a Windows Phone 7 series app including Windows Azure hosted push notifications, a rich Silverlight UI and partner integration. You’ll see how to take an idea from concept to the Windows Phone Marketplace in just an hour. In other words, not your general Hello World application.

 

Thursday

DEV354     Shake, Rattle and Roll with Windows Phone 7
09:45 – 11:00 : Breakout Session : Nick Randolph : 300

What distinguishes a Windows Phone 7 application from a regular desktop application is that it can make use of the features of the phone. In this session you’ll learn how to initiate tasks to capture photos from the camera, save a phone number, make a call and send an sms. The hardware integration goes much further with built in support for an accelerometer and FM radio tuner. When combined with the rich media aspects of Silverlight on the device, your Windows Phone 7 application will be set to keep you rocking all night long. .

DEV356     Advanced Windows Phone Services
17:00 – 18:15 : Breakout Session : Nick Randolph : 300

Building Windows Phone 7 applications is all about combining the power of Silverlight on the device with services in the cloud. You can offload long running processes to a worker process hosted in Windows Azure, and receive a push notification when it completes. Your application can also leverage the location services to provide more context rich information. This session walks through how you can consumer a number of cloud-based services such as Messenger Connect, Windows Azure storage and OData WCF Data Services from within your Windows Phone 7 application. Of course, this wouldn’t be complete without the mandatory discussion on how to handle connectivity issues, such as caching and synchronization.

 

Friday

DEV358     Windows Phone 7 + XNA. Bringing it all together for Games Development.
09:45 – 11:00 : Breakout Session : Chris Walsh : 200

Windows Phone 7 + XNA. The partnership you’ve been missing for Game Development. The XNA development platform has been around for years. First started off enabling developers to write games for the Xbox, Xbox360 & Zune devices. Now Microsoft have brought the amazing platform to Windows Phone 7. It enables developers to build extremely powerful and top class games. In this session, Chris will walk you through the constructs of the game template, and show you how to port the classic game in “Pong” to Windows Phone 7 using XNA.

Windows Phone 7 Beta: Go Back…. No I mean the other Back

Windows Phone 7 Beta: Go Back…. No I mean the other Back

Having spent quite a bit of time working with Windows Phone 7 on both a real device and the emulator I’ve come to the conclusion that the Back button is awesome! Now when I pick up a lesser device, that for example only has a home key, I get frustrated that I can’t go back to the application I was just in, or cancel an action that I didn’t mean.

This said, there are some times when the behavior of the Back button gets in the way. The most frustrating of these is Internet Explorer. The Back button handles two different types of Back-stacks: Firstly there is the application back-stack. This is the stack of applications that have been opened. For example if you open App1, followed by App2, App3 and App4, you’ll have a back-stack that consists of Start | App1 | App2 | App3 | Start | App4 (note that the Start appears twice in the list, once immediately before the last application on the stack, and then again at the beginning of the stack). As you press the Back button you will navigate back through the stack, progressively closing the applications, so starting at App4 you would see the Start, App3, App2, App1 and then Start again.

The second type of Back-stack is within the individual applications, and by default is made up of the pages that have been navigated to in that instance of the application. I say by default because the Back button is the one hardware button that an application developer can intercept and handle within the application. This means that the application can maintain a completely custom Back-stack. For example, within Internet Explorer, rather than opening/closing pages, the Back-stack consists of the websites that have been navigated to. As you can guess, pressing the Back button within Internet Explorer is like pressing the Back button on any desktop browser, it takes you back through the browsing history.

Ok, so by now you might be able to see where my frustration lies…. Let’s combine these two Back-stacks and replace App3 with Internet Explorer, and let’s say that I was browsing for a couple of minutes and have visited three websites. The total Back-stack looks like this:

Start | App1 | App2 | IE (site1) | IE (site2) | IE (site3) | Start | App4

As you can see, the longer I spend browsing in IE, the larger the Back-stack is going to be, which is a royal pain if you want to empty the Back-stack, or you want to go back to App1 or App2.

So by now you might be thinking “quit your whinging, you can just press the Start button and then click on App1 or App2.” But here is the issue with that – because we have a “Consistent Start” experience, whenever we click on an application from the Start it will always relaunch the application as if it wasn’t already running. This means that if the application was previously in the background (or Tombstoned) it will be terminated and restarted. Alternatively, clicking Back to get back to a running application will return the application to the foreground in the state it was in (relaunching if Tombstoned but automatically navigating to the correct page etc).

Is there a work around for this? In Internet Explorer, there is – you can open a new tab, and then clicking the Back button will take you to the previous application. For other applications, there currently isn’t a general solution to get around this issue.

Could there be a work around in future versions? Well if you look at the iphone 4 model where you can double-tap the home key to bring up the list of running applications, this could easily be applied to Windows Phone 7. You could get a list of applications that are suspended/tombstoned and be able to select one to bring to the foreground. The interesting thing there is what this means for the Back-stack – does the selected application move to the front of the Back-stack (immediate thoughts would be yes, but what about if you open the CameraCaptureTask and then try to bring the calling application to the foreground?). I definitely think having the ability to swap between running applications is a must for v.next.

Windows Phone 7 Beta: How do I save an image to the Pictures Hub

Windows Phone 7 Beta: How do I save an image to the Pictures Hub

If you started playing with the Windows Phone 7 beta you may be aware that the only storage you have to play with is isolated storage. However, what happens if you take a photo in your application (ie using the CameraCaptureTask) that you then want to be available in other applications. Clearly by the virtue of it being “isolated” you can’t simply share access to isolated storage. Instead what you can do is to save the image to the Pictures Hub.

Let’s start by taking a photo:

CameraCaptureTask camera = new CameraCaptureTask();
public MainPage(){
    InitializeComponent();

    camera.Completed += new EventHandler<PhotoResult>(camera_Completed);
}

byte[] imageBits;
void camera_Completed(object sender, PhotoResult e){
    imageBits = new byte[(int)e.ChosenPhoto.Length];
    e.ChosenPhoto.Read(imageBits, 0, imageBits.Length);
    e.ChosenPhoto.Seek(0, System.IO.SeekOrigin.Begin);

    var bitmapImage = PictureDecoder.DecodeJpeg(e.ChosenPhoto);
    this.PhotoImage.Source = bitmapImage;
}

private void TakePictureButton_Click(object sender, RoutedEventArgs e){
    camera.Show();
}

Now for the interesting part. Let’s add this to the Pictures hub. We do this by creating an instance of the MediaLibrary class (you will need to add a reference to Microsoft.Xna.Framework.dll to your project). Then you simply call SavePicture, passing in either a byte array (in our case imageBits) or an image stream.

private void SaveToHubButton_Click(object sender, RoutedEventArgs e){
    var library = new MediaLibrary();
    library.SavePicture(“My Photo”,imageBits);   
}

And that’s it for saving. You can also view all saved images via the SavedPictures property on the MediaLibrary instance.

private void SavedPicturesButton_Click(object sender, RoutedEventArgs e){
    var library = new MediaLibrary();
    var photos = (from p in library.SavedPictures
                    select new ImageWrapper(p)).ToArray();
    SavedPhotosList.ItemsSource = photos;
}

public class ImageWrapper{
    public Picture Picture { get; set; }

    public ImageWrapper(Picture picture){
        Picture = picture;
    }

    public ImageSource Image{
        get{
            var image = new WriteableBitmap(100,100);
            image.SetSource(Picture.GetThumbnail());
            return image;
        }
    }
}

You might be wondering why I’m wrapping the Picture in an ImageWrapper. This is so that I can easily data bind to a listbox. My xaml is the following:

<Grid x_Name=”ContentGrid” Grid.Row=”1″>
    <Button Content=”Take Picture” Height=”72″ HorizontalAlignment=”Left” Name=”TakePictureButton”
                   VerticalAlignment=”Top” Width=”293″ Click=”TakePictureButton_Click” />
    <Image Height=”135″ HorizontalAlignment=”Left” Margin=”314,6,0,0″ Name=”PhotoImage” Stretch=”Fill” 
                   VerticalAlignment=”Top” Width=”154″ />
    <Button Content=”Save to Pictures Hub” Height=”72″ HorizontalAlignment=”Left” Margin=”0,69,0,0″
                   Name=”SaveToHubButton” VerticalAlignment=”Top” Width=”293″ Click=”SaveToHubButton_Click” />
    <ListBox Height=”396″ HorizontalAlignment=”Left” Margin=”0,221,0,0″ Name=”SavedPhotosList”
                      VerticalAlignment=”Top” Width=”480″ >
        <ListBox.Resources>
            <DataTemplate x_Key=”ImageTemplate”>
                <Border Height=”100″ Width=”100″ Padding=”5″ >
                    <Image Source=”{Binding Image}”/>
                </Border>
            </DataTemplate>
        </ListBox.Resources>
        <ListBox.ItemTemplate>
            <StaticResource ResourceKey=”ImageTemplate”/>
        </ListBox.ItemTemplate>
    </ListBox>
    <Button Content=”Saved Pictures” Height=”72″ HorizontalAlignment=”Left” Margin=”0,143,0,0″ 
                    Name=”SavedPicturesButton” VerticalAlignment=”Top” Width=”293″ Click=”SavedPicturesButton_Click” />
</Grid>

Ok, so you might be wondering what this looks like in action…. (note that I’m using the hacked emulator build to do this so that you can see the pictures hub)

image

Across the top we have the stages of the application. Use clicks the Take Picture button that launches the camera capture task. When this returns the photo is applied to the image (top right of image three). The user clicks the Save to Pictures Hub button to save the image. Then when they click the Saved Pictures button the list of images in the Saved Pictures folder on the Pictures hub are displayed.

The bottom line illustrates where to find the images in the Pictures hub – All > Saved Pictures.

Windows Phone 7 MVVM Template for Visual Studio

Windows Phone 7 MVVM Template for Visual Studio

There are two ways to get this:

– The old slow way: http://visualstudiogallery.msdn.microsoft.com/en-us/5f8407ad-eb7c-42d9-872b-4ad8462b3e43

– Or via Visual Studio itself.

image

Open Visual Studio, select File > New Project, Search online templates for Windows Phone and off you go!

Windows Phone 7 Wheel Control

Windows Phone 7 Wheel Control

Update: The initial source and concept for this control was made available courtesy of FairFax as part of their investment into building applications for the Windows Phone platform.

If you’ve taken a look at either the hacked emulator build or a real Windows Phone 7 device you’ll notice that there are cases, such as selecting date or time, where they use a wheel-like control. It’s not the same as the iphone version which looks very 3d’ish. Instead they’ve gone for a very flat style in keeping with the rest of the device (as an aside if you’ve been wondering what “digitally authentic” means it essentially means don’t pretend that the screen is 3d. It’s not, so use 2d flat color buttons – check out the rest of the metro UI if you don’t believe me).

Yesterday I got a little side tracked and ended up re-skinning the ListBox to behave in a similar way to the wheel.

image

I’ve attached the source project which includes this sample application to show you how to use it. Feel free to consume and suggest improvements!

Windows Phone Wheel Control and Sample

System.ComponentModel.EditorBrowsable was written by idiots

System.ComponentModel.EditorBrowsable was written by idiots

This post is to remind myself that the EditorBrowsableAttribute was written in such a way that it isn’t really usable by anyone other than framework developers. Essentially this attribute is supposed to provide Visual Studio with a hint as to whether a property/method/field/class/struct etc should be visible in Intellisense or in the visual designers. In my case I wanted to hide certain properties from intellisense, not because they couldn’t be used but because in most cases there is a better way to do the task (I’m not hear to argue whether this is the correct way to handle this or not). You’d expect the following to hide MyProperty from intellisense.

[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public int MyProperty { get; set; }

Unfortunately there are a couple of conditions that need to be met in order for this to work.

1) The item that you’re applying the EditorBrowsable attribute to has to be declared in a separate assembly from the one you’re consuming it in.

2) It isn’t enough to just place the item in another project within the same Visual Studio solution – it has to be an assembly reference (ie not a project reference).

The second point is the one I don’t get – why doesn’t this work for project references. The work around is to reference the built version of the assemblies, but that introduces all manner of issues with Visual Studio and deployment. Honestly, who designed this stuff?

Windows Phone 7 Beta: My Application Won’t Start After Renaming Project

Windows Phone 7 Beta: My Application Won’t Start After Renaming Project

Yesterday I lost an hour or so tracking down a bug whereby I hit F5/Run in Visual Studio to debug a Windows Phone application. I’d been happily doing this all morning, then I decided to rename my application. You’d have thought this was just a matter of renaming the project, assembly name, default namespace, class/xaml namespaces, xap file and assembly information (to make sure they’re all consistent, rather than because they’re necessarily required in order to rename the application). It turns out that I’d completely forgotten to set the Startup object to the new xap file. We’ll it wasn’t all my fault – I’ve since then created a new project, changed the namespace in app.xaml, app.xaml.cs, mainpage.xaml and mainpage.xaml.cs and tried (unsuccessfully) to get Visual Studio to let me select NewApplication.App to be the startup object (as you can see in this image). Remember that it’s is the class (typically App) that inherits from Application that is the startup object for a Windows Phone application.

image

The symptoms (and this is true if the Startup object is set to “(not set)” or to an incorrect app name) is that Visual Studio deploys the application but when it goes to invoke the application it fails, so Visual Studio returns to the not running state (no errors!). If you attempt to run the application on the emulator you get the same thing – application goes to launch then crashes (again no error message/warning).

The fix is quite simple – Build the Windows Phone application (which shouldn’t have any errors, although in my opinion there should be to point out that the startup object doesn’t match a valid class), then Unload the project (by right-clicking the project and selecting Unload Project as the image below suggests). All you need to do now is to reload the project by again right-clicking the project node and selecting Reload Project.

.image

If you open up the project properties page you should be able to select the correctly named app as the startup object.

OData Synchronization with WCF Data Services

OData Synchronization with WCF Data Services

Over the last couple of months I’ve been doing quite a bit of work with OData, being one of the easiest ways to consume data with a Windows Phone application. One of the things that has frustrated me is that there isn’t any built in synchronization components for Windows Phone (there isn’t any database persist technology either but I won’t digress…). However, because of the way that OData exposes data, it isn’t too difficult to come up with scheme for doing synchronization.

Background

Before we get into how I’ve been doing data synchronization over OData I want to take this opportunity to point out that there are different approaches to synchronization. If you look at technologies such as RDA and Merge Replication these are clearly targeting the synchronization of relational data. Change tracking is typically at a per row level for each table that you choose to synchronize. Alternatively if you take Sync Framework this takes a much more generic approach to synchronization where by you could be synchronizing anything whether they be files, rss content or data. For most data driven applications this isn’t particularly useful since all you want to be able to do is say “synchronize this data set between the server and client”. You end up using the default sql providers in which case you might as well have just used Merge Replication.

One of the challenges of building a good synchronization strategy is getting the granularity of change tracking right. I don’t mean change tracking at the database level (after all that can be done by simply enabling change tracking on Sql Server 2008), I mean change tracking between the client and server. Take the example of a Person entity which can be broken down into a Peron table with joins to an Address table (1 to many, since they might have a work and home address).

1) Table/Row Change Tracking

You could track changes on both the Person and Address tables, in which case the client could request all changes to the Person and Address table since the last sync.

Pro: Change sets are small as only the data changed is synchronized (eg just the Address data if a change to an Address)

Con: More change tracking data (you need to track last updated timestamp and deleted flag as a minimum)

2) Entity Change Tracking

Alternatively you could track changes at just the Person table level. In this case changes to any Address would result in the corresponding Person table too.

Pro: Less change tracking data (you only need to track at the entity level, in this case the Person level)

Cons: Change sets are larger as the entire entity needs to be synchronized (eg if an Address changes, the entire Person entity needs to be synchronized).

If you decide to go with the first option then you should consider either Sync Framework or Merge Replication (for platforms where it is supported). Alternatively, if you don’t have a client side relational database (eg Silverlight or Windows Phone) then you might want to consider synchronizing whole entities and tracking at the entity level.

Change Tracking with OData

Ok, lets return to doing synchronization with OData. There are a number of different strategies for tracking changes to data on the server. As mentioned earlier you could go with SQL Server Change Tracking which once enabled allows you to request changes to a table between two timestamps. For simplicity we’re going to go with a much simpler approach of having two additional fields, LastUpdated and IsDeleted, on the tables that we want to track changes on. This gives us the flexibility of either tracking on a table-by-table basis (1) or at an entity level (2). LastUpdated is a server date stamp indicating when the data was last modified. We’re not tracking all changes sets, only the cumulative effect of all changes – in other words if you do multiple changes to an entity they will all get synchronized as a single change based on the LastUpdated value. The IsDeleted boolean value is required to ensure clients get notified when an entity is deleted. The upshot is that you should never actually delete an entity from the database that is synchronized because you don’t know whether a client still has that entity in their offline cache.

Publishing OData

We’re going to continue with the previous example of a Person entity which can have a number of associated addresses. The basic data model would look like ( Person > PersonId, Name; Address> AddressId, PersonId, StreetAddress):

image

To enable change tracking you need to add the LastUpdated and IsDeleted fields. You can either add these fields to both tables (option 1 from earlier) or just the Person table (option 2 since the Peron entity is effectively a row in the Person table coupled with the associated rows from the Address table).

image image
The next thing to do is to start building out the server components:

– New project called PeopleServer based on the ASP.NET Empty Web Application project template

– Add a new item called PeopleModel.edmx based on the ADO.NET Entity Data Model. Follow the steps to setup a connection to your database and add the Person and Address tables to your model.

image

– Add a new item called PeopleDataService.svc based on the WCF Data Service item template. Update the template to use the MyPeopleEntities (this name may vary depending on what you called your entity set – open the edmx file, and look at the Properties window. This name corresponds to the Entity Container Name)

public class PeopleDataService : DataService<MyPeopleEntities>
{
    public static void InitializeService(DataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("*", EntitySetRights.All);
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    }
}

Server Change Tracking

This is enough to publish your data using odata, allowing read/write access to all the entities (ie both Person and Address tables). However, it doesn’t enforce any behavior regarding setting the LastUpdated or the IsDeleted flag. The LastUpdated should be set to the server time of any updates (rather than a client date stamp) and the IsDeleted flag should be set to true instead of actually deleting an entity. We can add this functionality in the SaveChanges method on the MyPeopleEntities. Rather than having to write code for each type of entity we want to track changes for, we’ll also extend our entities to implement the IEntityTracking interface.

– Add a new item called IEntityTracking.cs based on the Interface item template. This will define the LastUpdated and IsDeleted properties.

public interface IEntityTracking
{
    DateTime LastUpdated { get; set; }
    bool IsDeleted { get; set; }
}

– Add a new item called PeopleModel.Custom.cs based on the Code File item template. Extend the Person partial class to implement the IEntityTracking interface (note that you don’t need to add any properties since there are already properties which match those required by the interface). We’re only going to track changes against the whole Person entity here but if you want to track changes at the Address level as well you can extend that class with this interface too.

public partial class Person : IEntityTracking
{
}
    
public partial class MyPeopleEntities
{
    public override int SaveChanges(SaveOptions options)
    {
        var changes = this.ObjectStateManager.GetObjectStateEntries(
                                 EntityState.Modified |
                                 EntityState.Added |
                                 EntityState.Deleted);
        foreach (var change in changes)
        {
            var entity = change.Entity as IEntityTracking;
            if (entity != null)
            {
                if (change.State == EntityState.Deleted)
                {
                    change.ChangeState(EntityState.Modified);
                    entity.IsDeleted = true;
                }
                entity.LastUpdated = DateTime.Now;
            }
        }

        return base.SaveChanges(options);
    }
}

In the SaveChanges method you simply iterate through the changes, detect whether the item being modified implements IEntityTracking. If it does you reverse any deletion attempts (replacing it with setting the IsDeleted flag to true) and set the LastUpdated date to the current server time.

Consuming The Data

OK, we done configuring the server side. Let’s look at how you consume this from the client. Rather than going through an actual client implementation (which will vary depending on the technology stack you’re using). I’ll walk through this using Fiddler to send GET/POST/PUT/DELETE messages.

Let’s start by  retrieving all the entries in the Person table. The following image shows how to build a simple GET request in Fiddler. Note that we’re specifying that we want the results in JSON (Set the header “Accept: application/json”). You have to love ADO.NET Entity Framework – when you have a table called Person, it knows that the plural (ie the set name) should be People!

image

Ok, so what does the response look like:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Wed, 04 Aug 2010 04:39:12 GMT
X-AspNet-Version: 4.0.30319
DataServiceVersion: 1.0;
Content-Length: 3611
Cache-Control: no-cache
Content-Type: application/json;charset=utf-8
Connection: Close

{“d” : [{
“__metadata”: {“uri”: “<a href=”http://localhost:16896/PeopleDataService.svc/People(guid’2b64d1ca-5802-4937-8134-0ad978415117′)””>http://localhost:16896/PeopleDataService.svc/People(guid’2b64d1ca-5802-4937-8134-0ad978415117′)”</a>, “type”: “MyPeopleModel.Person”
}, “PersonId”: “2b64d1ca-5802-4937-8134-0ad978415117”, “Name”: “Mary”, “LastUpdated”: “/Date(1280932624977)/”, “IsDeleted”: false, “Addresses”: {
“__deferred”: {
“uri”: “<a href=”http://localhost:16896/PeopleDataService.svc/People(guid’2b64d1ca-5802-4937-8134-0ad978415117′)/Addresses””>http://localhost:16896/PeopleDataService.svc/People(guid’2b64d1ca-5802-4937-8134-0ad978415117′)/Addresses”</a>}}}, {
“__metadata”: {
“uri”: “<a href=”http://localhost:16896/PeopleDataService.svc/People(guid’f1c245d0-2262-43e0-b78b-3086068a72fa’)””>http://localhost:16896/PeopleDataService.svc/People(guid’f1c245d0-2262-43e0-b78b-3086068a72fa’)”</a>, “type”: “MyPeopleModel.Person”
}, “PersonId”: “f1c245d0-2262-43e0-b78b-3086068a72fa”, “Name”: “Ken”, “LastUpdated”: “/Date(1280932635510)/”, “IsDeleted”: false, “Addresses”: {
“__deferred”: {
“uri”: “<a href=”http://localhost:16896/PeopleDataService.svc/People(guid’f1c245d0-2262-43e0-b78b-3086068a72fa’)/Addresses””>http://localhost:16896/PeopleDataService.svc/People(guid’f1c245d0-2262-43e0-b78b-3086068a72fa’)/Addresses”</a>
}…

Hmmm, that’s not particularly easy to read. The JSON Viewer plugin for Fiddler makes it much easier to see what’s going on.

image

As you can see the data returned is a collection of objects that represent the data in the Person table. The __medadata node specifies the uri of the individual entities, which in this case specifies the Person to return by the PersonId (which is a Guid). Unfortunately this isn’t all the information about the Person entities since it doesn’t include the Address information. At the end of the Person object there is a node called Addresses but it has a _deferred node. If you follow that you can access the collection of addresses associated with the Person. This requires further round trips in order to get the data for a single entity. There is a work around, which is to include the $expand parameter in the query:

http://localhost:16896/PeopleDataService.svc/People?$expand=Addresses

image

You should note that the value of the $expand is the name of the Navigation property (see the entity model that you added to your project). Some other points to note:

– If your Person has other linked tables (eg PhoneNumber) you can expand multiple tables by separating them with a comma.

http://localhost:16896/PeopleDataService.svc/People?$expand=Addresses,PhoneNumbers

– If the Address table links to another table (eg AddressType) you can expand to that table as well by adding a slash.

http://localhost:16896/PeopleDataService.svc/People?$expand=Addresses/AddressType,PhoneNumbers

Filtering the Data For Synchronization

Coming back to how we use this to do synchronization. Well the basic principle of synchronization is to download changes from the server and upload changes you’ve made locally. The changes to download should be all entities that have changed between the last time you sync (which might be never) and now. To do this you can apply the $filter parameter to the query. For the initial sync you should pick sometime a long time in the past:

http://localhost:16896/PeopleDataService.svc/People?$expand=Addresses&filter=(LastUpdated%20gt%20datetime’1900-00-00T00:00:00.0000000′)

The entities that are returned will determine what the next filter value is. Select the most recent LastUpdated value for the entities received and use this as the next filter value.

Now, if your database is of a reasonable size you will probably want to employ paging and rather than allowing the client to specify this you probably want to enforce this on the server. You can do this by updating the InitializeService method on your data service:

public static void InitializeService(DataServiceConfiguration config)
{
    config.SetEntitySetAccessRule("*", EntitySetRights.All);
    config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    config.SetEntitySetPageSize("People", 50);
}

Here we’re applying paging on the People entity set. You can apply it to all entities by using the “*” instead of “People”. This introduces some extra work that you have to do on the client. If there are multiple pages then you will need to follow the “__next” link that will be included in the returned result set.

image

If you want some indication of how many entities there are in the total change set (for example if you want to track percentage complete) you can request that the total number of items is included across all pages. This is done by including the $inlinecount=allpages parameter.

http://localhost:16896/PeopleDataService.svc/People?$expand=Addresses&filter=(LastUpdated%20gt%20datetime’1900-00-00T00:00:00.0000000′)&$inlinecount=allpages

image

Saving Changes

If you want to save changes back to the server you need to issue a POST (new entity), PUT (modified) or DELETE (you guessed it – delete) request to the data service. Here’s an example of each:

Modify an item by issuing a PUT to the address specified in the __metadata.uri element.

PUT http://localhost:16896/PeopleDataService.svc/People(guid’2b64d1ca-5802-4937-8134-0ad978415117′) HTTP/1.1
User-Agent: Fiddler
Host: localhost:16896
Accept: application/json
Content-Type: application/json
Content-Length: 71

{ “PersonId”: “2b64d1ca-5802-4937-8134-0ad978415117”, “Name”: “Mary”}

Insert an item by issuing a POST to the entity set url (

POST http://localhost:16896/PeopleDataService.svc/People HTTP/1.1
Accept: application/json
Content-Type: application/json
Host: localhost:16896
Content-Length: 77

{ “PersonId”: “C5AC406D-2278-48D7-91BF-BDFF53ECD9F6”, “Name”: “New Person”}

Delete an item by issuing a DELETE to the address specified in the __metadata.uri element

DELETE http://localhost:16896/PeopleDataService.svc/People(guid’2b64d1ca-5802-4937-8134-0ad978415117′) HTTP/1.1
Accept: application/json
Host: localhost:16896
Content-Length: 2

In the case of the delete this request should return a valid success response (ie a 204) but in fact it won’t have deleted the item, only set the IsDeleted flag to true.

Completing the Loop

Bringing this all together you should iterate over the download-upload cycle until the client and server are in sync (ie no changes pending in either direction).

Hopefully this will have given you an idea of how to perform synchronization using odata in a way that is not reliant on a particular client technology. Feel free to post comments on how you think this could be improved or if you see any issues with this approach.