Welcome to Smips.com Sign in | Join | Help

Code Badger (Brad Tutterow's Blog)

Brad Tutterow is a consultant that likes Microsoft development technologies.
Presenting at .NET User Group – Feb 22

I’ll be presenting on Inversion of Control with StructureMap at the next meeting of the .NET user group.  It will be exactly as awesome as it sounds.

Simplify your life with Inversion of Control! One of the most challenging aspects of software development is dealing with code that depends on other code. The Dependency Inversion principle tells us that we should depend on abstractions, not concretions but it doesn’t tell us how to do that. That’s where Dependency Injection comes in – we inject our dependencies into the mushy center of our classes with a big syringe. This can often be as messy as it sounds, but luckily Inversion of Control Containers can help us by providing a single source for configuring dependencies. This presentation will show how to effectively manage dependencies with StructureMap, an open-source IOC container. StructureMap can make your life easier, your code more maintainable, and the world a better place.

http://www.stlnet.org/DesktopDefault.aspx

Share this post: Email it! | bookmark it! | digg it! | reddit!
Building a Silverlight Game : Part 8 : Writing Code to Drag Rectangles

Introduction and Review

This is the eight post in a series on building a Silverlight game.  In the last post, we talked about all the steps that we need to take to drag a rectangle around.  In this post, we’ll write the code to satisfy all those steps and let us drag our rectangles around the canvas.

For the sake of review, remember that in Part 6 we wrote code to prepare a rectangle for dragging.  This included

  1. Setting a flag that tells us a rectangle is being dragged
  2. Adjusting the opacity of the rectangle to provide a nice visual effect
  3. Capturing the mouse so the rectangle will be sure to respond to mouse events
   1: public void StartDrag(Rectangle rectangle)
   2: {
   3:     if (rectangle.Cursor.Equals(Cursors.Hand))
   4:     {
   5:         dragging = true;
   6:         rectangle.CaptureMouse();
   7:         rectangle.Opacity = 0.6;
   8:     }
   9: }

That will set up a rectangle for dragging.  The code that will drag the rectangle around (Part 7) needs to do these things:

  1. Check the flag to make sure it’s true
  2. Remove the rectangle from the stack panel
  3. Place the rectangle on the canvas so we can drag it around
  4. Bring the rectangle forward
  5. Move the rectangle to the current position of the mouse

Wiring up the proper event

The first thing to do is to decide when we want to do all these things.  In other words, what event of what object?  The answer (for now) is that we want to do these things when the MouseMove event of the topmost rectangle fires off.  To get things started in blend, just select the top-most rectangle in the object explorer, switch your properties tab to the event view, and double-click inside the MouseMove event’s textbox.  This will auto-generate an event handler method and wire it up in the XAML. 

image

If you’re not using Blend, the same event can be wired up manually in Visual Studio.

   1: <StackPanel x:Name="LeftPanel" Orientation="Vertical" 
   2:     Canvas.ZIndex="1" VerticalAlignment="Bottom">
   3:     <Rectangle Height="50" Width="100" Fill="Orange" 
   4:                MouseEnter="Rectangle_MouseEnter" 
   5:                MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" 
   6:                MouseMove="Rectangle_MouseMove" />
   7:     <Rectangle Height="50" Width="110" Fill="Blue" />
   8:     <Rectangle Height="50" Width="120" Fill="Green" />
   9:     <Rectangle Height="5" Width="120" Fill="Black" />
  10: </StackPanel>

Just like we’ve done with all of our other rectangle events so far, we are going to delegate the actual work to the DragAndDrop.cs class.

   1: private void Rectangle_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
   2: {
   3:     dragAndDrop.Drag(
   4:         sender as Rectangle,
   5:         e.GetPosition(null));
   6: }

The Drag() method

You can see that we’re calling a Drag method on the instance of DragAndDrop.  This method wants to know the rectangle to drag and the current position of the mouse.  Now we just need to write this method.

First things first, here’s the entire Drag() method. 

   1: public void Drag(Rectangle rectangle, Point position)
   2: {
   3:     if (dragging)
   4:     {
   5:         StackPanel panel = rectangle.Parent as StackPanel;
   6:         if (panel != null)
   7:         {
   8:             originalParent = panel;
   9:             panel.Children.Remove(rectangle);
  10:             draggingCanvas.Children.Add(rectangle);
  11:             Canvas.SetZIndex(rectangle, 5);
  12:         }
  13:         mover.Move(rectangle, position);
  14:     }
  15: }

Let’s step through this one line at a time. 

On line 3, we’re checking our dragging flag.  Since this method will be called whenever the rectangle’s MouseMove event fires, we want to make sure that we really should be dragging before we start moving things all over the screen.

On line 5, we put the rectangle’s parent in a local variable.  This is so we can put the rectangle back where it belongs in things go awry.

On line 6, we check to see if the rectangle’s parent is null.  If it is, then that means the cast to StackPanel failed (line 5).  And that means that the parent is not a stack panel.  And THAT means that rectangle is on the canvas.  And if the rectangle is on the canvas, then we skip lines 8 – 11, since those lines put the rectangle on the canvas.  Remember that this is being called over and over as the mouse moves across the screen.

On line 8, we keep track of the original parent.  On line 9, we remove the rectangle from it’s parent stack panel.  On line 10, we place the rectangle on the dragging canvas.  And on line 11, we bring the rectangle to the front of the screen.

Finally, one line 13, we call out to another class that will actually move the rectangle.  We haven’t written the code for this class yet.

If you paste the code for the Drag() method into your copy of DragAndDrop.cs, you’ll notice it doesn’t compile.  We just have to make a handful of changes to get things all wired up and working.

The first problem is that we don’t have a field variable for the original parent.  The next problem is that we don’t have a reference to a dragging canvas.

DragAndDrop’s new constructor

Both of these problems are resolved by changing our field declarations and constructor definition.

   1: private Canvas draggingCanvas;
   2:  
   3: private bool dragging = false;
   4: private Panel originalParent;
   5:  
   6: public DragAndDrop(Canvas draggingCanvas)
   7: {
   8:     this.draggingCanvas = draggingCanvas;
   9: }

Now we have fields for the dragging canvas and the original parent.  Notice also that we added the dragging canvas as a parameter for the constructor.  We’re telling anyone that wants to create an instance of a DragAndDrop helper that they better provide a canvas to use.

If you remember, it’s MainPage.xaml.cs that is currently creating an instance of the DragAndDrop helper.  So we need to change the code there to pass in the dragging canvas.  In this case, the dragging canvas is the layout root for the main page.

   1: public MainPage()
   2: {
   3:     InitializeComponent();
   4:     dragAndDrop = new DragAndDrop(this.LayoutRoot);
   5: }

The RectangleMover class

At this point, the only thing that’s preventing our code from compiling is line 13 of the Drag() method above. 

   1: mover.Move(rectangle, position);

To get this working, we need a class that move a rectangle around the canvas … a mover.  This class will be very dumb.  While the DragAndDrop class has all the logic associated with dragging a rectangle around, the mover will just know how to move a rectangle within the bounds of a canvas.

The code for this class looks like this:

   1: public class RectangleMover
   2: {
   3:     private double heightLimit;
   4:     private double widthLimit;
   5:  
   6:     public RectangleMover(double heightLimit, double widthLimit)
   7:     {
   8:         this.heightLimit = heightLimit;
   9:         this.widthLimit = widthLimit;
  10:     }
  11:  
  12:     public void Move(Rectangle rectangle, Point position)
  13:     {
  14:         double left = CalculateRectangleLeft(rectangle, position);
  15:         double top = CalculateRectangleTop(rectangle, position);
  16:         Canvas.SetLeft(rectangle, left);
  17:         Canvas.SetTop(rectangle, top);
  18:     }
  19:  
  20:     private double CalculateRectangleTop(Rectangle rectangle, Point position)
  21:     {
  22:         double top = position.Y - (rectangle.ActualHeight / 2);
  23:         double maxTop = this.heightLimit - rectangle.ActualHeight;
  24:         double minTop = 0;
  25:         if (top >= maxTop)
  26:         {
  27:             return maxTop;
  28:         }
  29:         if (top < minTop)
  30:         {
  31:             return minTop;
  32:         }
  33:         return top;
  34:     }
  35:  
  36:     private double CalculateRectangleLeft(Rectangle rectangle, Point position)
  37:     {
  38:         double left = position.X - (rectangle.ActualWidth / 2);
  39:         double maxLeft = this.widthLimit - rectangle.ActualWidth;
  40:         double minLeft = 0;
  41:         if (left >= maxLeft)
  42:         {
  43:             return maxLeft;
  44:         }
  45:         if (left < minLeft)
  46:         {
  47:             return minLeft;
  48:         }
  49:         return left;
  50:     }
  51: }

This class can look a bit intimidating, but it doesn’t really do anything interesting.  It has one public method that takes a rectangle and a position.  It moves the rectangle to that position.  Feel free to explore the class on your own, but we’ll leave it at that for our purposes here.

Now we just need to instantiate an instance of RectangleMover when we instantiate our DragAndDropClass, so DragAndDrop gets a new constructor a new instance field.

   1: private Canvas draggingCanvas;
   2: private RectangleMover mover;
   3:  
   4: private bool dragging = false;
   5: private Panel originalParent;
   6:  
   7: public DragAndDrop(Canvas draggingCanvas)
   8: {
   9:     this.draggingCanvas = draggingCanvas;
  10:     mover = new RectangleMover(
  11:         draggingCanvas.Height,
  12:         draggingCanvas.Width);
  13: }

Running the game

If we run the game now, we can now drag the top rectangle around the canvas.  But we can’t drop it yet.  That’s for next time!

image

Download the source code so far

Share this post: Email it! | bookmark it! | digg it! | reddit!
Paint.NET: The friendliest update in town

As far as update processes go, Paint.NET has the best in town. Just check out this dialog that you see when launching the program and note how friendly it is.  It’s saying "Hi!  I’m sure you have some image editing to do.  When you’re done, I’d be happy to update myself.  Just let me know.”  Thanks, Paint.NET!

PaintNETInstall

Let’s see how some other software on my machine stacks up.  Here’s Adobe.  It doesn’t even wait until I use the software, but just pops up at random times throughout the day.  Actually, this screenshot isn’t even from my machine since I get so annoyed at Adobe Updater I don’t allow it to run.

AdobeUpdater

FileZilla and Firefox are a little better, in that they only pop up when I’m using the software.  But not quite as friendly as Paint.NET since they expect me to either install the update before I use the software or not install the update.  This isn’t bad, but not near as slick as Paint.NET.  When I launch software, I want to USE it, not UPDATE it.

auomatic-check

 FireFoxUpdate 

So my hat’s off to the guys at Paint.NET for letting me update my software while staying out of my way!

Share this post: Email it! | bookmark it! | digg it! | reddit!
Fixing Outlook Pet Peeves with Quick Steps

One of the new features in Outlook 2010 is Quick Steps.  Quick Steps let you chain multiple Outlook actions together into an easy-to-access action that shows up in the “Home” tab of the ribbon.  Kinda like macros, I suppose, but friendlier.

Outlook 2010 comes with a few handy Quick Steps by default, including one to forward an email to your manager, send an email to your team, or send an email to a folder.

image 

It’s also super easy to create a new Quick Step.  I used one to solve one of my biggest pet-peeves about Outook: deleted items are not automatically marked as read.  By default, when you delete an email from your inbox without reading it, Outlook moves the message to your “Deleted Items” folder but is still marked as unread

image

This is crazy frustrating, because now I have a blue “1” in parentheses, meaning I have unread email.  Technically, this is true – I didn’t read it – but in practice, this drives me nuts, because the reason I deleted it is that I didn’t want to read it.

Quick Steps to the rescue …

image

Here I’ve defined a Quick Step that will mark a message and read and then delete it.  Even better, I can add a keyboard shortcut.  Nice!  No more unread email in my trash can.

Share this post: Email it! | bookmark it! | digg it! | reddit!
Building a Silverlight Game : Part 7 : Getting Started with Dragging Rectangles

This is the seventh post in a series on building a Silverlight game.  In the last post, we wrote code to set up a rectangle for dragging.  In this post, we’ll look at what it will take to drag the rectangle around the playing area.

Recap

So we don’t lose sight of the big picture, remember that our overall goal is to build a Towers of Hanoi clone that looks like this:

CropperCapture[3]

And so far, we’ve built a Towers of Hanoi clone that looks like this:

image

The current part of the game that we’re working on is the code to drag rectangles around the playing area since that’s pretty much the only thing there is to the game.  Last week, we wrote the code that sets up a rectangle for dragging.  Remember that this involved three things

  1. Setting a flag that tells us a rectangle is being dragged
  2. Adjusting the opacity of the rectangle to provide a nice visual effect
  3. Capturing the mouse so the rectangle will be sure to respond to mouse events

Dragging

This week, we’ll think about the code that we need to write to drag the rectangle around the canvas. There are five things that need to happen to move the rectangle around

1) We have to check the flag that was set previously.  If a dragging operation is not current, we certainly don’t want rectangles moving around the screen.  So we’re only going to drag things around the screen if the flag is set to true.

2) We need to get the rectangle out of the stack panel (remember that our rectangles are sitting in a stack panel).  Items in a stack panel have to be in a stack.  Think of the stack of papers on your desk.  You can’t drag them around while they’re in the stack; you have to get them out first. 

   1: <StackPanel x:Name="LeftPanel" Orientation="Vertical" 
   2:     Canvas.ZIndex="1" VerticalAlignment="Bottom">
   3:     <Rectangle Height="50" Width="100" Fill="Orange" 
   4:                MouseEnter="Rectangle_MouseEnter" 
   5:                MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
   6:     <Rectangle Height="50" Width="110" Fill="Blue" />
   7:     <Rectangle Height="50" Width="120" Fill="Green" />
   8:     <Rectangle Height="5" Width="120" Fill="Black" />
   9: </StackPanel>

3) We need to place the rectangle somewhere that it can be dragged.  The root canvas is perfect for this.  Remember that our three stack panels are contained in a canvas.  A canvas container keeps track of its children by exact position, which is perfect for dragging.  Imagine that we’re taking a piece of paper from the stack on your desk and placing it on the desk to drag it around.

   1: <Canvas x:Name="LayoutRoot" Width="800" Height="430">
   2:     <Border Height="380" Width="257" Canvas.Left="15">
   3:         <StackPanel x:Name="LeftPanel" Orientation="Vertical" 
   4:             Canvas.ZIndex="1" VerticalAlignment="Bottom">
   5:             <Rectangle Height="50" Width="100" Fill="Orange" 
   6:                        MouseEnter="Rectangle_MouseEnter" 
   7:                        MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" />
   8:             <Rectangle Height="50" Width="110" Fill="Blue" />
   9:             <Rectangle Height="50" Width="120" Fill="Green" />
  10:             <Rectangle Height="5" Width="120" Fill="Black" />
  11:         </StackPanel>
  12:     </Border>

4) We need to bring the rectangle forward, closer to the player.  We don’t want the rectangle to accidentally get dragged behind another graphic or another rectangle, so we’ll set the ZIndex to make sure that any rectangle that is currently being dragged is the front-most object.

5) And finally, the most important thing of all, we need to move the rectangle to the current position of the mouse so that as the player moves the mouse the rectangle moves with it.  That’s the essence of dragging after all.

Conclusion

So that’s it.  If we can write code to do those five things, we can drag a rectangle around the playing area.  Next post, we’ll write the code to do those things.  We didn’t write any code this week, so the code from last week will still be the most recent.

Share this post: Email it! | bookmark it! | digg it! | reddit!
Speaking at Iowa Code Camp

I’ll be speaking at the Iowa Code Camp in Des Moines, IA on November 7th.  Should be great Iowa weather!  The topic will be Ruby on Rails for .NET/Java Developers.

The Iowa Code Camp is a completely free, one-day event and registration is still open.  Should be a lot of fun.

Share this post: Email it! | bookmark it! | digg it! | reddit!
Building a Silverlight Game : Part 6 : Setting up a rectangle for dragging

This is the sixth post in a series on building a Silverlight game.  In the last post, we wrote code to change the cursor into a hand when the player mouses over the orange rectangle.

image

Introduction

In this post, we’ll write some code to set up a rectangle for dragging and dropping.  If we think about the idea of dragging a rectangle around the screen, there are a few things we need to take are of before a rectangle is ready to be dragged around.

  1. We need to set a flag that we’re dragging.  When we drag, we’re going to tie that to the rectangle MouseMove event and we don’t want to drag all the time, just when we’re supposed to.  So we’ll set a flag to tell us that dragging is currently active. That will prevent rectangles from being dragged around the screen every time the player mouses over them.
  2. We need to adjust the opacity of the rectangle to provide a nice visual effect. This will distinguish the dragged rectangle from the rest of the rectangles.
  3. We need to capture the mouse.  It is possible in Silverlight to move the cursor so fast that the cursor will come out of the item being dragged.  When we capture the mouse we tell Silverlight to keep responding to events as if the mouse was still inside the item being dragged.

Adding the MouseLeftButtonDown event handler

 

Our first task is to wire up the MouseLeftButtonDown event for the orange rectangle.  This is easiest in Blend.  Just select the orange rectangle, open the Properties tab, and then hit the event button in the upper right.  This will display all the events that we can wire up for the rectangle.  Double-click inside the MouseLeftButtonDown textbox to have Blend automatically create an event handler.

image

 

 

If you would rather use Visual Studio, you can just manually add the event handler code to the rectangle’s XAML and then add the Rectangle_MouseLeftButtonDown method to the XAML’s code-behind.

   1: <Rectangle Height="50" Width="100" Fill="Orange" 
   2:            MouseEnter="Rectangle_MouseEnter" 
   3:            MouseMove="Rectangle_MouseLeftButtonDown " />

 

   1: private void Rectangle_MouseLeftButtonDown (object sender, MouseEventArgs e)
   2: {
   3:     // TODO: Add event handler implementation here.
   4: }

 

 

 

 

Inside the Rectangle_MouseLeftButtonDown event handler, we’ll make a call to do the three things that are required to set up a rectangle for dragging and dropping: setting the flag, changing the opacity, and capturing the mouse.  We don’t want to put all of this code in our code-behind though, so let’s write a new class called “DragAndDrop” that can contain all of drag-and-drop logic. 

But first, let’s write the code that will call our new class.  As you can see below, we’re going to call an instance of our DragAndDrop class’s StartDrag method and send it the rectangle that we want to start dragging.

   1: private void Rectangle_MouseLeftButtonDown(object sender, 
   2:      MouseButtonEventArgs e)
   3: {
   4:     dragAndDrop.StartDrag(sender as Rectangle);
   5: }

The DragAndDrop class

The DragAndDrop class is nice and simple.  It has a boolean that knows if something is being dragged or not and it has one method that can start the dragging process for a given rectangle.

 

   1: public class DragAndDrop
   2: {
   3:     private bool dragging = false;
   4:  
   5:     public void StartDrag(Rectangle rectangle)
   6:     {
   7:         if (rectangle.Cursor.Equals(Cursors.Hand))
   8:         {
   9:             dragging = true;
  10:             rectangle.CaptureMouse();
  11:             rectangle.Opacity = 0.6;
  12:         }
  13:     }
  14: }

The StartDrag method first checks to see if the rectangle’s cursor is a hand.  If it is, then we know that this rectangle must be on top and so is eligible for dragging.  This will prevent players from dragging rectangles that are not on top.

If the rectangle is on top, we just do the three things required to start dragging

  1. Set the boolean to true
  2. Capture the mouse so events on the rectangle will continue to fire even if the mouse leaves the rectangle’s area
  3. Set the opacity of the rectangle to 0.6.  This means that the rectangle being dragged will be 40% see through.

In our next post, we’ll write some code to actually drag the rectangle around the canvas. 

Download source code so far

Share this post: Email it! | bookmark it! | digg it! | reddit!
Screencast: Silverlight 3 and ADO.NET Data Services

Here’s a short screencast that explores using ADO.NET Data Services (Astoria) to provide data for a Silverlight 3 navigation application.  The screencast is just a bit over thirty minutes and is about 1/3 slides and 2/3 demo.

The screen cast covers

  • A brief overview and history of Silverlight
  • Overview of data access options in Silverlight
  • Comparison / contrast between ADO.NET Data Services and RIA Services
  • Demo showing how to
    • use Visual Studio to create an ADO.NET Data Service that exposes and ADO.NET Entity Data Model
    • use Expression Blend to wire up a Silverlight Navigation Application to Expression Blend Sample Data
    • use Visual Studio to wire up a Silverlight Navigation Application to communicate with an ADO.NET Data Service

image

Download (WMV, 45MB)

Share this post: Email it! | bookmark it! | digg it! | reddit!
Using Converters Instead of Custom Client Properties with Silverlight and ADO.NET Data Services

One challenge with ADO.NET Data Services is that it has trouble understanding what’s going on if you add custom properties to your entities on the client side.  This post will explain using converters to overcome that challenge when using Silverlight.  Or WPF, I suppose.

Background

When you add a reference to an ADO.NET Data Service, Visual Studio generates a set of client classes that represent the entities on the server.  These classes are tantalizing marked as partial, which could lead you to believe that you are welcome to add additional client-only properties to these classes.

   1: [global::System.Data.Services.Common.DataServiceKeyAttribute("Id")]
   2: public partial class Employee
   3: {
   4: }
 
However, if you extend the partial class to add a property, ADO.NET Data Services will be grumpy when you try to save your object since it won’t know what to do with the extra property.

Let’s say that we want to add an extra property to our Employee class called “HasCornerOffice” that returns “true” if the employee has “VP” in their title.  Something like this.

   1: public partial class Employee 
   2: {
   3:     public bool HasCornerOffice 
   4:     {
   5:         get { return this.Title.StartsWith("VP");  }
   6:     }
   7: }

When you try to save an instance of an employee back to the database, you’ll get an error along the lines of “Error processing request stream. The property name ‘HasCornerOffice’ specified for type ‘Employee’ is not valid.”  ADO.NET Data Services has no idea what the property is all about and is letting us know.

Some Solutions

There are a few ways around this. 

You could use a brand-new client-only class that can be mapped to and from Employee.  Adding this layer of abstraction could make a lot of sense and add some insulation between your client and server that could come in handy later.  Not a bad way to go for the trade-off of writing and maintaining the mapping code to back and forth between the client and server objects.

You could also customize the way that objects are serialized by digging into the bowels of the data context and intercepting the ATOM request before it is send to the server.  Not sure what this would do if you were using JSON, but this blog post has the details for wiring it up with an ATOM request.

Using Convertors

An alternate quick and easy solution is to leave the client-side entities as-is and use a converter to transform our Employee data into the data that we want to display.  This has the advantage of being straightforward and low-impact, but is maybe not as flexible or extensible long-term as the two solutions above.

Using the same Employee example as above, our Converter would look like this.

   1: public class CornerOfficeConverter : IValueConverter
   2:  {
   3:      public object Convert(
   4:          object value, 
   5:          Type targetType, 
   6:          object parameter, 
   7:          CultureInfo culture)
   8:      {
   9:          if (string.IsNullOrEmpty(value as string))
  10:          {
  11:             return false;
  12:          }
  13:  
  14:          return value.ToString().StartsWith("VP");
  15:      }
  16: }

And we could bind to it like this.

   1: <TextBlock 
   2:     Text="{Binding Title, 
   3:            Converter={StaticResource TitleConverter}}" />

Conclusion

Hopefully, this shortcoming in ADO.NET Data Services will be resolved in the framework itself in the next version or so, but in the meantime, those are some ideas of how to work around the problem.

Share this post: Email it! | bookmark it! | digg it! | reddit!
Building a Silverlight Game : Part 5 : Changing the cursor

This is the fifth post in a series on building a Silverlight game.  In the last post, we finished our basic layout: three stack panels for the game rectangles, some rectangles to play with, and a bottom border for the rectangles to sit on.

image

With all of that set, we can start writing some code.  The first thing to do is let the user know which rectangle they are allowed to drag.  The rules of the game state that you can only drag the top rectangle around. In our case, this is the orange rectangle.

The standard way to let someone know that they can interact with an object is to change the cursor from the default arrow to a hand, so that’s what we’ll do.  We need to set things up so that when the player mouses over the orange rectangle, the cursor changes into a hand.

image

Blend makes event handling an n easy task through the events pane.  Select the orange rectangle, and then look for the lightning bolt icon over on the Properties tab.  This gives us access to all of the events available for the orange rectangle.

The one we want is the MouseEnter event.  Double-click inside of the textbox next to MouseEnter and Blend will create an event handler for us.

   1: public partial class MainPage : UserControl
   2: {
   3:     public MainPage()
   4:     {
   5:         InitializeComponent();
   6:     }
   7:  
   8:     private void Rectangle_MouseEnter(object sender, MouseEventArgs e)
   9:     {
  10:         // TODO: Add event handler implementation here.
  11:     }
  12: }

Blend 3 will let us write C#, but the experience is a better in Visual Studio.  If you don’t have Blend, you can accomplish the same event handle wire-up task by adjusting the XAML for your orange rectangle to look like the snippet below and then manually adding the Rectangle_MouseEnter code to your code-behind.

   1: <StackPanel x:Name="LeftPanel" Orientation="Vertical" 
   2:     Canvas.ZIndex="1" VerticalAlignment="Bottom">
   3:     <Rectangle Height="50" Width="100" Fill="Orange" 
   4:                MouseEnter="Rectangle_MouseEnter" />
   5:     <Rectangle Height="50" Width="110" Fill="Blue" />
   6:     <Rectangle Height="50" Width="120" Fill="Green" />
   7:     <Rectangle Height="5" Width="120" Fill="Black" />
   8: </StackPanel>

Inside of Rectangle_MouseEnter, we can write our code to change the cursor into a hand.  The easiest thing to do is this:

   1: private void Rectangle_MouseEnter(object sender, MouseEventArgs e)
   2: {
   3:     Rectangle rectangle = sender as Rectangle;
   4:     rectangle.Cursor = Cursors.Hand;
   5: }

We cast the sender of the event to a rectangle (because it is a rectangle) and then set the Cursor to Cursors.Hand. This does the job, but isn’t very flexible.  We eventually want this code to apply to all of our rectangles, not just the orange one, so let’s add some checks to make sure that the rectangle is on top of its stack.  We only want to change the cursor to a hand if the rectangle being moused over is on top.

So we adjust our Rectangle_MouseEnter to look like this:

   1: private void Rectangle_MouseEnter(object sender, MouseEventArgs e)
   2:  {
   3:      Rectangle rectangle = sender as Rectangle;
   4:      Panel panel = rectangle.Parent as Panel;
   5:      rectangle.Cursor = (RectangleIsOnTop(rectangle, panel))
   6:          ? Cursors.Hand
   7:          : Cursors.Arrow;
   8:  }

All we’re lacking now is the RectangleOnTop() method referenced by our new conditional logic.  Since the children (rectangles) of the stack panel are ordered by their index, with 0 being on top, such a method might look like this.

   1: private static bool RectangleIsOnTop(Rectangle rectangle, Panel panel)
   2: {
   3:     return panel.Children.IndexOf(rectangle).Equals(0);
   4: }

Now when we mouse over the orange rectangle, our cursor will change into a hand to indicate that we can drag the rectangle around.  In the next post, we’ll write some code to start dragging the rectangle around.

Share this post: Email it! | bookmark it! | digg it! | reddit!
Building a Silverlight Game : Part 4 : Finishing the basic layout

This is the fourth post in a series on building a Silverlight game.  In the last post, we polished off our three stack panels and added some rectangles to the first stack panel.

image

The challenge we left off with is how to get the rectangles down to the bottom where they belong.  Stack panels like to put their items at the top and then add subsequent items underneath, just like in HTML.

We can get around this by making our stack panel just tall enough to hold only the rectangles that are in it, and then forcing the entire stack panel down to the bottom.  This is accomplished by wrapping our stack panel in a border and taking away its height.

A border is an interesting Silverlight control that can have only one child.  It is best used for making borders of course, but it can also make a handy container.  There are some nice benefits of having a container control that you know will only ever have one child. 

To surround the panels with borders in Expression Blend, just right-click the panel and select “Group Into > Border”.  Blend is even kind enough to move our height from the stack panel to the border.  Repeat this for all of the panels. If you’re using Visual Studio, you can just skip ahead to the finished XAML below.

image

After surrounding the panels with borders, your object tree should look like this.

image

The next step is to get the panels to sit at the bottom of their panels.  This is done by selecting all three panels at once in the object explorer and changing their vertical alignment property to “Bottom”

image

Now all of the panels are sitting snugly at the bottom of their borders.  Remember that the empty space at the bottom is intentional.  We’ll fill that up shortly.

image 

Your finished XAML should look something a lot like this.  We have three stack panels, each wrapped in a border.  The first stack panel has three playable rectangles and a rectangle platform.

   1: <Canvas x:Name="LayoutRoot" Width="800" Height="430">
   2:     <Border Height="380" Width="257" Canvas.Left="15">
   3:         <StackPanel x:Name="LeftPanel" Orientation="Vertical" 
   4:             Canvas.ZIndex="1" VerticalAlignment="Bottom">
   5:             <Rectangle Height="50" Width="100" Fill="Orange" />
   6:             <Rectangle Height="50" Width="110" Fill="Blue" />
   7:             <Rectangle Height="50" Width="120" Fill="Green" />
   8:             <Rectangle Height="5" Width="120" Fill="Black" />
   9:         </StackPanel>
  10:     </Border>
  11:     <Border Height="380" Width="257" Canvas.Left="272">
  12:         <StackPanel x:Name="MiddlePanel" Orientation="Vertical" 
  13:             Canvas.ZIndex="1" VerticalAlignment="Bottom"/>
  14:     </Border>
  15:     <Border Height="380" Width="257" Canvas.Left="529">
  16:         <StackPanel x:Name="RightPanel" Orientation="Vertical"  
  17:             Canvas.ZIndex="1" VerticalAlignment="Bottom"/>
  18:     </Border>
  19: </Canvas>

The last thing we need to do to finish our basic layout is to fill up the bottom area.  For now, we’ll just use a boring gray rectangle.  Later, we’ll use brushes to spice it up a bit.

   1: <Rectangle x:Name="BottomRectangle" Height="50" Width="800" 
   2:            Canvas.Top="380" Fill="Gray"  />

After adding the bottom rectangle, our playing area looks like this.

image

And that’s it for basic layout.  In the next post, we’ll start writing some C# to enable dragging and dropping the rectangles.

Share this post: Email it! | bookmark it! | digg it! | reddit!
Windows 7 device pictures are worth 2^10 words

I’m impressed that Windows 7 knows what my thumb drive and mouse look like.  Curious that it doesn’t know what an iPhone looks like though.

temp

Share this post: Email it! | bookmark it! | digg it! | reddit!
Unit Testing Silverlight ViewModels (MVVM) That Make Asynchronous Calls

This post will look at using the Silverlight Unit Test Framework to make it possible to use TDD to test a ViewModel (MVVM) that is making asynchronous calls to ADO.NET Data Services.

With Silverlight 3, we have a collection of new ideas, technologies, and practices that sometimes collide in interesting ways. For example

  • Most sane people agree that data access in Silverlight should be done asynchronously to avoid blocking the UI thread and angering users.
  • Model-View-ViewModel is emerging as the most common way to loosely couple Silverlight application architectures.
  • TDD, or at least test-first development, is becoming increasingly recognized as a “good thing”.

If you’re anything like me, and you tried to combine these three things, you would find to your dismay that

  • The major unit testing frameworks don’t support Silverlight testing yet.  They expect to find binaries that are compiled against the full .NET framework.
  • These same unit testing frameworks don’t have anything built-in for asynchronous unit testing.  There are some things you can do about that, but it makes for hard-to-read, long tests.

Luckily, the Silverlight Unit Test Framework, now a part of the Silverlight Toolkit, goes a long way towards solving these problems.

The ViewModel

To start, let’s look at the ViewModel that we want to test.

   1: public void Load()
   2: {
   3:     DataServiceQuery<Meal> dataQuery = _context.Meals;
   4:     dataQuery.BeginExecute(LoadCompleted, dataQuery);
   5: }
   6:  
   7: private void LoadCompleted(IAsyncResult ar)
   8: {
   9:     var qry = ar.AsyncState as DataServiceQuery<Meal>;
  10:     if (qry != null)
  11:     {
  12:         var results = qry.EndExecute(ar);
  13:         foreach (var meal in results)
  14:         {
  15:             Meals.Add(meal);
  16:         }
  17:     }
  18:     InvokeLoadComplete();
  19: }

This ViewModel has one public method (Load()) that communicates with ADO.NET Data Services asynchronously.  When the data returns, the LoadCompleted() method is responsible for taking the data returned and using it to fill up a Meals property.  This Meals property is what our UI will bind to.

All we want to do is test that when the Load() method is called, the Meals property will be populated … eventually.  We can tell when the Meals property should be filled up because the ViewModel kindly fires off a LoadComplete event.

The Test Project

The first step is to create a test project following the instructions available on Jeff Wilcox’s blog. There are two sets of instructions there – I followed the manual ones so I could be sure of what was going on.

At this point, we’ll have two Silverlight applications: our real one, and the test one.  That looks like this in my Solution explorer.

image

The Test

Let’s take a look at what the test looks like.

   1: [TestMethod]
   2: [Asynchronous]
   3: public void Load_PopulatesAListOfNonNullMeals()
   4: {
   5:     bool done = false;
   6:     
   7:     var viewModel = new HomeViewModel();
   8:     viewModel.LoadComplete += (() => done = true);
   9:  
  10:     EnqueueCallback( viewModel.Load );
  11:     EnqueueConditional( () => done );
  12:     EnqueueCallback( () => Assert.IsNotNull(viewModel.Meals) );
  13:     EnqueueTestComplete();
  14: }

Lines 1 & 2: Our method is decorated with the standard MSTest “TestMethod” attribute to identify it as a test and is also decorated with “Asynchronous” to identify it as, well, an asynchronous test.

Line 5: Here we set up a boolean that we can check later to see if the asynchronous call has been completed.  Remember that our ViewModel fires off a “LoadComplete” event when it is finished talking to ADO.NET Data Services.

Line 7 and 8: We create the ViewModel and use a lambda expression to set our “done” boolean to “true” when the “LoadComplete” event fires.  This means that we can rely on our boolean to tell us if the “LoadComplete” has fired yet or not.

Line 10: This is the first of our Silverlight Unit Testing Framework nuttiness.  The “EnqueueCallback” method is available to us if our unit test inherits from SilverlightTest, which it does.

   1: [TestClass]
   2: public class HomeViewModelTests : SilverlightTest
   3: {
   4: }

“EnqueueCallback” tells our test to queue up some work to do.  In this case, the specific work that we’re asking the test to queue is the call to the Load() method on our ViewModel.  We have to use the “EnqueueCallback” syntax because the Load() method is going to be doing work asynchronously.  If we just called Load() and our test moved on, our test would arrive at its conclusion before any data came back from the server.

Line 11: This is the backbone of the test.  The “EnqueueConditional” method essentially tells our test to “hold your horses until the condition that I specificy is true”.  In this case, we’re having it look at our “done” boolean.  This prevents our test from moving forward until the ViewModel “LoadComplete” event is fired, since the boolean is tied directly to that event back on line 8.  You can put a breakpoint on this line and watch it get called over and over while the tests wait for “done” to be true.

Line 12: This is our standard assert method, but wrapped up in the “EnqueueCallback” method since we’re still working asynchronously.  Basically, once you start in with the “Enqueue” methods, you stick with them until the end of the test.

Line 13: This tells our test that we’re all done, and it needs to report back what happened.  If you omit this line, the test will run forever.  Or until you kill it.

Running the Tests

To run the tests, all you have to do is set your test application as the startup project, and hit F5.  Unless you are using ADO.NET Data Services as your back-end, that is.  Silverlight is not allowed to communicate with ADO.NET Data Services across servers, so your tests have to be running on the same server as your back-end data source.  If you see an ‘Access Denied’ error message running your tests, that’s why.

Fortunately, this is an easy problem to overcome.  In the Properties tab for the web project that is hosting your ADO.NET Data Services, just add the Silverlight testing project to the deployed Silverlight applications.

image 

Now you can set the startup project to be your web project, and set the startup page to be the host page for your Silverlight testing application.

image

Conclusion

And that’s that.  It’s a lot of hoops to jump through, and the tests look a bit odd and hard-to-read, but they would be odder and harder-to-read if you did all the async plumbing yourself, I would imagine.

Hopefully, the other unit testing frameworks will release their own solutions to this problem soon so we can have some good alternatives.  But in the meantime, this accomplishes my goal of doing TDD with MVVM in Silverlight.

Share this post: Email it! | bookmark it! | digg it! | reddit!
Building a Silverlight Game : Part 3 : Adding some rectangles

This is the third post in a series on building a Silverlight game.  In the last post, we created our game canvas and three stack-panels to hold our rectangles. Our goal is to create the Towers of Hanoi game pictured below.

CropperCapture[3]

We have our canvas set up and it has three stack-panels that will hold our rectangles.

   1: <UserControl x:Class="TowersTutorial.MainPage"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
   5:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
   6:     mc:Ignorable="d">
   7:   <Canvas x:Name="LayoutRoot" Width="800" Height="430">
   8:       <StackPanel Height="100" Width="100"/>
   9:       <StackPanel Height="100" Width="100"/>
  10:       <StackPanel Height="100" Width="100"/>
  11:   </Canvas>
  12: </UserControl>

We want to position these three stack panels so they each have an equal share of the canvas.  You’ll also notice that the stack panels do not extend all the way to the bottom of the canvas, but stop short to leave room for the “grass” that the rectangles are sitting on.

Replace the three boring stack panels with the code snippet below.  Notice that we’re explicitly setting the height, width, and Canvas.Left so these stack panels end up exactly where we want them.

   1: <StackPanel x:Name="LeftPanel" Orientation="Vertical"  
   2:             Height="380" Width="257" Canvas.ZIndex="1" Canvas.Left="15" />
   3: <StackPanel x:Name="MiddlePanel" Orientation="Vertical"  
   4:             Height="380" Width="257" Canvas.ZIndex="1" Canvas.Left="272"/>
   5: <StackPanel x:Name="RightPanel" Orientation="Vertical" 
   6:             Height="380" Width="257" Canvas.ZIndex="1" Canvas.Left="529"/>

Now we just need some dummy rectangles to sit in the first stack panel to simulate what things look like at the beginning of the game.  We’ll fancy things up shortly but these dummy rectangles will let us wire up our drag and drop logic.

You can create these rectangles in either Expression Blend or Visual Studio, but they should end up looking something like this.

   1: <Rectangle Height="50" Width="100" Fill="Orange" />
   2: <Rectangle Height="50" Width="110" Fill="Blue" />
   3: <Rectangle Height="50" Width="120" Fill="Green" />
   4: <Rectangle Height="5" Width="120" Fill="Black" />

If you don’t specify height and width, Silverlight will not allocate any room for the rectangles and they won’t be visible.  If you don’t specify a Fill (background color), they will be invisible.  It’s important to give all Silverlight controls some shape and color.

Now we have four rectangles.  The orange, blue, and green rectangles are our game pieces and the black rectangle is a platform for the other three to sit on.  If you view this in Blend (or run it from VS), you’ll see that our game is starting to take shape.

image

Next post, we’ll look into how to get those rectangles down at the bottom where they belong.

Share this post: Email it! | bookmark it! | digg it! | reddit!
Excel’s no quitter

It would appear that I’m not moving on to my next task after all.  I hope this is only a temporary moratorium on quitting.  I didn’t realize how much I need to quit until told I can’t.

image

Share this post: Email it! | bookmark it! | digg it! | reddit!
More Posts Next page »