Here’s a simple UserControl + codebehind concept for Silverlight 1.0, involving minimal changes to Visual Studio 2008’s “Silverlight JScript Page” template code.

The example here is for a basic ‘progress bar’ control.  First create a new Silverlight JScript Page (I called this one ProgressBar) and paste this into ProgressBar.xaml:

<Canvas xmlns="http://schemas.microsoft.com/client/2007"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Width="1"
        Height="0.1">

    <Rectangle Name="box" Width="1" Height="0.1" StrokeThickness="0.01"
               Stroke="#FF8C92C8" Fill="#505050" />

    <Rectangle Name="progress" Width="0" Height="0.08" Canvas.Top="0.01" Canvas.Left="0.01">
        <Rectangle.Fill>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FF187EE4" Offset="0"/>
                <GradientStop Color="#FF306CA7" Offset="1"/>
                <GradientStop Color="#FF6AACEE" Offset="0.232"/>
            </LinearGradientBrush>
        </Rectangle.Fill>
    </Rectangle>

</Canvas>

Note the ‘normalized’ Width and Height values I’ve used.  The only reason for this is so the ProgressBar is easily scalable; the idea is you’d apply a ScaleTransform somewhere higher in the control tree.  This is particularly useful if you have a group of related controls (say an image, selection border, loading progress bar etc) and you want them to resize together; just apply a ScaleTransform to their common parent.

Next, modify ProgressBar.js to look like this (you’ll need to replace ‘MyProject’ with your actual project name):

if (!window.MyProject)
    window.MyProject = {};

MyProject.ProgressBar = function( plugIn, onLoad ) 
{
    UserControl.load( plugIn, "ProgressBar.xaml", true, Silverlight.createDelegate( this, function( sender, args )
    {
        if ( onLoad ) onLoad( sender, args );
        this.handleLoad( plugIn, null, args.xaml );
    } ) );
}

MyProject.ProgressBar.prototype =
{
    box: null,
    progress: null,

    handleLoad: function(plugIn, userContext, rootElement) 
    {
        this.plugIn = plugIn;
        
        this.box = rootElement.FindName( "box" );
        this.progress = rootElement.FindName( "progress" );
    },

    setProgress: function( progress )
    {
        if ( this.progress )
        {
            this.progress.Width = ( this.box.Width - ( this.box.StrokeThickness * 2 ) )
                * Math.max( 0, Math.min( 1, progress ) );
        }
    },

    getProgress: function()
    {
        return this.progress
            ? this.progress.Width / ( this.box.Width - ( this.box.StrokeThickness * 2 ) )
            : 0;
    }
}

Note the similarity to the auto-generated code.  In the constructor it calls ‘UserControl.load’, which is defined here:

function UserControl()
{
}

UserControl.prototype =
{
    load: function Load( plugIn, url, createNameScope, onCompleted )
    {
        var downloader = plugIn.createObject( "Downloader" );

        downloader.addEventListener( "Completed", Silverlight.createDelegate( this, function( sender, args )
        {
            var xaml = sender.getResponseText( "" );
            args = { xaml: plugIn.Content.CreateFromXaml( xaml, createNameScope ) };
            onCompleted( sender, args );
        } ) );

        downloader.open( "GET", url );
        downloader.send();
    }
}

var UserControl = new UserControl();

The UserControl helper just hides away the messy business of loading the XAML file (from the webserver), calling CreateFromXaml and invoking a custom handler when it’s done.

If you look again at ProgressBar.js you’ll see it defines a handler to point a couple of variables at relevant Silverlight objects (the outer ‘box’ rectangle and the ‘progress’ rectangle).  It also exposes ‘setProgress’ and ‘getProgress’ methods.

To create an instance of the progress bar, here’s what you need to do:

var progressContainer = rootElement.FindName( "progressContainer" );

this.progress = new MyProject.ProgressBar( plugIn, Silverlight.createDelegate( this, function( sender, args )
{
    progressContainer.Children.Add( args.xaml );
} ) );

The example assumes you already have a parent Canvas named ‘progressContainer’ and you want to hold a reference to the ProgressBar Javascript object in ‘this.progress’.  Setting the current progress is then just a matter of calling ‘setProgress’:

this.progress.setProgress( this.downloader.DownloadProgress );
...

The ‘setProgress’ method just wants a value between 0 and 1.  In this example it’s using the DownloadProgress value from a Silverlight Downloader object.

If you use this code, remember you’ll need to apply a ScaleTransform somewhere in your control tree (or if you just want to see it work, put one in ProgressBar.xaml itself).

Hope this helps!  Fortunately for codebehind fans the pain will soon end when we get Silverlight 2.0😉