Fun with Fills in Silverlight 1.0

I've saw a few people trip over the Fill property of Silverlight objects in JavaScript last week. Let's use the following XAML snippet as an example:

<Canvas>    
    <
Rectangle x:Name ="_box1" Canvas.Left="10" Canvas.Top="10"
                Width="100" Height="100" Fill="Red" />

    <
Rectangle x:Name ="_box2" Canvas.Left="120" Canvas.Top="10"
                Width="100" Height="100" Fill="Red" />
</
Canvas>

Given the way the Fill attributes look (Fill="Red"), you'd be tempted to think the following code would work:

var box1 = silverlightControl.content.findName('_box1');
var box2 = silverlightControl.content.findName('_box2');


box1.Fill =
"Green";
box2.Fill = box1.Fill;
// this will create an error

But, that last line of code will create a runtime error:

AG_E_RUNTIME_SETVALUE

The infamous AG_E_RUNTIME_SETVALUE error! The error says we are trying to put a square object into a round hole. What is the Fill property expecting? Aren't we just copying a simple string reference around? The debugger's immediate window can give us a few hints as to what is happening:

immediate window debugging

The first dump shows us that the Fill property doesn't reference a simple string. The second dump tells us we are actually dealing with a SolidColorBrush object. Hmmm – what happened to "Red"? Even more mysterious - the third dump (the brush's Color property) is a negative number.

Magical Colors

The MSDN docs for Color describe some of the type conversion magic operating behind the scenes. Essentially, you can set a Color property (or the Fill property of a SolidColorBrush) using a well known name ("Green"), a hex string ('#FF00FF00'), or an ScRGB string ('sc#1,0,1,0'). Silverlight will take care of converting the incoming value into the proper internal representation. So, setting a Color property is easy. What's difficult is getting a meaningful value out of the Color property. Take note of this remark in the MSDN docs:

The runtime scripting value of an existing Color is potentially stored differently on different browsers and platforms. You can compare color values obtained from scripting between existing instances, or set one Color property with the value of another existing Color, but directly comparing these values to named color strings, hex strings, or ScRGB strings that were used to specify the color initially is not supported.

This means we can avoid the runtime error with the following code …

box1.Fill = 'BlanchedAlmond';
box2.Fill.Color = box1.Fill.Color;

… but we need to be careful with code like the following. The makeHexColor function will compute the correct hex string for Color properties on IE7 (like '#ff00ff00' for a green color, which we saw yielded -65536 in the debugger), but according to the docs this code might break in FireFox or on a Mac, because the internal representation of colors might be different.

    box1.Fill = 'Green';
    box2.Fill.Color = makeHexColor(box1.Fill.Color);
    
// ...

function makeHexColor(color)
{
    
var result = "";
    
for (var i = 0; i < 8; i++) {
        result = (color & 0xF).toString(16) + result;
        color >>= 4;
    }
    
return "#" + result;
}


Posted Feb 20 2008, 10:33 PM by scott-allen

Add a Comment

(required)  
(optional)
(required)  
Remember Me?