Automatically stretching a Silverlight 2 control on a webpage

Standard

image

A couple of fun hours were spent trying to get my Silverlight content to resize when the user resized the browser. 

I mean, what’s the point of having your Silverlight content replace HTML if it wont flow and resize when the user resizes the browser? I want my Silverlight content to take up the whole browser frame.

The Html Code

You’d think this would be the default behaviour for an asp.net tag definition like this:

<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/TechnologyOneCrm.xap" Version="2.0" Width="100%" Height="100%" />

 

Sadly this is not enough.  Your silverlight sits there in a dumb un-resizeable box.

The Xaml

When you create a Silverlight 2 control in Visual Studio 2008 or blend, the UserControl typically has Height and Width properties set, something like this:

<UserControl x:Class="Daphne.WorkplaceHome"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Width="900" Height="400" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
    <Grid x:Name="LayoutRoot" Background="White" >
    </Grid>
</UserControl>

 

The Elusive Auto

Hence the reason why your content is not resizable.

One solution is to remove the Width and Height property.   Another is to set them to “Auto”, like so:

<UserControl x:Class="Daphne.WorkplaceHome"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Width="Auto" Height="Auto" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
    <Grid x:Name="LayoutRoot" Background="White" >
    </Grid>
</UserControl>

 

If you run the project, it will start resizing.  Unfortunately this causes the designer in Blend and VS2008 look like rubbish.  (or more rubbish than usual anyway).

The trick is to set the Width and Height properties to “Auto” after the the screen has been rendered.

 

In WPF (apparently) you can use code like this:

Partial Public Class Page
    Inherits UserControl
    Public Sub New()
        InitializeComponent()

        Me.Height = new System.Windows.LengthConverter().ConvertFromString("Auto")
        Me.Width =  new System.Windows.LengthConverter().ConvertFromString("Auto")
    End Sub

...

 

Sadly, in another twist of fate, “LengthConverter” does not exist in Silverlight.

The Silverlight Solution – Who’s your Nan?

 

image

 

Fortunately, browsing the type library showed me that setting the property value of Height or Width to “System.Double.Nan” has the same effect as “Auto”.

So, in the intialise of your Silverlight control, put this:

 

Partial Public Class Page
    Inherits UserControl
    Public Sub New()
        InitializeComponent()

        Me.Height = System.Double.NaN
        Me.Width = System.Double.NaN
    End Sub

 

I am not sure if Microsoft intend to support LengthConverter (or TypeDescriptor.GetConverter!) in a future Silverlight version, but I’m guessing not.

Links

 

Share this post :

Advertisements

6 responses »

  1. Hi Julian, a colleague of yours sent me here via a post in the ausdotnet group. I’m also utterly sick fo trying to make SL pages and controls Dock Fill on a web page or part of a web page (such as a resizable table cell). Here is my reply to the group:

    ————–
    Hi Joe,

    I’ll send Julian a sympathetic email to tell him he’s not alone. I did something similar with child controls recently so they filled their container at runtime. I had 3 different controls filling the same container, but only one was visible at a time (they faded in an out as needed). I had to make them visible at design time and then position correctly at runtime. Forms developers simply position all 3 controls to be visible at design time, then Dock Fill at runtime. I did the equivalent by coding this:


    public SizePickerControl()
    {
    InitializeComponent();
    FillSizeList();
    LayoutRoot.Width = double.NaN;
    LayoutRoot.Height = double.NaN;
    }

    As Julian did, I tried this once in the main SL page, but it collapsed vertically to about 5 pixels high. However, I think this is a HTML problem, and not an SL one. I’ll return to this later and try to find the correct HTML container that creates the elastic effect.

    Cheers,
    Greg Keogh

  2. In your usercontrol designer, you can delete the Height and Width on the UserControl tag so that it resizes automatically in the window. To make it have a size in Blend you can add the following attributes so you have a window to work with in Blend:

    d:DesignWidth=”640″ d:DesignHeight=”100″

    If it doesn’t know what d is then add these attributes:

    xmlns:d=”http://schemas.microsoft.com/expression/blend/2008″
    mc:Ignorable=”d”

  3. I usually set Width and Height to “Auto” and provide a MinWidth and MinHeight, which simultaneously resolves the designer problem and also ensures that the UI doesn’t get smaller than it can reasonably handle.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s