Archive for June, 2008

It’s funny - I work on Silverlight all day and then I come home and work on… Silverlight. I was working on a project last night, and my wife said “Oh, that’s kind of like an Etch-A-Sketch”. I then felt compelled to build a Silverlight Etch-A-Sketch, so here it is. The whole project took me a total of 45 minutes, and the majority of that was spent trying to find a background image that was big enough to suit my needs.

The application starts out by setting the X and Y values of a point to the center of the drawing surface. Each time one of the arrow keys is pressed, the “cursor” moves in that direction, leaving a point on the drawing surface. I initially had the project set up to use a polyline object, and add points to the PointCollection as the arrows were pressed, but I found a quirk with that functionality. Instead, I created a “pointEllipse” user control, which is a 1×1 pixel ellipse the color of the “pen” that draws on the drawing surface. Each time you press a key, an instance of the pointEllipse is placed on the drawing surface at the appropriate location.

Here’s how the code breaks down:

I set up a new point object to hold the next coordinates assigned each time the cursor moves. X and Y store the current X and Y location of the cursor. Step defines the distance the cursor will travel each time a key is pressed.

Point nextPoint = new Point();
double x;
double y;
double step = 1;

Next, I get the center of the drawing canvas and place a copy of the pointEllipse element there. Also, a few event listeners are wired up. One to take user input on KeyDown, one when the “Shake It!” button is pressed to clear the drawing, and one when the “OK” button is pressed on the instruction pane.

public Page()
{
InitializeComponent();

x = drawingCanvas.Width / 2;
y = drawingCanvas.Height / 2;
nextPoint.X = x;
nextPoint.Y = y;

pointEllipse pE = new pointEllipse();
pE.SetValue(Canvas.LeftProperty, x);
pE.SetValue(Canvas.TopProperty, y);
drawingCanvas.Children.Add(pE);

this.KeyDown += new KeyEventHandler(Page_KeyDown);
clearButton.Click += new RoutedEventHandler(clearButton_Click);
okButton.Click += new RoutedEventHandler(okButton_Click);
}

When the app loads, the background is drawn and the center point is added. The instruction pane is shown. When the “OK” button is pressed, the instructions are hidden with the following event handler.

void okButton_Click(object sender, RoutedEventArgs e)
{
instructions.Visibility = Visibility.Collapsed;
}

When keys are pressed, the event handler code adjusts the X or Y value depending upon which key was pressed. If the X or Y values go beyond the boundaries of the drawing canvas, they are not permitted to advance. The adjustments you see in the boundary code checks are because I got a little sloppy when I put the drawing canvas in place. Once the keyboard input is handled, a function called doDraw() is called.

void Page_KeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Up:
y -= step;
if (y <= 17) y = 17;
break;
case Key.Left:
x -= step;
if (x <= 17) x = 17;
break;
case Key.Right:
x += step;
if (x > drawingCanvas.Width - 10) x = drawingCanvas.Width - 10;
break;
case Key.Down:
y += step;
if (y >= drawingCanvas.Height - 10) y = drawingCanvas.Height - 10;
break;
default:
// do nothing
break;
}
doDraw();
}

The doDraw function creates an instance of the pointEllipse object and drops it on the drawingCanvas object after positioning it based on the current values of X and Y.

void doDraw()
{
pointEllipse pE = new pointEllipse();
pE.SetValue(Canvas.LeftProperty, x);
pE.SetValue(Canvas.TopProperty, y);
drawingCanvas.Children.Add(pE);
}

The last function is the event handler for when the “Shake It!” button is pressed. If you remember on an Etch-A-Sketch, shaking them is how you erase your drawing. To do that, I clear all the children off of the drawing canvas and reset the cursor to the center of the drawing canvas.

void clearButton_Click(object sender, RoutedEventArgs e)
{
drawingCanvas.Children.Clear();
x = drawingCanvas.Width / 2;
y = drawingCanvas.Height / 2;
nextPoint.X = x;
nextPoint.Y = y;
}

If you want to see the game, you can check it out here.

If you would like to play with the project, you can download all the code here.

If someone has the patience/ability to draw something really cool, send me a screen shot. =)

OK, Dave’s picking on me, so I’ll bite. =)

How old were you when you first started programming?
I was 12 or 13. This was back in 1982 or 1983. My dad got an Apple ][+ that I started plugging away on, in GW-Basic, I believe. Once I got rolling, I started grabbing all the books and magazine subscriptions I could. Back then, a lot of program listings were provided in Assembly, so I would literally spend HOURS typing in lines of hex code to get programs out of the magazines to run.

How did you get started in programming?
I don’t remember what actually got me into programming on our Apple. I do remember when I was very young, my father would bring me into work with him on the weekends sometimes - he worked at Tandem Computers, which was later acquired by Compaq. I would sit there at a terminal and play Eliza or one of the football games the programmers there had created. If I can point to anything that piqued my interest along the way, that would be it.

What was your first language?
GW-Basic.

What was the first real program you wrote?
When I was 13, I remember all I wanted to do was be a programmer. Somewhere along the way, I grew away from that desire and did other things for a while until getting into web development in my early 20s. So, “real” program, I don’t know. I wrote a pretty kick-ass Star Trek program back in ‘83 or ‘84, using graphic sprites and audio through a Mockingboard on the Apple, which by then had been chipped to upgrade to an Apple //e.

What languages have you used since you started programming?
Once you get going, you just can’t get enough. I’ve done Assembler, C, Cobol (bleh), Pascal, C++, Basic, Fortran, Java, C# and VB. At the time, C was my favorite - we’d write Assembler code inline for video card initialization. Boy have times changed! I like C# now. Go figure…

What was your first professional programming gig?
I worked for a bit doing Java for an online domain name acquisition company, but never got deeply into it. There’s been bits and pieces through my web development here and there, but I suppose I consider my current job the “real deal”, since it’s almost purely coding most of the time.

If you knew then what you know now, would you have started programming?
Yes, and I’d have been rich from Yahoo stock, too! The only thing I would have changed was that I would not have let my desire to be a developer get away from me for so long, but hey, that’s life.

If there is one thing you learned along the way that you would tell new developers, what would it be?
Find a mentor. The amount of information can be overwhelming, and if you’re lucky, you can find someone willing to help bring you along. You don’t want someone to give you the answers, but it’s great to have people to bounce ideas off of when you hit a spot where you could use some input.

What’s the most fun you ever had programming?
What can I say? Silverlight. The variety of programs I get to produce in my current role keeps it interesting and fun. Anyone that is a challenge but gets done on time is the most fun. =)

What’s the most fun you’ve ever had … programming?
I’m sure there’s a road trip or two that would rank highly as “most fun”, but programming is fun - I can look forward to getting up and going to work each day to dig into whatever project we have on the board.

Who are you calling out?
Rob Houweling
Adam Kinney (how did he slip by this?)
Michael Washington (that’s two, Michael!)

Generally speaking, I’ve had decent luck upgrading my beta 1 applications to beta 2. The one exception to that was the Twemes client I wrote, which currently resides at http://www.toysfortweets.com. The changes made to the cross-domain policy seemed simple enough - include a “headers” attribute when using HttpWebRequest. Unfortunately, *nothing* I was doing seemed to help.

This is one of those situations where I don’t have control over the target domain name, but the people who run it were kind enough to place a Flash policy file up there for me. I didn’t want to keep asking them to make changes, so I placed the files on another domain we have control of, and worked from that. I installed the Web Development Helper recommended in this great post by Tim Heuer. This gave total visibility into what was happening when I loaded the page, and there were a couple of problems. Eventually I got the problems fixed, but still no love.

The site loaded the application, the application called out to check for the Silverlight cross-domain policy file, which returned a 406 (Not Acceptable), then called out to check for the Flash cross-domain policy which returned a 200 (OK). Having that, the app called out for the RSS feed, which returned 200, and 19K of data. After that, silence. The callback function was not executing. This leads me to believe there may be a quirk in Silverlight when the Flash cross-domain policy file is in play. Silverlight took the file as OK, but it didn’t recognize the data needed to make the app go had come back. I tried several variations of the file based on different posts I found on the Silverlight.net forums, but nothing worked.

Finally, out of frustration, I created a simple version of the project that was still failing to execute the callback and sent it off to Tim Heuer for a more experienced set of eyes. He didn’t have any insight as to why HttpWebRequest was not executing the callback, but suggested I use WebClient instead. There is an older post on Tim’s site describing how to call web services. The example code was a big help in changing over to WebClient from HttpWebRequest.

The Flash cross-domain policy on the target domain currently looks like this:

<cross-domain-policy>
  <allow-access-from domain=”*” />
</cross-domain-policy> 

The code to call out for the file now looks like this:

WebClient rest = new WebClient();
rest.DownloadStringCompleted += new DownloadStringCompletedEventHandler(rest_DownloadStringCompleted);
rest.DownloadStringAsync(new Uri(”RSS FILE NAME“));

This returns the data as e.Result in the DownloadStringCompleted event handler:

XDocument doc = XDocument.Parse(e.Result);

This now means I can use the information in “doc”:

var items = from g in doc.Descendants(”item”)
    select new
    {
         title = g.Element(”title”).Value,
         description = g.Element(”description”).Value,
         pubDate = g.Element(”pubDate”).Value,
         guid = g.Element(”guid”).Value,
         link = g.Element(”link”).Value,
    };

Once the data was organized, I populate arrays based on the data I need. The reason why I did it this way is because the app displays random posts, so it’s easy to reach in and grab an element out of the array.

foreach (var item in items)
{
    i++;
    rssDescriptions[i] = item.description;
    rssLinks[i] = item.link;
    rssPubDates[i] = item.pubDate;
}

I was going to use a multidimensional array, but I’m not tracking that much data, so it’s easier to keep track of this way. So now whenever a new post is detected in the RSS, the app will display the first post, then generate 4 random numbers to grab other posts out of the feed for display.

I have updated both the Bird Hunt and Tank Combat games to run in beta 2. The downloadable zip files were also updated.

I recently put together a proof of concept app for displaying “twemes” - hash-tagged tweets from Twitter (spell check is having a field day!). Twemes.com is a site that aggregates posts made to Twitter that contain various hash (#) tagged terms into RSS feeds.  We wanted to do something for TechEd (#teched08) and this app was the end result.

This was a fun project to work on. It’s the first time I’ve done any cross-domain work. I initially ran into trouble grabbing the RSS feed due to the lack of a cross-domain policy file. I was using Yahoo Pipes and had good luck with that, but through ongoing conversations with the people that run twemes.com, got a cross-domain policy put in place that allows me to consume the feed. Very cool of them to help me out.

The app displays 5 chat bubbles. The one with the orange time stamp is always the top post from the feed, the other 4 are selected at random. The app periodically checks the feed for new posts and if one is found, the bubbles disappear and then reappear with new data. Unfortunately, TechEd attendees are not Twittering heavily (or not using the tag), so you might have to watch it for a while to see it change (or post if you have a Twitter account).

You can see it live at http://www.toysfortweets.com.