Unni's Blog

Design, Expression Blend, Silverlight, WPF, Windows Phone

Designing FreeCell using Expression/VS toolsets

Designing FreeCell using Expression/VS toolsets

  • Comments 1

When I set out in the morning on this project, I only had one goal in mind – I wanted to understand the workflow in designing an application in collaboration with a developer. In this article, I will try and describe my experiences on this brief one-day journey and how much fun it turned out to be!

 

The first thing I did was to create all the card visuals once I knew I was doing FreeCell. All of the visuals are vectors done in Interactive Designer. Essentially, there are 4 drawing brushes for the 4 suites (created using the Tools -> Make Tile Brush -> Make Drawing Brush option in Interactive Designer).

 

FreeCell uses the Model View Controller (MVC) pattern that WPF makes it very easy to implement using it powerful data-binding feature. The model for the card game resides in 4 classes:

  1. Card.cs defines Card which is your regular card data structure.
  2. Cell.cs defines Cell – FreeCell has two kinds of cells – Home and Free.
  3. GameModel.cs defines GameModel which is the main game engine and holds the data-structures for the various card stacks and cells.
  4. RandomCardGenerator.cs defines a helper class that helps in generation of cards in random order using Enumeration – I brought this type in from a previous card game I wrote.

GameModel exposes all the data-structures as properties – such as HomeCells (which is collection of home cells), FreeCells and CardStacks. CardStacks is a collection of collections – each of which is collection of Cards. Using ObservableCollection (which is derived from IList) allows you to simply tweak the model (such as moving a card from one stack to another whenever a game event happens) and this will update the UI – all of this requires no UI manipulation code. GameModel also exposes a string for displaying the time on the game board. For ensuring that the UI updates each time a timer in the model ticks, you need to implement an Interface called INotifyPropertyChanged which will fire a PropertyChanged event whenever a property changes. You can the bind against this property in the view and forget about it – isn’t that a sweet separation between model and view?

 

So much for the code – which was written in VS. An Expression project flows smoothly into VS and back since they share the same infrastructure underneath – any changes you make in Expression and visible in VS and vice-versa – so you can have VS and Expression open side-by-side on two different monitors!

 

The next step was to get back into Expression Interactive Designer and make this thing look cool. I used a ViewBox at root of the game board (minus the status-bar like thing) so that things would scale correctly when the app was resized – one of the biggest complaints I have with the FreeCell that ships with Windows. Expression has powerful layout capabilities that make it every easy to control behavior when the app is resized, and you can do this without it being your main concern.

 

A custom Panel was required for stacking the various cards – so I put back my developer hat on and created CardStackPanel.cs. It exposes an Offset property that allows the designer to control the Offset on the design surface.

 

The rest of the UI creation was a breeze using Expression powerful data-binding feature – just drag and drop data (like the time string that you created previously in your model), choose the control that you want to display the data (in this case a TextBlock), select the property you want to bind to (Text in our case), and finally for more complex data-fields customize the look. To create a stack of stacks for the various cards on the game board, I used the default StackPanel that WPF provides (in horizontal mode) and each collection within it was laid out using the custom panel I wrote (and I set the Offset property to a value that made this look good).

 

One of the tricky things is that there really are no cards in these various data-structures till the game actually beings – so to workaround that, I wrote some temporary code in the constructor of my GameModel to populate them – so I could visualize the cards and design them. We are working on providing a better solution to this problem so that you really won’t have to write this temporary code (which is not much work frankly).

 

There are two more interesting things – the design for the cards and the interactivity. At this point, you have 4 drawing brushes? How do you convert this to form 52 cards? The solution is to use the very powerful DataTrigger feature that WPF exposes. Data triggers allow you to specify the look of the visual based on a property in the model (in this case the Suite and Card number information). So I created 13 data triggers for the 13 possible cards, and 4 additional data triggers for the 4 suites. Each card template uses the Brush set on the control that represents it and thus you have 13 * 4 cards – cool ah? Unfortunately, you cannot create DataTriggers in Interactive Designer as of now – so it has to be done by editing the markup. However, once this is done, you can then leverage the power of Interactive Designer to figure out how your Queen of Hearts or Ace of Spades should look like.

 

Here is how the structure of the DataTemplate for a Card looks like:

 

<DataTemplate x:Key="CardTemplate">

<Grid x:Name="Grid1" Width="72" Height="100">

            <ColumnDefinition/>

            <RowDefinition/>

            <Control x:Name="CardDisplayControl" Margin="2,0,2,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" />

            ....

      </Grid>

      <DataTemplate.Triggers>

            <DataTrigger Binding="{Binding Suite}">

                  <DataTrigger.Value>

                        <FreeCell:Suite>Hearts</FreeCell:Suite>

            </DataTrigger.Value>

                  <Setter Property="Foreground" TargetName="CardDisplayControl" Value="{StaticResource HeartsDrawingBrush}" />

      </DataTrigger>

            ....

      <DataTrigger Binding="{Binding SuiteIndependentCardNumber}">

                  <DataTrigger.Value>

                        <system:Int32>1</system:Int32>

            </DataTrigger.Value>

                  <Setter Property="Template" TargetName="CardDisplayControl" Value="{StaticResource AceTemplate}"/>

     </DataTrigger>

            ....

</DataTemplate.Triggers>

</DataTemplate>

 

There are two kinds of Interactivity possible in this game – starting the game, and selecting cards. To start the game, I used yet another WPF feature – called command binding. Command binding allows your command implementation to be in your model (which in this case involves re-setting the data structures, timers, etc.) without have to worry about how the command will be exposed. To hook up the command, you again use – guess what – data-binding using drag-drop in Interactive Designer – you can hook up the command to a Button, Menu Item or both if you like. If the command is not available, then these various UI elements appear disabled – all without a line of UI code.

 

Finally to figure out which card or cell was hit by the user, all one has to do is to add a MouseDown event – look at the DataContext property on the sender of the event. If the DataContext is not null and is an object in your model, you know exactly what was hit – at this point, all you do is call a function into your model to execute the game logic.

 

Check it out! It sure is fun…
Leave a Comment
  • Please add 2 and 8 and type the answer here:
  • Post
  • Would be a niche thing, if it would work.
    Got sreaming angry tryin to compile the project. something about not recognized namesapaces in the xaml file. i barely know xaml so i cannot fix. What went wrong? erik.hennig@gmx.de
Page 1 of 1 (1 items)