Friday, October 23, 2009

Silverlight Eyecandy - Spawning A Random TextBlock

We will cover Storyboard Animations, Loading Data from Dynamic XML Files, and Using the Silverlight Random Class

I will show you how to load a list of words from a dynamic XML file, and display those words on a canvas at random sizes and using random fonts just like the Silverlight application below.




If the above silverlight app does not show up for you, try clicking on the link of the topic, the pathing got screwy with Blogger no longer allowing publishing to ftp.

For this project you will need to Add Reference To System.Xml.Linq


Step 1.
Start by creating a new Silverlight Application project in Visual Studio

Step 2.
Inside your LayoutRoot Grid, create a Canvas & inside that Canvas create a Textblock. Created a Loaded callback for the Canvas. Set Opacity to 0.

<Usercontrol x:Class="CanvasTextblock_EyeCandy.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
  <Grid x:Name="LayoutRoot">
        <Canvas x:Name="canvas1" Background="#303030" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Loaded="Canvas_Loaded" >
            <TextBlock x:Name="textBlock1" Opacity="0" Foreground="WhiteSmoke" />
        </Canvas>
    </Grid>
</UserControl>

Step 3.
Create storyboard in the UserControl resources for fading the Textblock's Opacity in and out using a DoubleAnimation. We'll set To to 0.85, Duration to 3 seconds. Also, set AutoReverse to True and then create a callback for the DoubleAnimation being Completed

Then create 2 more DoubleAnimations to change the Canvas.Top and Canvas.Left attributes of the TextBlock, set their To to 1

Your code should look something like this:
<UserControl x:Class="CanvasTextblock_EyeCandy.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480" >
    <UserControl.Resources>
        <Storyboard x:Name="textBlockFader">
            <DoubleAnimation  Storyboard.TargetName="textBlock1" Storyboard.TargetProperty="(Canvas.Top)" To="1" Duration="00:00:00" x:Name="tbPositionTop" />
            <DoubleAnimation  Storyboard.TargetName="textBlock1" Storyboard.TargetProperty="(Canvas.Left)" To="1" Duration="00:00:00" x:Name="tbPositionLeft" />
            <DoubleAnimation Storyboard.TargetName="textBlock1" Storyboard.TargetProperty="Opacity" To="0.85" AutoReverse="True" Duration="00:00:03" Completed="DoubleAnimation_Completed" />
        </Storyboard>
    </UserControl.Resources>
  <Grid x:Name="LayoutRoot">
        <Canvas x:Name="canvas1" Background="#303030" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Loaded="Canvas_Loaded" >
            <TextBlock x:Name="textBlock1" Opacity="0" Foreground="WhiteSmoke" />
        </Canvas>
    </Grid>
</UserControl>

Step 4.
Now we create the XML file that will store our Words, Fonts, and FontSizes we'll be using for our randomness. You can either use my XML file for your sample or the code below. For my example, if the webpage hosting my silverlight control is at http://domain.com/index.htm then my XML file is going to be in http://domain.com/Data/SmileWords.xml :

<?xml version="1.0" encoding="utf-8" ?>
<Data>
  <Words>
    <Word>Smile</Word>
    <Word>Smirk</Word>
    <Word>Grin</Word>
    <Word>Whiter Teeth</Word>
    <Word>Laugh</Word>
    <Word>Laughter</Word>
    <Word>Happiness</Word>
    <Word>Success</Word>
    <Word>Straight Teeth</Word>
    <Word>Beam</Word>
    <Word>Joy</Word>
    <Word>Joyful</Word>
    <Word>Happy</Word>
    <Word>Shine</Word>
  </Words>
  <Sizes>
    <Size>18</Size>
    <Size>20</Size>
    <Size>24</Size>
    <Size>28</Size>
    <Size>30</Size>
    <Size>32</Size>
    <Size>36</Size>
    <Size>40</Size>
    <Size>44</Size>
    <Size>48</Size>
    <Size>50</Size>
    <Size>54</Size>
    <Size>58</Size>
    <Size>60</Size>
    <Size>66</Size>
    <Size>72</Size>    
  </Sizes>
  <Fonts>
    <Font>Arial</Font>
    <Font>Arial Black</Font>
    <Font>Calibri</Font>
    <Font>Cambria</Font>
    <Font>Cambria Math</Font>
    <Font>Comic Sans MS</Font>
    <Font>Candara</Font>
    <Font>Consolas</Font>
    <Font>Constantia</Font>
    <Font>Corbel</Font>
    <Font>Courier New</Font>
    <Font>Georgia</Font>
    <Font>Tahoma</Font>
    <Font>Times New Roman</Font>
    <Font>Trebuchet MS</Font>
    <Font>Verdana</Font>
  </Fonts>
</Data>

Step 5.
We'll now go to the code-behind. You'll need to add 3 code references that are not added to your project by default:

using System.Xml;
using System.Xml.Linq;
using System.IO;

You'll also want to make 3 List<> declarations to store the values we load from our dynamic XML file and declare an instance of the Silverlight Random class:
List<string> words = new List<string>();
List<string> fontnames = new List<string>();
List<double> fontsizes = new List<double>();
Random myrand = new Random();

Inside the DoubleAnimation_Completed callback we have the code for setting up the next randomization:
private void DoubleAnimation_Completed(object sender, EventArgs e)
{
    textBlock1.Text = words[myrand.Next(0, words.Count - 1)];
    textBlock1.FontFamily = new FontFamily(fontnames[myrand.Next(0, fontnames.Count - 1)]);
    textBlock1.FontSize = fontsizes[myrand.Next(0, fontsizes.Count - 1)];
    tbPositionTop.To = myrand.Next(1, Convert.ToInt32(canvas1.ActualHeight - textBlock1.ActualHeight));
    tbPositionLeft.To = myrand.Next(1, Convert.ToInt32(canvas1.ActualWidth - textBlock1.ActualWidth));
    textBlockFader.Begin();
}

Then in the Loaded function for the Canvas you're going to download the XML file for loading.

private void Canvas_Loaded(object sender, RoutedEventArgs e)
{
    WebClient client = new WebClient();
    client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
    Uri url = new Uri("/Data/SmileWords.xml", UriKind.RelativeOrAbsolute);
    client.DownloadStringAsync(url);
}
In the callback for DownloadStringCompleted:
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
     StringReader stream = new StringReader(e.Result);
     XmlReader reader = XmlReader.Create(stream);
     XDocument xmlDoc = XDocument.Load(reader);
     words = (from at in xmlDoc.Descendants("Words").Descendants("Word")
              select at.Value.ToString()).ToList();
     fontsizes = (from at in xmlDoc.Descendants("Sizes").Descendants("Size")
              select Convert.ToDouble(at.Value)).ToList();
     fontnames = (from at in xmlDoc.Descendants("Fonts").Descendants("Font")
              select at.Value.ToString()).ToList();
     DoubleAnimation_Completed(null, null);
}


That's it! Your program should now download the XML file upon loading, parse and store the information into memory, and begin the eyecandy!

You can further customize the randomness by giving a seperate Random class for each attribute you're randomizing, and initializing the Random class each with a different seed. You could also add in FontWeights, RenderTransforms, or even import custom Fonts.

The solution for this project can be found here: Silverlight_EC1.zip

Monday, October 12, 2009

Abbreviation And Extension Pronounciation

When you're talking to a friend about a file you sent them, that was created using Microsoft Word, how do you refer to it? Do you say call it a "doc" file? A "dee-oh-see" file? Or a word document?

What about SQL? My co-workers and i held a discussion about which abbreviations and file extensions we pronounce in what ways. I've always said "ess-cue-el" and both of them have always used "sequel". I still disagree with them on which is right for SQL, but we all agree that .xaml files are called "ecksamel", and that .xml is "ex-em-el".

"Did you get that PDF file?"
 Now say the sentence above, but sounding it out as if PDF was a word. "Did you get that pedif file?". If you're not laughing or offended, you didn't say it right. Try again!

Yeah, we're pretty much going straight to hell. But hey, at least we did get a good laugh out of it, saying it over and over. It reminded me of that scene in Zoolander where Ben Stiller says "Uh, no, I don't think you do. Listen. It's not like we think we're actually in a control tower trying to reach outer space aliens or something, okay?" and Owen Wilson says "Hello. Hello." and they were all just kind of giggling. Yeah...that's what we were doing, saying it over and over and just laughing it up.


Here's a list of more abbreviations and how I pronounce them (Want to add to the list? Send me a message!):


.doc      dock
SQL     ess-cue-el
.pdf       pee-dee-eff
.txt        text
.xls        ex-el-ess
CNN    see-en-en
SNL     ess-en-el
.jpg       jay-peg
.bmp     bitmap
.png      ping
.gif        gif
.psd      pee-ess-dee
.exe      e-ex-e
.dll        dee-el-el
.ocx      oh-see-exe
.vox      vox
.cs        see-ess
.vb       vee-bee
LDS     el-dee-ess

Thursday, October 8, 2009

Kaboodle & Twitter Open Job Postings

My sister had made me aware of a job opening at the company she works for, Kaboodle, so i thought i'd pass the information along in case any of you lived in that area or planned on moving out to that area :)

Sr. User Interface Designer
http://hotjobs.yahoo.com/job-JPVA96SVGD4

And also today Al3x, from Twitter, tweeted about a job opening there for Twitter..

Developer Support
http://static.twitter.com/jobvite_frame.html?nl=1&jvi=oWCcVfwp,Job&jvs=AlexTwitter