I’ve been heads-down in Visual Studio 2008 Beta 2 and the Silverlight 1.1 Alpha Refresh for the past several days. Now that I’ve come up for air, I’d like to share a few tips, tricks, and work-arounds for glitches in the current builds that other developers might find helpful.

SILVERLIGHT.JS
After you install the July 2007 Microsoft Silverlight Tools Alpha Refresh for Visual Studio, you can create Silverlight 1.1 projects in Visual Studio. However, the copy of Silverlight.js that Visual Studio includes in new projects goes with Silverlight 1.0, not 1.1. The result? If someone visits your Silverlight 1.1 page and they don’t already have Silverlight 1.1 installed, they’re prompted to install the wrong one. Then they’re prompted again, and again, and again…

The fix is to replace the version 1.0 Silverlight.js file Visual Studio added to your project with version 1.1. You can grab the correct version from the SilverLife source code.

XAML PARSER DOESN’T HANDLE CUSTOM CONTROLS CORRECTLY
Custom controls derive from System.Windows.Controls.Control, and from it they inherit certain properties such as Width and Height. You typically reimplement these properties in derived classes and hide them by tagging them with C#’s new keyword. However, these properties can’t be initialized declaratively because the XAML parser doesn’t properly generate calls to the property setters. Instead of doing this:

<custom:MyControl x:Name=”MyControl1″ Width=”200″ Height=”200″ … />

You have to do this:

<!– XAML –>
<custom:MyControl x:Name=”MyControl1″ … />

// C#
MyControl1.Width = 200;
MyControl1.Height = 100;

Interestingly, other properties–that is, ones that don’t come from the base class–can be declaratively initialized just fine.

GETTING RID OF TESTPAGE.HTML
Visual Studio includes files named TestPage.html and TestPage.html.js in every Silverlight 1.1 project. You can change TestPage.html’s name in Solution Explorer, but you can’t rename TestPage.html.js. (And if you do it manually, the link between the two files in Solution Explorer is lost.)

As a work-around, go out to the file system and rename the files. In SilverLife, for example, I named them Default.html and Default.html.js. Then open the SLN file in Notepad and change this:

<ItemGroup>
<None Include=”TestPage.html” />
<None Include=”TestPage.html.js”>
<DependentUpon>TestPage.html</DependentUpon>
</None>
</ItemGroup>

to this:

<ItemGroup>
<None Include=”Default.html” />
<None Include=”Default.html.js”>
<DependentUpon>Default.html</DependentUpon>
</None>
</ItemGroup>

Reopen the project in Visual Studio and the files will appear in Solution Explorer properly linked together.

STORYBOARDS AS GAME TIMERS
In SilverLife, I needed a timer to drive automated simulations. HtmlTimer is deprecated and not very reliable. System.Threading.Timer wasn’t an option because at present, there’s no way to marshal timer callbacks back onto the UI thread. So I declared a Storyboard in XAML and wired a handler to its Completed events for use as a timer:

<!– XAML –>
<Canvas.Resources>
<Storyboard x:Name=”Timer” />
</Canvas.Resources>

// C#
Timer.Completed += new EventHandler(OnTick);

It worked fine initially but proved totally unreliable. Simply running the project from a directory other than the one in which it was created caused Completed events to stop firing (or the handler to never be called).

I found a work-around after 10 hours of head-banging: wire the event to the event handler declaratively:

<Canvas.Resources>
<Storyboard x:Name=”Timer” Completed=”OnTick” />
</Canvas.Resources>

So far it’s working just fine, and it works in Firefox, too.

As an aside, despite documentation and blog posts to the contrary, I found that it’s not necessary to declare a target for Storyboard objects in the Silverlight 1.1 Alpha Refresh. Maybe it’s just me…

HTML BRIDGE / DOM INTEGRATION
To close on a positive note, I found that the DOM integration features not only work well, they’re downright amazing. How cool is it to be able to call into managed code from JavaScript and even process managed events in JavaScript? I found a handy use for the latter.

I’d like to be able to execute the equivalent of window.alert from managed code, but the Alpha Refresh doesn’t support that. What you can do instead is declare a scriptable event in your XAML code-behind class:

[Scriptable]
public partial class Page : Canvas
{
public void Page_Loaded(object o, EventArgs e)
{
InitializeComponent();
WebApplication.Current.RegisterScriptableObject(“magic”, this);
}

    [Scriptable]
public event EventHandler<ShowMessageEventArgs> ShowMessage;

}

Then register a JavaScript handler for the event like this:

var control = document.getElementById(‘SilverlightControl’);
control.content.magic.ShowMessage = onShowMessage;

Finally, call window.alert in the handler, like this:

function onShowMessage(sender, args)
{
window.alert(args.Message);
}

Now, anytime you want to pop up an alert box, simply fire a ShowMessage event from managed code:

ShowMessage(this, new ShowMessageEventArgs(“Hello, world!”));

I derived ShowMessageEventArgs from EventArgs and marked it scriptable. I also built in a Message property and marked it scriptable, too. That way I can pass the message that I want to appear in the alert box in ShowMessageEventArgs.Message and easily access it in the JavaScript handler.