Silverlight: Dynamically creating XAML elements at runtime

Given the following XML file:

<assets>
  <asset name="tile">
    <Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <Path x:Name="top" Width="24" Height="12" Stretch="Fill" Fill="#FF065F02" 
            Stroke="#10000000" Data="F1 M 0,6L 12,12L 24,6L 12,0L 0,6 Z "/>
    </Canvas>
  </asset>
</assets>

It’s easy enough to create reusable assets in Silverlight and load them on demand from XML, and refer to the various pieces that make up the asset by name.

First, add an XML file to your Silverlight project. Set the Build Action to “Content” and the Copy to Output Directory to “Do not copy”. In the example below, it’s “r.xml”.

image

Next, add the following methods to a class (probably your UserControl):

private Canvas CreateXamlAsset(string assetName)
{
    return XamlReader.Load(LoadAsset(assetName)) as Canvas;
}

private string LoadAsset(string assetName)
{
    var e = from a in XDocument.Load("r.xml").Descendants("assets")
            where (string) a.Attribute("name") == assetName
            select a.FirstNode;
    return e.First().ToString();
}

The code uses LINQ to extract the asset and create it using the XamlReader.Load method. It assumes that the type being returned is a Canvas (it needs to be a container type and for these types of situations I normally use Canvas).

Once the canvas is created, you can call methods such as this:

private Shape FindShape(Canvas c, string name)
{
    return c.FindName(name) as Shape;
}

to locate the named elements within the dynamically created Xaml. For example, given the XAML at the top of this post, I could call the FindShape method like this:

Shape top = FindShape(canvas, "top");

That would return the Path named “top" in the XAML.

Make sure that you actually add the asset being returned from CreateXamlAsset to a parent control at some point! :) 

this.Children.Add(canvas);

Silverlight Stars/Sparkles

I was in a “star” mood this afternoon and created this Silverlight 2.0 demonstration.

image

For rendering it uses the CompositionTarget.Rendering method (the easiest way to control dynamic animations such as this). It also uses the VisualStateManager in a variety of places to control the user interface. I’ve become a big fan of the VSM – it’s easier to use than what WPF has as of 3.5 SP1 (I know it’s coming to WPF as well).

If you click into the UI to give it focus, you can press the [F] key to go full screen.

Switching to full screen is simple:

SilverlightHost host = Application.Current.Host;
if(host != null)
{
    Content content = host.Content;
    content.IsFullScreen = true;
}

I’ve also used my ToColorFromHex function liberally (I used Kuler to make some colors and grabbed their hex values and directly pasted into my source code).

To create the star trails (as I’ve called them), I needed to do a little bit of trigonometry:

double radians = Math.Atan2(-star.Vector2D.Y, -star.Vector2D.X);
(star.StarTrailUI.RenderTransform as RotateTransform).Angle = radians * 180 / Math.PI;

I used a RenderTransform in place of building a line with the proper X & Y coordinates as it made dealing with the LinearGradientBrush on the trail a TON easier (for me at least).

Demonstration

I’ve provided all of the source code – maybe you’ll find it useful (if so, I’d like to hear about it!).

Source code

Update: Fixed the links. Sorry!

Recommended: Fluke’s 62 Mini IR Thermometer

This is by far the most popular item I’ve ever loaned out to friends and family:

Fluke 62 Mini Infrared Thermometer

It’s a digital thermometer which is able to read the surface temperature of an object by simply pointing at it. It’s great for determining the temperature of hard-to-reach surfaces as well as objects that are close. It has a small red-laser for accurate targeting of a surface.  You can use it to check the temperature of your oven for example to verify the accuracy of the oven’s set temperature (they’re often less accurate than you’d think).

I, and many others, have used it during a cold winter to try to find cold air leaks, cold spots, poorly insulated walls, and electrical outlets (and more!).

I’d highly recommend it.

ColorConverter for Silverlight

Silverlight 2.0 is missing a ColorConverter. There’s no easy and efficient way from code to convert from a HEX color format to a built in Color type. I like being able to paste standard web color formats into my source code without converting them to a Color.FromArgb byte format (as most web color selectors support that format).

I wrote this code to end this annoyance (but didn’t bother with a full-fledged TypeConverter):

public static class Extensions
{
    public static void SetFromHex ( this Color c, string hex )
    {
        Color c1 = ToColorFromHex(hex);

        c.A = c1.A;
        c.R = c1.R;
        c.G = c1.G;
        c.B = c1.B;                        
    }
public static Color ToColorFromHex ( string hex )
{
    if(string.IsNullOrEmpty(hex))
    {
        throw new ArgumentNullException("hex");
    }

    // remove any "#" characters
    while(hex.StartsWith("#"))
    {
        hex = hex.Substring(1);
    }

    int num = 0;
    // get the number out of the string 
    if(!Int32.TryParse(hex, System.Globalization.NumberStyles.HexNumber, null, out num))
    {
        throw new ArgumentException("Color not in a recognized Hex format.");
    }

    int[] pieces = new int[4];
    if(hex.Length > 7)
    {
        pieces[0] = ((num >> 24) & 0x000000ff);
        pieces[1] = ((num >> 16) & 0x000000ff);
        pieces[2] = ((num >> 8) & 0x000000ff);
        pieces[3] = (num & 0x000000ff);
    }
    else if(hex.Length > 5)
    {
        pieces[0] = 255;
        pieces[1] = ((num >> 16) & 0x000000ff);
        pieces[2] = ((num >> 8) & 0x000000ff);
        pieces[3] = (num & 0x000000ff);
    }
    else if(hex.Length == 3)
    {
        pieces[0] = 255;
        pieces[1] = ((num >> 8) & 0x0000000f);
        pieces[1] += pieces[1] * 16;
        pieces[2] = ((num >> 4) & 0x000000f);
        pieces[2] += pieces[2] * 16;
        pieces[3] = (num & 0x000000f);
        pieces[3] += pieces[3] * 16;
    }
    return Color.FromArgb((byte) pieces[0], (byte) pieces[1], (byte) pieces[2], (byte) pieces[3]);
}

}

 

It accepts 3 standard formats for colors:

  1. [ALPHA][RED][GREEN][BLUE] (alpha and all colors)
  2. [RED][GREEN][BLUE] (no alpha channel, automatically set to 255)
  3. Short hand [R][G][B] (takes the single digit hex number and adds it to the same number * 16, alpha set to 255);

To use the function:

Color c1 = Extensions.ToColorFromHex("#00B2D6E8");

Obviously the built in components, brushes, etc. support that format already, but there doesn’t seem to be any place that functionality is exposed.

Recent Sci-fi readings …

Some sci-fi books I’ve read recently that I’d recommend:

Orphan’s Journey (Jason Wander)

Orphan’s Destiny (Jason Wander)

Orphanage (Jason Wander)

The above books by Robert Buettner were very enjoyable, although shorter than I would have liked (either more depth added or fewer books).

Ilium

Ilium is a bit tough to read (as the story parallels some of the Iliad along with all of the names), but I definitely enjoyed the twists and turns of the book. It’s gotten really good reviews generally (although there’s of course some people who hated it).

If you haven’t tried Dan Simmons before, I’d definitely recommend this book:

Hyperion

(It’s gotten awesome reviews at Amazon).

Here’s some of my older recommendations for sci-fi books. I definitely appreciate the advice given then and any new suggestions you might have!