Windows Phone Developer Tip: Navigation Events and Tombstoning

computer-geek-gets-fitting-tombstone_1One of the developer features that I think all Windows Phone developers should be supporting is tombstoning.  If you are writing Windows Phone apps and are not supporting Tombstoning then please do just makes UX better which makes happy customers!  If you have not implemented tombstoning in your app, make sure you you read the Windows Phone Execution Model which has details on this.

So what is the tip?  First some background to give some context.  We built a picture viewer for one of our apps, and to conserve memory on the Page.OnNavigateFrom we dispose of a bunch of objects in the view model as we don’t want those lingering around.  Our primary concern was WriteableBitmaps.

The issue was we were cleaning up objects in the Page.OnNavigateFrom method and cleared our objects before we had a chance to save any state in the PhoneApplicationService.State.  This is because Page.OnNavigateFrom was called before the PhoneApplicationService.Deactived event was fired.  So to work around this we did the following

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
    if (!e.Uri.ToString().Equals("app://external/"))
    {
        //Clean up only if not tombstoning
    }
    base.OnNavigatedFrom(e);
}

This way our PhoneApplicationService.Deactived event handler can save any state required.

The key take away is the Uri your app navigates to when being tombstoned and that is “app://external/”  This is the Uri you need to look for to see if you are being tombstoned before cleaning up any view models or objects.

Again, this is relevant in the app we where building and the code above may not fit your scenario exactly.  But the “app://external/” Uri may be useful at some point when developing for Windows Phone!  And you get this Uri if you are using Windows Phone Mango or Nodo.

Disposable SolidBrush for Compact Framework 1.0



I’ve been working on a Compact Framework 1.0 project for a customer and doing some custom control work (yes CF1.0 even though CF3.5 is coming).  I’ve done a lot of custom controls using Compact Framework 2.0 and have gotten used to the new methods/properties available so going back to 1.0 takes a little bit of getting used to.


That said, I was using a SolidBrush and in CF1.0 it does not implement IDisposable whereas in CF2.0 it does.  At first I ended up with code like this.

SolidBrush brush = new SolidBrush(Color.Black);
//Drawing code here
brush.Dispose();

This will work, but when you have a lot of brushes you are creating it also starts creating a lot of code.  You are probably thinking why not just use the using statment since SolidBrush has a Dispose() method like this.

using (SolidBrush brush = new SolidBrush(Color.Black))
//Drawing code here

Although in CF1.0 SolidBrush does have a Dispose() method, it does not implement IDisposable so using the using statement is out.  So how do you overcome this?  I created a ‘wrapper’ to the SolidBrush.  Here is an implementation:

public class SolidBrush2 : IDisposable
{
private SolidBrush brush;

public SolidBrush2(Color color)
{
this.brush = new SolidBrush(color);
}

public SolidBrush Brush
{
get
{
return brush;
}
}

#region IDisposable Members

public void Dispose()
{
brush.Dispose();
}

#endregion
}


 


You’ll notice a few things.  First, our SolidBrush2 class implements IDisposable. Second, we have a private SolidBrush variable that holds the actual SolidBrush object used for drawing.  With this class we can now use using like this:

using (SolidBrush2 brush = new SolidBrush2(Color.Black))
//Drawing code here

So we eliminated the manual calling of Dispose() by using the using statement (for another example of using statement see here).  Great, but I still wasn’t happy.  With the SolidBrush2 implementation we would still have code like this:

using (SolidBrush2 brush = new SolidBrush2(Color.Black))
e.Graphics.DrawString(“Test”, this.Font, brush.Brush, 1, 1);

Notice the brush.Brush in the DrawString() method?  If the customer would ever update to CF2.0 (which I’m trying to get them to do) there will be a lot of code to change. If this does happen, first SolidBrush2 would be changed to SolidBrush. Then all the brush.Brush statements would have to be changed to just brush.  This means grunt work for me and wasted money for the customer (since they would pay me for the grunt work). 


implicit operator to the resuce!!  By adding an implicit operator to our SolidBrush2 class we can return the internal SolidBrush member variable.

public static implicit operator SolidBrush(SolidBrush2 sb2)
{
return sb2.Brush;
}

And when using our SolidBrush2 in a using statement we can get rid of the ‘.Brush’ like so:

using (SolidBrush2 brush = new SolidBrush2(Color.Black))
e.Graphics.DrawString(“Test”, this.Font, brush, 1, 1);

The results, cleaner code, less grunt work for me if the customer decides to upgrade CF2.0, and saved money for the customer since all I would have to do is a Find&Replace on SolidBrush2 to SolidBrush.


Here is the final SolidBrush2 implementation:

public class SolidBrush2 : IDisposable
{
private SolidBrush brush;

public SolidBrush2(Color color)
{
this.brush = new SolidBrush(color);
}

public static implicit operator SolidBrush(SolidBrush2 sb2)
{
return sb2.Brush;
}

public SolidBrush Brush
{
get
{
return brush;
}
}

#region IDisposable Members

public void Dispose()
{
brush.Dispose();
}

#endregion
}

Enjoy!

C# Event Accessors

I’m working on a project where a customer needs some custom controls.  One of the requirements is to have a UserControl contain a TextBox and a Button and to expose an event that will be raised when the button is clicked.  Easy enough, but to enhance the design time experience instead of adding a ButtonClick event for example, I added the following to the UserControl


public new event EventHandler Click
{
   add
   {
      lock (m_button)
      {
         m_button.Click +=
value;
      }
   }
   remove
   {
      lock (m_button)
      {
         m_button.Click -=
value;
      }
   }
}


What this does is instead of adding the EventHandler to the UserControl.Click event, I add it straight to the m_button.Click event.  Not terribly complicated but gives a better design time experience and avoids creating a new event to expose.


For more info on declaring events see here.