Welcome to irritatedVowel.com Sign in | Help

POKE 53280,0: Pete Brown's Blog

Silverlight, WPF, Woodworking, .NET Programming, CNC, Nature, and other topics.

Pete Brown writes on a number of topics including Silverlight, WPF, .NET, woodworking and working as a consultant in the DC area. On most forums, Pete goes by the name Psychlist1972. Pete has worked at Applied Information Sciences (AIS) since 1996 where he currently performs as a lead architect and project manager.

Subscribe to my feed

Add to Technorati Favorites
Applied Information Sciences - My Employer

Community Events



World Domination

who's online

Networks


View Pete Brown's profile on LinkedIn

AddThis Social Bookmark Button

How to Resize a Silverlight 2 App and Keep the Same Aspect Ratio

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.

image image image

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.

  Add to Technorati Favorites
Posted: Friday, July 04, 2008 11:28 PM by Pete.Brown
Filed under: ,

Comments

Dew Drop – July 5, 2008 | Alvin Ashcraft's Morning Dew said:

PingBack from http://www.alvinashcraft.com/2008/07/05/dew-drop-july-5-2008/
# July 5, 2008 9:21 AM

DrYSG said:

I think I was the guy who asked the question in the forum you mentioned. Quick Question (which I could probably figure out by doodling, but perhaps you already know the answer). The effect I am trying to achieve is a GridLayout where 3/4 of the screen is fixed, and the lower-right quadrant has an MSI that scales to fill the available space. Since you are using the PageScale of the whole page, I assume what I have to do is embedd a Grid in the lower quadrant and watch the scale of that grid itself (What I probably will do is create a UserControl with and embedded great and then the MSI in the grid.) Does that sound right to you?
# July 6, 2008 1:26 PM

Community Blogs said:

Michael Washington on SL Security, Jesse LIberty on Styles & Templates, Koen Swikstra on Tweening
# July 7, 2008 12:22 AM

Community Blogs said:

Michael Washington on SL Security, Jesse LIberty on Styles & Templates, Koen Swikstra on Tweening
# July 7, 2008 2:32 AM

Rui Marinho said:

And if you don't want to give a fixed size? how can the render transform.. transform also the childrens in the grid? like a user control.. thanks for sharing :)
# July 8, 2008 11:29 AM

Pete.Brown said:

@Rui the fixed size is only the starting point - the "natural" resolution of the application. Depending on how you set up your containers, you can retrieve that at runtime. More often than not, however, you end up with zero or NaN (more on that in another post).

As to resizing children as well: scaling the parent scales the children. If you want to scale only the children, that's a slightly more difficult problem as Silverlight has only render transforms, not layout transforms, making holistic layout a bit trickier.

Pete

# July 8, 2008 5:01 PM

Mirrored Blogs said:

Post: Approved at: Jul-8-2008 GUI .. GUI ... GUI ... Themes for Silverlight Applications "A theming
# July 8, 2008 6:25 PM

代震军 said:

Pete Brown在它的BLOG中提到了一个按自定义比例使用silverlight适应IE窗口大小的方法
# July 13, 2008 11:33 PM

Kamran Shahid said:

Nice One
# July 21, 2008 2:40 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Enter the text you see in the image:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS