← About Jeff

WP7 Panorama: Smoothly fading the background (and enabling fading when changing, too)

November 14, 2010

I’ve heard a number of conversations with developers about wanting to smoothly fade in background image changes within the Panorama control that ships in the Windows Phone 7 Developer Tools.

I spent the better part of this rainy Seattle Sunday looking into this. I actually had a conversation with the famed Kelly Sommers (@kellabyte) a few months ago about implementing a Panorama whose Background was automatically set to the daily Bing image, and was recently inspired by an internal developer discussion at Microsoft.

Here’s a video of the sample project where I was able to do just that, and more! The control takes care of smoothly fading any background property change, and the sample project grabs the daily Bing image to show in there as a sample, too.

So if you just want to jump in, the source is all up in the sample project in DynamicPanoramaBackgrounds.zip download (1.2 MB).

Feel free to use this in your own projects, it’s a simple set of extensions. This sort of effect is nice, but I’m personally glad that it isn’t built into the framework by default: there’s definitely some fixed performance cost to this sort of dynamic effect in the platform today.

I did a lot of testing on my phone and didn’t run into any noticeable performance issues, but beware that this implementation will increase the fill rate and have an effect over the standard, so don’t just use it without evaluating how important the scenario is to your apps. Note that this isn’t designed to do well when moving between background Brush types, or images of massively different sizes – but if they are all the same or similar, it should just work well!

Using ‘DynamicBackgroundPanorama’

Just set the Background property of the Panorama!

You can use data binding, or just straight code, for this. The example sample I wrote has two sub pages: one which just shows the current Bing search background for your region, and another which shows some photos that are just built into the project. No special work required!

I’ve packaged the control and its various components into the sample project instead of building out a standalone class library, so if you place it in your project, make sure you pick up all its individual files, including the Generic\Themes.xaml file that contains the default styles.

Contrasting image note

I haven’t addressed the contrasting image issue in this implementation. Ideally a second brush might be exposed, to allow for a translucent overlay of color such as a transparent black, over the backgrounds. This would help with keeping the contrast more appropriate, but I didn’t want to as it would increase the fill rate even more.

Designing the primitive(s)

It’s pretty straightforward to think about, but difficult to implement without also building out a few primitive controls to help with the re-templating experience.

So in designing the right implementation, I decided to mimic the same design ideas that went into the TransitioningContentControl (TCC) that is built into the Silverlight Toolkit’s layout control library. With that control, the Content property (or bound Content) is used in a cycle to smoothly animate out the old content and bring in the new content.

I wanted the same effect, but instead with just a Brush – in most situations an ImageBrush. I went ahead and started from the open source code to the TCC, changed the content presenters in the default style and control template to no longer be needed in the same way (I just derived from Control instead of ContentControl).

So here are the primitive components I built out:

DynamicBackgroundPanorama

A one-line control that derives from the official Panorama control. The constructor sets the DefaultStyleKey to the type, enabling the style from the Generic.xaml file to be pulled in automatically.

This is important because this scenario is built on re-templating and just a few primitive changes, and this type lets a developer use it without having to work very hard at all.

UpdatingPanningLayer

This is a one-method derived control, deriving from the primitive PanningBackgroundLayer. The purpose is to call the UpdateWrappingRectangles method, a protected method. This will cause the writeable bitmaps in the control to update so that the updated image changes will also update the “ears” or left/right wrapping rectangles used to show the wrap-around effect.

TransitioningBackgroundControl

Starting with the Silverlight Toolkit’s TransitioningContentControl created by Mr. Ruurd Boeke, I changed it up to instead work from the brushes. In case anyone is interested, changes from that were basically:

  • Moving the ContentPresenter sites from typeof ContentPresenter to Grid
  • Updating the code to specific issues with image brushes, where I’d like to wait to kick off the transition until after the image actually loads. Most of this code is done in the StartTransition method, plus the addition of the Loading visual state.
  • I dropped a subset of the VisualStates internal class from the toolkit into the file, just to reduce the number of unique files needed for the solution.
  • Added a dependency property of type Brush and name DynamicBackground. I could have used just the standard Background property, but that actually takes more work to wire up to ‘change’ events than to just define a new property like this.
  • A special workaround in the OnApplyTemplate to walk up the visual tree and identify the UpdatingPanningLayer, if any. This lets me force the Panorama control to effectively bump and update the side images of the control used when you scroll beyond the edges of the extreme items.
  • Updating the template:
    • Removing the alternative defined transitions
    • Changing the default fade-in template by removing the fade out of the current – leads to a smoother look in my opinion
    • Adding a Loading visual state to help with the delay-load effect of loading an image brush from a URI, for smoothness.
    • Adding BitmapCache settings to the two individual sites (Grids)

Themes\Generic.xaml

This file contains the custom template for Panorama as well as the important default style and template for the TransitioningBackgroundControl that I built. The differences from the official Panorama template are:

  • The PanningLayer primitive is replaced by my UpdatingPanningLayer
  • The Border and background set in the content of the background panning layer has been replaced by my TransitioningBackgroundControl
  • The background has the margin offset to eliminate the seam
  • There is no BitmapCache setting on the background in Panorama, instead it is set within the transitioning control, for performance reasons.

I’ve also taken guidance from Panorama developer extraordinaire Dave Relyea’s posts:

Note that this project makes use of the Silverlight for Windows Phone Toolkit for transitions, so make sure you have it installed if you want to use the sample code.

Download the sample project

Sample Project and Control Implementation [ZIP] (1.2 MB)
Dependencies: Windows Phone developer tools and the Silverlight for Windows Phone Toolkit (for transitions in the example only. The control does not have this dependency)

Hope this helps!