Change in UIElementRenderer behavior and update to UIElementRendererHelper

A while I back I posted about a UIElementRendererHelper class I had made to simplify life when mixing Silverlight and XNA Framework rendering in Windows Phone 7 Mango. Since then we've shipped an update or two to the tools and along with those has come a change in how UIElementRenderer works and as such an update to my own UIElementRendererHelper.

When we shipped the first beta of XNA GS 4.0 Refresh along with the Windows Phone 7.1 SDK, you were able to call UIElementRenderer.Render() anywhere you wanted in your draw code. This was convenient as it allowed you to keep all your UIElementRenderer code in one location however it wasn't really safe or consistent enough for our liking. Under the hood, the Render method needs to do a render target swap to draw certain UI elements to the texture which meant that in some cases you'd lose your backbuffer and in others you wouldn't. This was a bit inconsistent since our default render targets discard the backbuffer when switching between them and it was also way too complicated to have developers have to track what elements do what in which conditions.

In an effort to make the framework more consistent and safe for our developers, we updated the type to make sure that Render always discards the backbuffer to ensure developers don't get caught in weird situations. By making this consistent with our render target API, developers have to only learn one set of rules which apply both to custom render targets and the UIElementRenderer. I believe this is a big improvement, even if it means a change from our original beta behavior.

As for UIElementRendererHelper this means that the existing code is likely to break real rendering scenarios because the call to Render is in the middle of the draw (the helper specifically hooks up after your page's draw code, calls Render, and then draws the UI). As such a change was required. I didn't like any of the more automated solutions such as creating and managing new timers, so instead I just made the helper a little less automatic. The original usage for construction still applies:

// Make a field for the helper
UIElementRendererHelper uiRenderer;

// Construct in OnNavigatedTo after enabling XNA rendering
uiRenderer = new UIElementRendererHelper(this);

// Dispose in OnNavigatedFrom before turning off XNA rendering
uiRenderer.Dispose();

However now you must do some manual method calls in OnDraw to make sure the UI can render into the texture before you've started drawing the scene:

// PreRender handles rendering the Silverlight content to the render target
uiRenderer.PreRender();

SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.CornflowerBlue);

// TODO: Add your drawing code here

// Draw uses SpriteBatch to draw the Silverlight UI to the screen
uiRenderer.Draw();

It's not quite as nice as the original, but the helper still handles a lot of things for you such as managing the size of the UIElementRenderer in case of page resizing (e.g. toggling the app bar, rotating the screen, etc). Additionally it still handles translating the UI drawing due to the on screen keyboard coming up for text boxes.

Hopefully this information helps you in your own code and the helper can continue to be useful as you get your apps and games Mango ready.

UIElementRendererHelperSample.zip