A similar question just popped up on a list I’m on, so I thought I’d whip up a quick example on how to resize a Silverlight application while keeping the same aspect ratio and centering the content.

The key to resizing is to use a ScaleTransform on the LayoutRoot of your main page. Here’s the important part of the xaml for the page. The key part is the “Grid.RenderTransform” section and the RenderTransformOrigin for the grid. In the latter, 0.5, 0.5 tells the engine that any render transforms should originate in the center of the grid. The former we name “PageScale” to allow us to easily manipulate its ScaleX and ScaleY properties from code.
<UserControl x:Class="PeteBrown.SilverlightScalingExample.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Grid x:Name="LayoutRoot"
Background="Cornsilk" ShowGridLines="True"
Width="400" Height="300"
RenderTransformOrigin="0.5 0.5">
<Grid.RenderTransform>
<ScaleTransform x:Name="PageScale" ScaleX="1" ScaleY="1"/>
</Grid.RenderTransform>
…
</Grid>
</UserControl>
Note also in the markup that I have left the grid lines on. This helps you visualize and debug resizing behavior especially when working with complex layouts that combine true expanding grids along with transforms and combinations of other panels.
Here’s the code. It is pretty straight-forward. I set the desired aspect ratio as a constant and then resize against that using the new SizeChanged event.
public partial class Page : UserControl
{
// this is the aspect ratio we want to maintain
// you can specify this all sorts of ways, but the
// easiest is to take the original size and divide
// X by Y (4:3 or 1.333 in this case)
private const double _originalWidth = 400;
private const double _originalHeight = 300;
private const double _originalAspectRatio =
_originalWidth / _originalHeight;
public Page()
{
InitializeComponent();
// wire up the event handler. This is a great addition
// to silverlight, as you used to have to hook into the
// browser event yourself
SizeChanged += new SizeChangedEventHandler(Page_SizeChanged);
}
void Page_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.NewSize.Width < _originalWidth ||
e.NewSize.Height < _originalHeight)
{
// don't shrink
PageScale.ScaleX = 1.0;
PageScale.ScaleY = 1.0;
}
else
{
// resize keeping aspect ratio the same
if (e.NewSize.Width / e.NewSize.Height > _originalAspectRatio)
{
// height is our constraining property
PageScale.ScaleY = e.NewSize.Height / _originalHeight;
PageScale.ScaleX = PageScale.ScaleY;
}
else
{
// either width is our constraining property, or the user
// managed to nail our aspect ratio perfectly.
PageScale.ScaleX = e.NewSize.Width / _originalWidth;
PageScale.ScaleY = PageScale.ScaleX;
}
}
}
}
In this example, I decided to restrict the user from resizing to a size smaller than the original size of the application. That is often but not always desirable. The check is easy enough to remove should you wish to allow a tiny thumbnail application.
If you have bitmap assets, resizing may not be as fluid. Experiment with the largest version you can include in your xap while keeping a reasonable download size.
Full source code available here.
Running example here.