Click here to Skip to main content
15,886,110 members
Articles / Desktop Programming / WPF

Solitaire and Spider Solitaire for WPF

Rate me:
Please Sign up or sign in to vote.
4.97/5 (89 votes)
26 Feb 2013CPOL24 min read 172K   15.4K   160  
Create Solitaire and Spider Solitaire for WPF, step by step.
<UserControl x:Class="SolitaireGames.KlondikeSolitaire.KlondikeSolitaireView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:SolitaireGames.KlondikeSolitaire"
             xmlns:solitaireGames="clr-namespace:SolitaireGames"
             xmlns:apexControls="clr-namespace:Apex.Controls;assembly=Apex"
             xmlns:apexCommands="clr-namespace:Apex.Commands;assembly=Apex"
             xmlns:apexDragAndDrop="clr-namespace:Apex.DragAndDrop;assembly=Apex"
             mc:Ignorable="d" 
             x:Name="klondikeSolitaireView"
             d:DesignHeight="300" d:DesignWidth="300">
    
    <!-- Point to the main resource dictionary for the assembly. -->
    <UserControl.Resources>
        <ResourceDictionary Source="/SolitaireGames;component/Resources/SolitaireGamesResourceDictionary.xaml" />
    </UserControl.Resources>
    
    <!-- The main grid - the game is at the top and the commands are at the bottom. -->
    <apexControls:ApexGrid 
        Rows="*,Auto"
        DataContext="{Binding ViewModel, ElementName=klondikeSolitaireView}">

        <!-- The cards etc are all in a Viewbox so that they resize in a sensible
        way when we resize the window. -->
        <Viewbox Grid.Row="0" Margin="10">
            
            <!-- A DragAndDropHost allows us to perform more complicated logic when
            we drag and drop. -->
            <apexDragAndDrop:DragAndDropHost 
                x:Name="dragAndDropHost" MouseRightButtonDown="dragAndDropHost_MouseRightButtonDown"
                MinimumHorizontalDragDistance="0.0" MinimumVerticalDragDistance="0.0">
                
                <!-- This is the layout grid for the tableaus, foundations etc. -->
                <apexControls:ApexGrid Width="1200" Height="840" Columns="*,*,*,*,*,*,*" Rows="240,600">

                     <!-- The drag stack, cards are stored here temporarily while they
                    are being dragged. -->
                    <solitaireGames:CardStackControl 
                        x:Name="dragStack" Grid.Row="0" Grid.Column="0" Margin="0,-2000,0,0"
                        Orientation="Vertical" FaceDownOffset="10" FaceUpOffset="30"
                        apexDragAndDrop:DragAndDrop.IsDragSource="False"/>
                    
                        <!-- The stock. -->
                        <Border 
                            Grid.Row="0" Grid.Column="0" Style="{StaticResource StackMarker}" />
                        <solitaireGames:CardStackControl 
                            Grid.Row="0" Grid.Column="0" ItemsSource="{Binding Stock}" Cursor="Hand"
                            Orientation="Horizontal" FaceDownOffset="0" FaceUpOffset="0" MouseLeftButtonUp="CardStackControl_MouseLeftButtonUp" />

                        <!-- The waste. -->
                        <Border 
                            Grid.Row="0" Grid.Column="1" Style="{StaticResource StackMarker}" />
                        <solitaireGames:CardStackControl 
                            x:Name="wasteStack"
                            Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Waste}"
                            Orientation="Horizontal" OffsetMode="UseCardValues"  />

                        <!-- The foundations. -->
                        <Border 
                            Grid.Row="0" Grid.Column="3" Style="{StaticResource StackMarker}" />
                        <solitaireGames:CardStackControl 
                            Grid.Row="0" Grid.Column="3" ItemsSource="{Binding Foundation1}"
                            Orientation="Horizontal" FaceDownOffset="0" FaceUpOffset="0" />
                        <Border 
                            Grid.Row="0" Grid.Column="4" Style="{StaticResource StackMarker}" />
                        <solitaireGames:CardStackControl 
                            Grid.Row="0" Grid.Column="4" ItemsSource="{Binding Foundation2}"
                            Orientation="Horizontal" FaceDownOffset="0" FaceUpOffset="0" />
                        <Border 
                            Grid.Row="0" Grid.Column="5" Style="{StaticResource StackMarker}" />
                        <solitaireGames:CardStackControl 
                            Grid.Row="0" Grid.Column="5" ItemsSource="{Binding Foundation3}"
                            Orientation="Horizontal" FaceDownOffset="0" FaceUpOffset="0" />
                        <Border 
                            Grid.Row="0" Grid.Column="6" Style="{StaticResource StackMarker}" />
                        <solitaireGames:CardStackControl 
                            Grid.Row="0" Grid.Column="6" ItemsSource="{Binding Foundation4}"
                            Orientation="Horizontal" FaceDownOffset="0" FaceUpOffset="0" />

                        <!-- The tableaus. -->
                        <Border 
                            Grid.Row="1" Grid.Column="0" Style="{StaticResource RunMarker}" />
                        <solitaireGames:CardStackControl 
                            Grid.Row="1" Grid.Column="0" ItemsSource="{Binding Tableau1}"
                            Orientation="Vertical" FaceDownOffset="10" FaceUpOffset="30" />
                        <Border 
                            Grid.Row="1" Grid.Column="1" Style="{StaticResource RunMarker}" />
                        <solitaireGames:CardStackControl
                            Grid.Row="1" Grid.Column="1" ItemsSource="{Binding Tableau2}"
                            Orientation="Vertical" FaceDownOffset="10" FaceUpOffset="30" />
                        <Border 
                            Grid.Row="1" Grid.Column="2" Style="{StaticResource RunMarker}" />
                        <solitaireGames:CardStackControl 
                            Grid.Row="1" Grid.Column="2" ItemsSource="{Binding Tableau3}"
                            Orientation="Vertical" FaceDownOffset="10" FaceUpOffset="30" />
                        <Border 
                            Grid.Row="1" Grid.Column="3" Style="{StaticResource RunMarker}" />
                        <solitaireGames:CardStackControl 
                            Grid.Row="1" Grid.Column="3" ItemsSource="{Binding Tableau4}"
                            Orientation="Vertical" FaceDownOffset="10" FaceUpOffset="30" />
                        <Border 
                            Grid.Row="1" Grid.Column="4" Style="{StaticResource RunMarker}" />
                        <solitaireGames:CardStackControl 
                            Grid.Row="1" Grid.Column="4" ItemsSource="{Binding Tableau5}"
                            Orientation="Vertical" FaceDownOffset="10" FaceUpOffset="30" />
                        <Border 
                            Grid.Row="1" Grid.Column="5" Style="{StaticResource RunMarker}" />
                        <solitaireGames:CardStackControl 
                            Grid.Row="1" Grid.Column="5" ItemsSource="{Binding Tableau6}"
                            Orientation="Vertical" FaceDownOffset="10" FaceUpOffset="30" />
                        <Border 
                            Grid.Row="1" Grid.Column="6" Style="{StaticResource RunMarker}" />
                        <solitaireGames:CardStackControl 
                            Grid.Row="1" Grid.Column="6" ItemsSource="{Binding Tableau7}"
                            Orientation="Vertical" FaceDownOffset="10" FaceUpOffset="30" />
                </apexControls:ApexGrid>
            </apexDragAndDrop:DragAndDropHost>
        </Viewbox>

        <!-- A padded grid is used to layout commands and info at the bottom of the screen. -->
        <apexControls:PaddedGrid 
            Grid.Row="1" Padding="4" Columns="Auto,*,Auto,Auto,Auto,*,Auto">
            <Button 
                Style="{StaticResource CasinoButtonStyle}"
                Grid.Column="0" Width="120" Content="Deal New Game"
                Command="{Binding DealNewGameCommand}" />
            <TextBlock Grid.Column="2" Style="{StaticResource CasinoTextStyle}" VerticalAlignment="Center">
                <Run Text="Score:" />
                <Run Text="{Binding Score}" />
            </TextBlock>
            <TextBlock Grid.Column="3" Style="{StaticResource CasinoTextStyle}" VerticalAlignment="Center">
                <Run Text="Moves:" />
                <Run Text="{Binding Moves}" />
            </TextBlock>
            <TextBlock Grid.Column="4" Style="{StaticResource CasinoTextStyle}" VerticalAlignment="Center">
                <Run Text="Time:" />
                <Run Text="{Binding ElapsedTime, Converter={StaticResource TimeSpanToShortStringConverter}}" />
            </TextBlock>
            <Button 
                Style="{StaticResource CasinoButtonStyle}"
                Grid.Column="6" Width="120" Content="Go to Casino"
                Command="{Binding GoToCasinoCommand}" />
        </apexControls:PaddedGrid>

        <!-- The win overlay. -->        
        <apexControls:ApexGrid 
            Rows="*,Auto,Auto,Auto,*" Grid.RowSpan="2" Background="#00FFFFFF"
            Visibility="{Binding IsGameWon, Converter={StaticResource BooleanToVisibilityConverter}}">

            <TextBlock 
               Grid.Row="1" FontSize="34" FontWeight="SemiBold" Foreground="#99FFFFFF"
               HorizontalAlignment="Center" Text="You Win!" />
            <TextBlock
               Grid.Row="2" FontSize="18" Foreground="#99FFFFFF"
               HorizontalAlignment="Center" TextWrapping="Wrap">
                <Run Text="You scored" />
                <Run Text="{Binding Score}" />
                <Run Text="in" />
                <Run Text="{Binding Moves}" />
                <Run Text="moves!" />
            </TextBlock>
            <StackPanel 
                Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Center">
                <Button 
                    Style="{StaticResource CasinoButtonStyle}" Width="120" 
                    Margin="4" Content="Play Again" Command="{Binding DealNewGameCommand}" />
                <Button 
                    Style="{StaticResource CasinoButtonStyle}" Width="120" 
                    Margin="4" Content="Back to Casino" Command="{Binding GoToCasinoCommand}"  />
            </StackPanel>
        </apexControls:ApexGrid>
    </apexControls:ApexGrid>
</UserControl>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United Kingdom United Kingdom
Follow my blog at www.dwmkerr.com and find out about my charity at www.childrenshomesnepal.org.

Comments and Discussions