You are on page 1of 136

Exercise Manual for Course 419

C# Programming:
Hands-On

419/MA/N.4/308/N.3

by Gregory Adams

Technical Editor:
Sean Smith
© LEARNING TREE INTERNATIONAL, INC.
All rights reserved.

All trademarked product and company names are the property of their respective trademark holders.

No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, electronic,
mechanical, photocopying, recording or otherwise, or translated into any language, without the prior written permission of the publisher.

Copying software used in this course is prohibited without the express permission of Learning Tree International, Inc. Making unauthorized
copies of such software violates federal copyright law, which includes both civil and criminal penalties.
Exercise Manual Contents

Legend for Course Icons ......................................................................................................ii


Hands-On Exercise 1.1: Our Development Environment .................................................... 1
Hands-On Exercise 2.1: Methods and Namespaces ......................................................... 11
Hands-On Exercise 2.2: Expressions, Casting, and Arrays............................................... 17
Hands-On Exercise 3.1a: Writing Windows Forms Programs ........................................... 23
Hands-On Exercise 3.1b: Developing a Web Application.................................................. 37
Hands-On Exercise 4.1: Defining Classes......................................................................... 51
Hands-On Exercise 4.2: Implementing Properties............................................................. 61
Hands-On Exercise 4.3: Leveraging Inheritance ............................................................... 67
Hands-On Exercise 5.1: Associations and Collections ...................................................... 73
Hands-On Exercise 6.1: Down-Casting ............................................................................. 83
Hands-On Exercise 6.2: Implementing Interfaces ............................................................. 91
Hands-On Exercise 7.1a: Adding Desktop Card Images—COM Components.................. 97
Hands-On Exercise 7.1b: Adding Desktop Card Images—Image List Component ......... 105
Hands-On Exercise 7.1c: Adding Web Card Images—Image Component ...................... 111
Hands-On Exercise 8.1: Using LINQ/EF ......................................................................... 117

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-i
Legend for Course Icons

Standard icons are used in the hands-on exercises to illustrate various


phases of each exercise.

Major step Warning

1.  Action Hint

Checkpoint Stop

Question Congratulations

Information Bonus

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-ii
Hands-On Exercise 1.1:
Our Development Environment

Objective
Become familiar with Visual Studio (VS) and test a sample C# program that
does currency conversion. Do all three parts—A, B, and C.

Part A: Compiling and executing programs

Start Visual Studio and maximize its window to full screen.

The installation of Visual Studio 2012 you are about to use has
been minimally preconfigured for course use. The following changes
have been made:
• Update 1 has been added.
• Help has been installed locally so that it is not necessary to be
online during class.
• C# developer layout settings were chosen on first launch.
• C# editor has been set to keep tabs rather than substitute spaces.
None of the course exercises are dependent on this configuration,
and you should be able to directly use a virgin installation of Visual
Studio 2012 to do them—update 1 is recommended.

1.  Click the Start Orb and from its pop-up menu, select Visual Studio.
This will start the integrated development environment (IDE) that we
will use during the course.

A start page should be displayed. It is actually a Web browser. It


will change each time you start VS to reflect the latest work you’ve
been doing. From here you can quickly select previous solutions, or
various other help and information.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-1
Hands-On Exercise 1.1:
Our Development Environment
(continued)

Open the existing solution CurrencyConverter.sln located


in the directory C:\Course\419\Exercises\Ex11.

Although you could select the link “Open Project” from the start
page, the start page might not be available depending on how Visual
Studio is configured.

2.  Select from the menu bar File | Open | Project/Solution.

3.  When the File dialog box appears, navigate to the directory


C:\Course\419\Exercises\Ex11 in the student folder.

The above directory can be located anywhere on your own


computer.

4.  Double-click the solution control file CurrencyConverter.sln.

The currency converter should open as the active project.

5.  Set local help as the default. From the menu bar select Help | Set
Help Preference | Launch in Help Viewer.

6.  Optional: You might wish to change the configuration of Visual


Studio to suit your personal preferences. For example, many users
like to have line numbers displayed in their editor. To select line
numbers, select Tools | Options from the main menu bar, and in the
dialog, select Text Editor | C# | General and check Line Numbers
under Display.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-2
Hands-On Exercise 1.1:
Our Development Environment
(continued)

Open the Solution Explorer window so that you are able to see
the files included in the project.

7.  If the Solution Explorer window is not already there, select from the
menu bar View | Solution Explorer, or click the Solution Explorer
icon in the top toolbar on the right side. Use “tool tips” if necessary to
locate it.

The Solution Explorer window should appear on the right side


of the VS work area if it was not already there.

8.  If the files are not already visible in the Solution Explorer, click the
triangle icon next to the CurrencyConverter project. This will open
to reveal all of the files and folders in the project.

What C# source files are in the project? Look in the folders


too. What assemblies in the .NET Framework are being
referenced?

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-3
Hands-On Exercise 1.1:
Our Development Environment
(continued)

Review the application source code.

9.  Open the file Program.cs by double-clicking the icon next to the


filename in the Solution Explorer window. This will open it into the
edit window.

10.  Briefly review it and see if you can determine what it does.

Build and then execute the program using the VS menu-bar


items and accelerator keys.

11.  Select from the VS menu bar Debug | Start Without Debugging.
This will both compile and run the program.

The application should run as a console program.

12.  The program will now prompt you for input with:

Input amount of USD to convert to EUR?

Enter an appropriate dollar value. The amount in Euros will be


displayed.

13.  Press the <Enter> key to continue.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-4
Hands-On Exercise 1.1:
Our Development Environment
(continued)

Part B: Exploring VS editing and compilation error handling

Edit Program.cs in any fashion you like.

14.  Try moving around Program.cs using the mouse and cursor keys.
Change some text by adding, modifying, or deleting.

If you inadvertently change something you didn’t mean to, you


can correct it using the menu-bar commands Edit | Undo
(<Ctrl><Z>) and/or Edit | Redo (<Ctrl><Y>). Alternatively, you
can use the toolbar icons near the top center to do the same thing.

15.  Now use undo to completely undo all changes you have made. You’ll
know when all changes have been undone because the toolbar and
menu items will gray out.

Notice that the edit window has [+] and [-] icons; these can be
used to fold away text that you are not currently working with and
then to unfold it again when you need it.

16.  Try folding and unfolding a few of the code sections, leaving only
Main exposed.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-5
Hands-On Exercise 1.1:
Our Development Environment
(continued)

Place an error in the Main method of the program and compile.

17.  Move to a convenient line and enter some gibberish text.

18.  Attempt to compile and execute the program using Debug | Start
Without Debugging.

There is no need to save your changes manually or do a


separate compile. “Make mode” is used and Visual Studio will
automatically save all the changes you have made and compile them
before attempting to run the program.

Wait for a dialog box to appear.

19.  Select No and do not run the program.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-6
Hands-On Exercise 1.1:
Our Development Environment
(continued)

Fix the error.

20.  In the message window, double-click the text of the first error
message. This will have the effect of jumping to the error line in the
edit window.

If you hover the mouse pointer over the highlighted error in the
edit window, a tool tip will appear possibly explaining the error.

21.  Enter a few other errors and compiling to see what happens. Try:
• Removing a semicolon at the end of a statement
• Removing a curly bracket: { or }

Warning! When there is more than one error message, it is


best to fix just the first one and then recompile. Don’t tediously
examine each of them in order. One error can produce many
error messages.

Close the solution.

22.  Select File | Close Solution and select No if asked to save changes.

Ensure that the project window and the edit windows disappear.

You have completed Part B. Please continue to Part C.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-7
Hands-On Exercise 1.1:
Our Development Environment
(continued)

Part C: Creating a project and writing a program

The purpose of Part C is to create a new project and to edit the


framework code produced by VS to be the “hello world” program.

Create a new project called HelloWorld.

23.  Select File | New | Project from the VS menu bar and wait for the
New Project dialog box to appear.

24.  In the dialog box:


a. From the tree menu on the left, select Visual C# | Windows.
b. In the center Templates window, click the Console Application.
c. In the Name text box, enter HelloWorld
d. Enter C:\Course\419\Exercises\ into the Location text box.
e. Make sure the “Create directory for solution” checkbox is
selected.
f. Make sure the “Add to source control” checkbox is cleared.
g. In the Solution Name text box, enter Ex11C
h. Click OK.

You will need to wait a few seconds while the project is


created.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-8
Hands-On Exercise 1.1:
Our Development Environment
(continued)

25.  Open the Solution Explorer window (View | Solution Explorer) if


necessary and view the file Program.cs.

VS has created a new solution with one project in it and


produced a framework Main method (function) for you. This can be
edited to produce the “hello world” program we looked at.

Add the “hello world” logic to the Main method.

26.  Modify the Main method—insert the logic to output the text message
"Hello World!".

As you start to type, IntelliSense will pop up items that match


what you have entered. You can continue to type or select an item in
the drop-down list and press <Tab> to select it and enter the text.

27.  Compile and test.

Congratulations! You have successfully completed the


exercise.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-9
Hands-On Exercise 1.1:
Our Development Environment
(continued)

If you have more time, try the following bonus.

28.  Highlight a keyword or a call to a system function and press <F1>.


Help text will appear in the edit area.

During installation of Visual Studio, the “Use Local Help” was


selected and all of the help files were installed. However the local
viewer must also be enabled—see Step 5 of this exercise.

29.  Dismiss the help window by clicking the [x] icon in the upper right
corner.

Explore the solution layout.

30.  Using Windows Explorer, examine the files and directory layout of
the solution you created in C:\Course\419\Exercises\Ex11C.

This is the end of the exercise.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-10
Hands-On Exercise 2.1:
Methods and Namespaces

Objective
Become familiar with using namespace directives, methods, and overloading.

Return to VS and close any open project solutions.

1.  From the VS menu bar, select File | Close Solution.

Open the existing solution: C:\Course\419\Exercises\Ex21


\CurrencyConverter.sln.

2.  From the VS menu bar, select File | Open Solution and, when the
File dialog appears, go to C:\Course\419\Exercises\Ex21 and
double-click the solution control file CurrencyConverter.sln.

3.  If the Solution Explorer window is not visible, select View | Solution


Explorer from the menu bar.

4.  Open Program.cs into the edit area by double-clicking its icon in


the Solution Explorer.

5.  Compile and test to ensure that everything is working. Select from


the menu bar Debug | Start Without Debugging or just press
<Ctrl><F5>.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-11
Hands-On Exercise 2.1:
Methods and Namespaces
(continued)

Replace all references to System.Console... with just


Console....

6.  Find the four occurrences in the program and make the substitution.

7.  Compile.

What happens?

Unless you direct the compiler where to look, it attempts to find


everything in the current namespace.

Fix the problem using a directive to select the proper


namespace.

8.  At the appropriate position in the file, add the directive to indicate


that we are using the System namespace.

9.  Compile and test.

The program should work the same as before.

In most cases, developing a solution requires attaching to


libraries that are not part of our own namespace or the System
namespace. To do this, we must not only declare that we are using
the namespace, but also add it to our assembly. This is the
equivalent of wanting to use, as part of the current solution, a project
that you wrote in the past or somewhere else.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-12
Hands-On Exercise 2.1:
Methods and Namespaces
(continued)

Switch to using a more complete SymbolFor method, available


from a library.

10.  If it is not already open, select the file Program.cs for editing.

11.  Comment out the local definition of the SymbolFor method.

12.  Insert the directive using MoneyLib; at the appropriate location.

You should see a red squiggly line indicating an error because


MoneyLib is not a known namespace.

MoneyLib is another namespace that is in its own library


(.dll) file. We need to include it as part of our program.

Attach the MoneyLib library to our solution.

13.  In the Solution Explorer window, click the triangle icon next to
References.

The libraries currently being used for this solution will be listed.

14.  Right-click References and select Add Reference from the pop-up
menu.

Wait for the Add Reference dialog box to appear.

15.  Click the Browse tab in the dialog box.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-13
Hands-On Exercise 2.1:
Methods and Namespaces
(continued)

16.  Navigate to the folder C:\Course\419\Samples\MoneyLib\bin


\Debug and open the file MoneyLib.dll.

Notice that MoneyLib.dll appears in the Selected


Components list box.

17.  Click the OK button in the Add Reference dialog box.

18.  Try to compile.

You will still get an error. This is because SymbolFor is in


another class (MoneyLib.EuroTable), not our own class.

19.  In our program, change both calls to SymbolFor(...) to be calls to


EuroTable.SymbolFor(...). If IntelliSense pops up a selection
box, press <Esc>.

20.  Compile and test.

The program should work the same as before.

Not only can MoneyLib.EuroTable return the symbols for


many different currencies, it also has a method called
ExchangeRate that returns the current exchange rate for most
currencies. A three-letter string is used to specify the desired
currency.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-14
Hands-On Exercise 2.1:
Methods and Namespaces
(continued)

Modify the Convert method to get the exchange rate by calling


EuroTable.ExchangeRate rather than using a hard-coded
value.

21.  Change the line const double convRate = …; to


double convRate = EuroTable.ExchangeRate(ic);

Note that const must be removed because it is no longer a


compile-time constant.

22.  Compile and test.

The program should work the same way as before, although


you should see different values.

Modify the calling program to use other input currencies than


euros or dollars.

23.  Edit the main program to use different input currencies. You should
have to change only one line of code to achieve this; e.g., something
like string inCur = "JPY";
Compile and test a few times, trying different currency codes like:
• SEK for Swedish Kronen
• GBP for Great Britain pounds

Congratulations! You have completed the exercise. If you


have more time, please continue to the bonus.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-15
Hands-On Exercise 2.1:
Methods and Namespaces
(continued)

Support conversion from any currency to any currency.

Our program is limited—it is “Eurocentric”; i.e., it can only


convert to or from Euros. We’ll improve on this now.

Modify the Convert method to convert any currency to any


currency.

24.  Modify the specification of the Convert method to take both the
input and output currencies as arguments. It should look like this:
… Convert(string ic, string oc, double amt)

25.  Add the following logic:


• Get the exchange rate from Euros to the output currency
• Get the exchange rate to Euros from the input currency
• Divide the input rate by the output rate
• Multiply the amount by the rate to get the output currency amount

The specific code is left up to you.

26.  Compile and test with different input and output currencies. Change
the inCur and outCur values in the Main(…) method.

Close the solution.

27.  From the VS menu bar, select File | Close Solution.

This is the end of the exercise.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-16
Hands-On Exercise 2.2:
Expressions, Casting, and Arrays

Objective
To make our program more convenient to use, we want to modify it so that
we can pass in the amount to be converted and the currency type to convert;
i.e., the command line should allow something like:
$ CurrencyConverter 34101.25 USD JPY
This should convert 34,101.25 U.S. dollars to Japanese yen.

Return to VS and close any open project solutions.

1.  From the VS menu bar, select File | Close Solution.

Open the existing solution C:\Course\419\Exercises\Ex22


\CurrencyConverter.sln.

Refer to the previous exercise if you have forgotten how to do


this. Get Program.cs ready for editing.

2.  Compile and test by pressing <Ctrl><F5> to make sure everything


is working as expected.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-17
Hands-On Exercise 2.2:
Expressions, Casting, and Arrays
(continued)

Modify the Main method to use the specification that supports


command-line operation.

3.  Change the specification of the Main method to:


public static int Main(string[] args)

4.  Compile.

What has caused this error?

When operating at the command line, it is typical to return an


integer value to indicate the success or failure of the program. Since
our main method declares a return type of int, we must return an
int.
• return 0; if there are no errors
• return n; if there is an error, where n is a non-zero integer
value, typically 1

5.  Modify the program to indicate to return 0;.

6.  Compile and test to ensure that the program is still working as before.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-18
Hands-On Exercise 2.2:
Expressions, Casting, and Arrays
(continued)

Test the command-line argument-passing facility by checking


the number of arguments passed in.

Command-line input is passed in as an array of strings—in our


case, as string[] args. Our program requires exactly three
arguments—no more, no less.

7.  Before the first line of code in the Main method, enter something like
the following (substitute your code for the … sections):

if (…number of args… != 3)
{
Console.WriteLine(…report the number of args…);
return …error code value…
}

Use the string concatenation operator (+) to report the number


of arguments provided. Use the array .Length property to get the
number of arguments provided.

8.  Get a clean compile of the program (but do not run it). From the VS
menu bar, select Build | Build or press <F6>.

9.  From the Windows Start Orb select All Programs | Microsoft


Visual Studio 2012 | Visual Studio Tools | Visual Studio
Command Prompt (2012).

Warning! Under Windows, the command prompt is


different than in the MS-DOS command window. Please do not
use Start | Run and type command, because this MS-DOS
command window will not work properly for long filenames or
for the .NET command-line tools.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-19
Hands-On Exercise 2.2:
Expressions, Casting, and Arrays
(continued)

10.  In the command-prompt window, enter the command


cd C:\Course\419\Exercises\Ex22\bin\debug
and perform a directory listing (dir) to see what files are there.

11.  Execute the command currencyconverter 100 usd

The program should report two arguments along with the


appropriate error message.

12.  Repeat using a proper command line like the following:


currencyconverter 100 usd jpy
There should be no error message.

You can use the <Up arrow> and <Down arrow> keys to
recall previous commands.

13.  Return to VS—do not close your command window.

Modify the program to actually use the parameters passed in.

14.  Find the line of code that contains string inCur = ... and
change it to initialize inCur using the second element of the
argument array converted to all uppercase.

Use the string named operation ToUpper() and apply it to


args[1].

15.  Repeat for outCur; initialize it from the third argument.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-20
Hands-On Exercise 2.2:
Expressions, Casting, and Arrays
(continued)

16.  Find the line of code that assigns a value to inAmt, as in:
inAmt = GetAmount("Enter…");

Modify it to initialize using the first argument, parsed into the


appropriate type. It will look something like this:
inAmt = decimal.Parse(args[0]);

17.  Get a clean compile using Build | Build or <F6>.

18.  Return to your command window and test by entering


currencyconverter 100.00 cad usd

19.  Try a few different currency types and amounts.

If you get any exceptions, click OK and continue. We’ll discuss


exceptions later in the chapter.

Congratulations! You have successfully completed the


exercise. Continue to the bonus if you have more time.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-21
Hands-On Exercise 2.2:
Expressions, Casting, and Arrays
(continued)

If you have more time:

20.  Modify the program so that if the wrong number of arguments is


entered by the user, a proper UNIX-style “usage” message is
printed—as opposed to just reporting the wrong number of
parameters. In other words, change the format of the error report to
include helpful information on what users should enter.

A “usage” message is essentially help text that shows the user


what the correct input format would be along with an example.

This is the end of the exercise.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-22
Hands-On Exercise 3.1a:
Writing Windows Forms Programs

Objective
Become familiar with writing Windows Forms programs. During the course,
we will be developing a card game known as “The Eyes Have It,” or “Tehi.”
To start, we will begin with the user-interface tier.

Specifically, we will utilize .NET controls and implement event-handling in a


Windows Form to implement a “game table.” A “Deal” button will be used to
deal cards and display them. Initially this will be text only, but later in the
course we will add playing card images and other truly graphical features.

For this exercise, we will use a ListBox as an area to display results. When
done, the game table should look something like the following.

© All rights reserved. Not to be reproduced without prior written consent. 23


419-MA-23
Hands-On Exercise 3.1a:
Writing Windows Forms Programs
(continued)

Part A: Laying out the game table form

Close the previous solution if you have not already done so.

Create a new Windows application using the .NET Windows


framework.

1.  From the VS menu bar, select File | New | Project.

Wait for a New Project dialog box to appear.

2.  In the dialog box:


a. From the tree menu on the left, select Visual C# | Windows.
b. In the center window, select Windows Forms Application.
c. In the Name text box, enter Tehi
d. Enter C:\Course\419\Exercises\Ex31 into the Location text
box if it is not already there.
e. Make sure that the “Create directory for solution” checkbox is
selected.
f. Make sure that the “Add to source control” checkbox is cleared.
g. In the Solution Name text box, enter Tehi if it is not already there.
h. Click OK.

After a few seconds, the project will have been created and the
Forms design window should appear.

Warning! If you are not sure what a Forms design window


is, please ask your instructor.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-24
Hands-On Exercise 3.1a:
Writing Windows Forms Programs
(continued)

Resize the form to be about twice as wide as it is high, and set


its properties as appropriate for a card game.

3.  Click the form and then move the mouse pointer to the grip at the
right edge of the form. A cursor that looks like <-> will appear so that
you can visualize the resizing.

4.  Drag the right edge so that the form is about twice as wide as it is
high.

5.  Right-click within the body of the form. From the pop-up menu that
appears, select Properties.

A properties sheet should appear on the right side if it is not


already there.

6.  Select the property called Text and modify its entry to read The
Eyes Have It!

If it is not already alphabetical, click the A–Z button at the top of


the property sheet to make them easier to find.

7.  Click the property called BackColor and click the color selection
combo box next to it. Since most card tables have a green or a blue
felt surface, click the Web tab and select a green or dark blue color
that suits your fancy.

8.  Set the following properties:


• StartPosition to CenterScreen
• Size to 665,420

© All rights reserved. Not to be reproduced without prior written consent. 25


419-MA-25
Hands-On Exercise 3.1a:
Writing Windows Forms Programs
(continued)

Configure VS for windows layout.

9.  Click the Toolbox icon at the far left side of the screen (in the left
bar) and click the “thumbtack” icon at the top of the window—that will
hold it in place. If the Toolbox icon is not visible, select the menu
choice View | Toolbox.

10.  If it is not already selected, click to open the All Windows Forms tab
in the Toolbox window.

Add a list box to the form and set its properties.

11.  Click the ListBox control. Move the cursor to the form and drag the
outline of where you want the list box to appear.

See the screenshot at the start of this exercise for the look of
the list box control.

12.  Click the ListBox control so that its property sheet appears. Set its
font property to Lucida Sans Unicode with a size of 10 point.

Warning! Make sure to set this specific font—it supports


Unicode. Not all fonts do.

13.  Also set the following properties as indicated:


• (Name) property to LogListBox
• Anchor to all (top, bottom, left, and right)
• HorizontalScrollbar to true

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-26
Hands-On Exercise 3.1a:
Writing Windows Forms Programs
(continued)

Add a status strip to the form.

14.  Drag and drop a StatusStrip control from the toolbox to the form. It
should snap to the bottom docked position on the form.

15.  Click the StatusStrip control (which you just added at the bottom of
the form), and a drop-down menu will appear. From the drop-down
menu, select StatusLabel. A label should appear on the status strip
on the left side.

16.  Click the label StatusLabel (not StatusStrip) and, in its Properties
window, set the following:
• (Name) property to be StatusLabel (the (Name) property is
located near the top of the property list)
• BackColor to System | Control
• Font property a little bigger—10 is good
• Text property to be blank

Add a button to the form to be the Deal button.

17.  Click the Button control in the toolbox. Move the cursor to the form
and drag the outline of where you want the Deal button (see
screenshot at start of this exercise).

18.  In its property sheet, set


• (Name) to DealButton
• Anchor only to the bottom
• Font size to 12 (click the triangle icon next to the font property to
display the subproperties)
• Size to 96,32
• Text to Deal

© All rights reserved. Not to be reproduced without prior written consent. 27


419-MA-27
Hands-On Exercise 3.1a:
Writing Windows Forms Programs
(continued)

19.  Execute the program by pressing the <F5> key (<Ctrl><F5> is no


longer needed because this is not a console application). Resize the
window to ensure the controls are anchored correctly.

As you resize, the Deal button should stay centered near the
bottom. The list box, however, should stretch to fill the middle.

20.  Exit the program by clicking the [x] in the upper right corner.

In the future you should always exit from the program before
returning to Visual Studio, even if the instructions do not explicitly
say to do so.

Part B: Adding event handling

Create the event-handling method for the button.

21.  In the form design window, double-click the Deal button.

This opens the source-code window and positions the cursor at


the button’s event-handling method called DealButton_Click.

22.  Position within the event method and clear the list box using:
LogListBox.Items.Clear();

23.  Position within the event method and output a message to


LogListBox using something like:
LogListBox.Items.Add("The spade symbol is \u2660");

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-28
Hands-On Exercise 3.1a:
Writing Windows Forms Programs
(continued)

24.  Set some information in the status label using something like:
StatusLabel.Text = "Deal button pressed";

25.  Press <F5> to compile and test.

When you click Deal, you should see the spade symbol
indicating that the proper Unicode font is selected. Also, the deal
message should be in the status bar.

Congratulations! You have successfully completed the


exercise. Continue to the bonus if you have more time.

© All rights reserved. Not to be reproduced without prior written consent. 29


419-MA-29
Hands-On Exercise 3.1a:
Writing Windows Forms Programs
(continued)

If you have more time, add the remaining controls and menus
that we will require in the future for various actions of the
game.

Drag a menu strip to the form and populate its menu and
menu-item choices.

26.  In the toolbox, drag a MenuStrip to the form. It should snap to the
top of the form. Move your list box down if necessary to make room
for the menu strip.

27.  Edit the menu choices to be:

Game Preferences Help  in the menu bar


New Table Color… About…  under each menu
Top 10
Exit

For each menu and menu item, enable <Alt> selection by


placing an & character at the appropriate place. For example:
&Game.

28.  Compile and test. The menus should select but won’t do anything
after selection just yet. Check that you can select them using
something like <Alt><G><X> to exit the game. Note that this is
done in three distinct key strokes—you do not need to hold the
<Alt> key down while you press the <G> or the <X>.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-30
Hands-On Exercise 3.1a:
Writing Windows Forms Programs
(continued)

Add event handling for the menu items.

29.  Double-click each menu item. In their respective event methods,


add:
• For Game | New, clear the list box by using
LogListBox.Items.Clear(). Also clear the status label text
(assign string.Empty to it).
• For Game | Top 10, display in the status label that top 10 was
chosen.
• For Game | Exit, use the Application class to exit.
• For Help | About, show information using a MessageBox
indicating who wrote the game. Place this as the first parameter.

Don’t worry about the color preferences just yet.

30.  Compile and test. Ensure the menus do the expected functions.

Modify the form’s display icon to be specific to the Tehi


program.

31.  In Solution Explorer, right-click the Tehi project (not the solution) and
select Add | Existing Item.

32.  In the dialog Filename field, enter *.ico and press <Enter>. This
is so that only icon files will show.

33.  Navigate to C:\Course\419\Graphics\Icons and select an icon


that suits your fancy. Click Add.

In Solution Explorer, the selected icon file should have been


added to the Tehi project.

© All rights reserved. Not to be reproduced without prior written consent. 31


419-MA-31
Hands-On Exercise 3.1a:
Writing Windows Forms Programs
(continued)

34.  Right-click this new icon file and rename it App.ico

35.  In Solution Explorer, right-click the Tehi project (not the solution).
Select Properties.

36.  In the properties page, select the Application tab and then, from the
drop-down list under Icon, select App.ico.

This is so that the file Tehi.exe will show in Windows with the
icon you selected.

37.  Get a clean compile and close the properties page (click the X).

38.  In the designer, click the form and then, from its property sheet,
select the Icon property. Click the […] button so that an icon
selection dialog box appears.

39.  Navigate to C:\Course\419\Exercises\Ex31\Tehi\Tehi and


select the App.ico file.

40.  Compile and run.

The icon you selected should now be showing on the left side
of the title bar.

41.  Unpin the toolbox (click the thumbtack) so that it returns to the far left
side of Visual Studio.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-32
Hands-On Exercise 3.1a:
Writing Windows Forms Programs
(continued)

Add a user name text box and a login button to the form.

42.  Open Form1.cs in design mode and click the TextBox control in
the toolbox. Move the cursor to the form and place the text box at the
position shown (login button will not be there yet).

43.  Set its properties to:


• (Name) property to NameTextBox
• Anchor to the bottom only
• Font Size to 12
• Size to 73,26
• Text to blank

44.  Right-click the Deal button. Select Copy from the pop-up menu.

45.  Right-click the form (not any control) and select Paste from the pop-
up menu. Drag it to the position for the Login button (see screenshot
above).

46.  Change the properties as follows:


• (Name) to LoginButton
• Text to Login

47.  Double-click the Login button to go to its event method. Display in


the status label that the Login button was pressed.

48.  Compile and test. Go back and forth between the Deal button and
the Login button.

© All rights reserved. Not to be reproduced without prior written consent. 33


419-MA-33
Hands-On Exercise 3.1a:
Writing Windows Forms Programs
(continued)

Use copy-and-paste to add the Swap buttons.

49.  Open Form1.cs for editing and add the method:

private void SwapCard(int ix)


{
StatusLabel.Text = "Swap button " + ix + " pressed.";
}

50.  Return to design view and right-click the form again. Select Paste.
Drag this button to the appropriate place for the first Swap button
(see screenshot).

51.  Change its properties as follows:


• (Name) to SwapButton0
• Text to Swap

52.  Right-click this new Swap button and select Copy.

53.  Right-click the form and select Paste. Drag this button to the position
for the next Swap button and set its (Name) to the next button
number: SwapButton1, SwapButton2, and so on.

54.  Repeat the previous step for the remaining three Swap buttons.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-34
Hands-On Exercise 3.1a:
Writing Windows Forms Programs
(continued)

55.  In design view, double-click the first Swap button. In its event
method, call SwapCard(0)

56.  Repeat the previous step for the remaining Swap buttons. Increment
the reported button number by one each time.

57.  Compile and test. Click all buttons to ensure they are working.

Add support for changing the table color.

58.  Drag and drop a ColorDialog control to your form and ensure it
appears in the non-attached list at the bottom of the design window.

59.  In the designer window, double-click the Preferences | Table Color


menu item and position the cursor in its event method.

60.  In the event method, add the code to display colorDialog1 and
capture its DialogResult. This is much like displaying a
MessageBox, but the ShowDialog() method is used, as in:
DialogResult result = colorDialog1.ShowDialog(this);

61.  Next, add the code to check if DialogResult.Cancel is returned.


If it is, then just return from the event method without doing any
further processing.

62.  If the user did not cancel the color dialog, then set the background
color of the game table using something like this:
BackColor = colorDialog1.Color;

63.  In the designer window, double-click the Preferences | Reset


Default Color menu item to go to its event method.

© All rights reserved. Not to be reproduced without prior written consent. 35


419-MA-35
Hands-On Exercise 3.1a:
Writing Windows Forms Programs
(continued)

64.  In the event method, set BackColor = Color.Green;

65.  Compile and test. Try selecting a few different colors.

Congratulations! You have completed the bonus material.

This is the end of the exercise.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-36
Hands-On Exercise 3.1b:
Developing a Web Application

Objective
Become familiar with writing ASP.NET thin-client Web pages. During the
course, we will be developing a card game known as “The Eyes Have It,” or
“Tehi.” To start, we will begin with the user-interface tier.

Specifically, we will utilize ASP.NET controls and implement event-handling in


a Web form to implement a “game table.” A “Deal” button will be used to deal
cards and display them. Initially this will be text only but later in the course we
will add playing card images and other truly graphical features.

For this exercise, we will use a ListBox as an area to display results. When
done, the game table should look something like the following.

© All rights reserved. Not to be reproduced without prior written consent. 37


419-MA-37
Hands-On Exercise 3.1b:
Developing a Web Application
(continued)

Part A: Laying out the game table

Close the previous solution if you have not done so already.

Create a new Web forms application using the ASP.NET


Framework.

1.  From the VS menu bar, select File | New | Project.

Web applications are often developed in the file system for


debugging and testing, and then published to a production server at
a later time. We will use the file system.

2.  In the dialog box, select or confirm the following, then click OK.
• Installed | Templates | Visual C# | Web
• ASP.NET Empty Web Application
• .NET Framework 4 (in a drop-down )
• Name: Tehi
• Location: C:\Course\419\Exercises\
• Solution Name: Tehi
• Create Directory For Solution: Selected

After a short wait, the Web site will be created. You should see
only the Web.config file in the project.

3.  Right-click the Tehi Web project and select Add | New Item. In the
dialog, select a Web Form and name it Default.aspx

The Web page will be added to your project. Be patient; it


might take 30 seconds or more.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-38
Hands-On Exercise 3.1b:
Developing a Web Application
(continued)

4.  Run the application—the page should be blank.


• If you get a Debugging Not Enabled dialog, click OK to enable
debugging in Web.config.
• If you get an “Intranet settings” warning in the toolbar, dismiss it
by clicking it and selecting Don’t Show this Message Again.

Configure VS to use the Web designer.

5.  Click the Toolbox icon at the far left side of the screen (in the left
bar), and click the “thumbtack” icon at the top of the window that
appears to hold it in place. If the Toolbox icon is not visible, select
the menu choice View | Toolbox.

6.  If it is not already selected, click to open the Standard tab in the


Toolbox window.

Lay out the content page.

7.  Open Default.aspx and if it is not already selected, click the


source tab at the bottom of the main edit area.

8.  Modify the body tag to set the background color to silver. The tag
should look like <body bgcolor="Silver">. Note that you will
have to type it in; the autocomplete will not recognize it until it is fully
entered.

© All rights reserved. Not to be reproduced without prior written consent. 39


419-MA-39
Hands-On Exercise 3.1b:
Developing a Web Application
(continued)

9.  Click the Design tab, and then click inside the rectangle beneath the
body tag. The tag will change to a div tag. From the menu bar (not
the tool box), select Table | Insert Table. In the dialog, select the
following:
• 7 rows by 5 columns
• Center aligned
• 8 for the Cell Padding
• 0 for the Cell Spacing
• 0 for the Border Size
• 550 pixels for the Width
• Green Background color (type it in)

Leave the remainder as is and click OK. A green table should have
appeared.

10.  Merge the columns of the first row. To do this, click in the first cell, then
hold down the <Shift> key and click in each of the remaining cells in
that row. Don’t worry if the first cell looks deselected—it is still selected.
Right-click and select Modify | Merge Cells.

11.  Repeat the merge for the second, third, and bottom rows.

12.  Execute the program by pressing the <F5> key (<Ctrl><F5> is no


longer needed because this is not a console application). You should
just see a green rectangle on a silver background. Resize your
browser window to be just big enough to show the green rectangle,
plus a little bit of the silver background.

13.  Exit the browser by clicking the [x] in the upper right corner.

In the future, always exit the browser before returning to Visual


Studio, even if the instructions do not expressly say to do so.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-40
Hands-On Exercise 3.1b:
Developing a Web Application
(continued)

Add the Deal button, a list box, and labels to the Web page.

See the screenshot at the start of this exercise for how the Web
page should look.

14.  Drag and drop a ListBox control to the third row in the table. If
necessary, press the <Esc> key to dismiss the ListBox Tasks dialog.
In its property sheet, change the following:
• (ID) property to LogListBox
• Enabled to false
• Font | Name to Lucida Sans Unicode
• Font Size to 12 (type it in)
• Height to 120px
• Width to 100%

Warning! Make sure to set this specific font—it supports


Unicode. Not all fonts do.

15.  Drag a Button to the form in the middle cell of the sixth row. In its
property sheet, set:
• (ID) to DealButton
• Font size to 12 (click the triangle icon next to the font property to
display the subproperties)
• Text to Deal
• Width to 96

16.  Run the program to see what you have so far. Don’t worry if the Deal
button is offset. This will adjust automatically as more controls are
added to the page.

© All rights reserved. Not to be reproduced without prior written consent. 41


419-MA-41
Hands-On Exercise 3.1b:
Developing a Web Application
(continued)

17.  Drag and drop a Label to the bottom row of the table. In its property
sheet, set:
• (ID) to StatusLabel
• Font Size to 14 (type it in)
• ForeColor to white (type it in)
• Text to blank

18.  Right-click the status label and select Copy. Right-click the top row
and select Paste. In its property sheet, set:
• Font to Bold and Italic
• Text to THE EYES HAVE IT!

19.  Compile and run the program.

The Web browser will appear with your application’s view


delivered to it.

Part B: Adding event handling

In the following, you will open the source code to add the
event-handling method for the button.

20.  Exit the browser. When you are back in the designer, double-click
the Deal button to open the source code for its event method.

This opens the source-code window and positions the cursor at


the button’s event-handling method called DealButton_Click.

21.  Insert a statement to clear the list box. Use:


LogListBox.Items.Clear();

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-42
Hands-On Exercise 3.1b:
Developing a Web Application
(continued)

22.  Output a message to LogListBox using something like:


LogListBox.Items.Add("The spade symbol is \u2660");

23.  Set some information in the status label using something like:
StatusLabel.Text = "Deal button pressed";

24.  Press <F5> to compile and test.

If you see the spade symbol, the list box has the correct font.
Ensure the status message is appearing, too.

Congratulations! You have successfully completed the


exercise. Continue to the bonus if you have more time.

If you have more time, add additional controls to the page that
we will need to implement the game.

Add link buttons to serve as menu choices.

25.  Open Default.aspx in design mode and drag a LinkButton into


the second row. Set its properties as follows:
• ForeColor to White (type it in)
• Text property to New

26.  Right-click the New link button and select Copy.

27.  Click to the right of the New link button and enter two spaces, then
right-click and select Paste. Repeat this step so that you have three
New link buttons.

© All rights reserved. Not to be reproduced without prior written consent. 43


419-MA-43
Hands-On Exercise 3.1b:
Developing a Web Application
(continued)

28.  Change the Text property of the second link button to Top10 and
the last one to About

29.  Double-click the New link button to go to its event method. Clear the
list box by using LogListBox.Items.Clear(). Also clear the
status label text by assigning string.Empty to it.

30.  Return to design view and double-click the Top10 link button. In its
event method, display “Top 10 Selected” in the status label.

31.  Compile and test. Ensure New clears the list box and status label and
Top 10 shows the message.

Add a playful icon to the game table.

32.  In Solution Explorer, right-click the Tehi Web project and select
Add | New Folder. Name this folder Images

33.  Right-click the new Images folder and select Add | Add Existing
Item. Select All Files (*.*) from the drop-down. Navigate to the
directory C:\Course\419\Graphics\Icons. Pick an icon you like
and select Add to copy it into our assembly. Rename it App.ico

34.  From under the Standard tab in the toolbox, drag and drop an Image
control onto the first row of the table, placing it before the label.
Place a couple of spaces after the image.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-44
Hands-On Exercise 3.1b:
Developing a Web Application
(continued)

35.  In the property sheet of the Image control, set:


• ImageUrl to ~/Images/App.ico (type it in)
• Width and Height each to 20

36.  Compile and run.

The icon you selected should now be showing on the left side
of the title bar.

Add an About page to the Web application.

When completed, the About page you develop should look


something like this:

© All rights reserved. Not to be reproduced without prior written consent. 45


419-MA-45
Hands-On Exercise 3.1b:
Developing a Web Application
(continued)

You have a choice. You can design the About page manually or
you can include one that has already been laid out. In either case, it
will be necessary for you to implement the page navigation logic.

37.  Do this step only if including the pre-designed page: In the


solution explorer window, right-click the Tehi project (not solution)
and select Add | Existing Item… Navigate to the directory
C:\Course\419\Tools\AboutPage and select both
About.aspx and About.aspx.cs. Click Add.

38.  Do this step only if manually designing the page: In the


solution explorer window, right-click the Tehi project (not solution)
and select Add | New Item… | Visual C# | Web | Web Form and
name it About.aspx. Click Add.

39.  Do this step only if manually designing the page: Using the
designer, lay out the About form so it looks similar to the screenshot
on the previous page. Here are some suggestions that might help:
• In design view, add the labels, icons, and buttons as shown and
set their properties as appropriate
• Substitute your name in the appropriate text position
• In the source view, find the Style1 tag and set the width to 565
• Also in source view, set the page title to About TEHI

40.  Open About.aspx in design mode and double-click the OK button


to go to its event method. In this method, make a call to redirect to
Default.aspx.

41.  Compile and test. When you click OK on the About page, the user
should be redirected to the game page.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-46
Hands-On Exercise 3.1b:
Developing a Web Application
(continued)

Modify the game page to go to the About page when


requested.

42.  Open Default.aspx in design mode and double-click the About


link button to go to its event method. In this method, do a response
redirect to the About page.

43.  Compile and test. When you click the About link, the user should be
redirected to the About page.

What is indicated in the browser’s URL text box?

44.  Return to the event method for the About link button modify it to do a
response redirect call to go to About.aspx.

45.  Compile and test. Click the About link.

Now what is indicated in the browser’s URL text box?

© All rights reserved. Not to be reproduced without prior written consent. 47


419-MA-47
Hands-On Exercise 3.1b:
Developing a Web Application
(continued)

Add a user name text box to the form.

After the following eight steps, your screen will look something
like this:

46.  Open Default.aspx in design mode.

47.  Drag a TextBox into the first cell of the same row as the Deal button
(see partial screen shot on previous page).Set its properties to:
• (ID) property to NameTextBox
• Font Size to 12
• Text to blank
• Width to 96

48.  Drag a Button to the form into the cell to the right of the name text
(see earlier screenshot). In its property sheet, set:
• (ID) to LoginButton
• Font size to 12
• Text to Login
• Width to 96

49.  Double-click the Login button to go to its event method. Display in


the status label that the Login button was pressed.

50.  Compile and test. Go back and forth between the Deal button and
the Login button.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-48
Hands-On Exercise 3.1b:
Developing a Web Application
(continued)

Add the Swap buttons.

51.  Open Default.aspx.cs for editing and add the method:

private void SwapCard(int ix)


{
StatusLabel.Text = "Swap button " + ix + " pressed.";
}

52.  In design view, drag a Button to the form into the first cell of the fifth
row as in the previous screenshot. In its property sheet, set:
• (ID) to SwapButton0
• Font size to 12
• Text to Swap
• Width to 96

53.  Right-click this new Swap button and select Copy.

54.  Right-click the next cell to the right and select Paste. Repeat for the
remaining cells on this row so that you have five Swap buttons.

55.  In design view, double-click the first Swap button. In its event
method, call SwapCard(0)

56.  Repeat the previous step for the remaining Swap buttons. Increment
the button number by one each time.

57.  Compile and test. Click all buttons to ensure they are working.

© All rights reserved. Not to be reproduced without prior written consent. 49


419-MA-49
Hands-On Exercise 3.1b:
Developing a Web Application
(continued)

Congratulations! You have completed the bonus material.

This is the end of the exercise.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-50
Hands-On Exercise 4.1:
Defining Classes

Objective
Become familiar with creating classes by producing abstractions of standard
playing cards.

A standard deck of 52 playing cards is a common basis for many popular and
entertaining games, including Poker, Bridge, Hearts, Euchre, Blackjack,
Cribbage, Crazy Eights, Fish—or even your favorite! If you were to program
any of these games in C#, creating a PlayingCard class would be a good
place to start.

This abstraction of playing cards will form the basis of the business logic for
our game, “The Eyes Have It.”

A preliminary playing card class

Close the previous solution if you have not already done so.

Open the solution Tehi.sln found in the directory


C:\Course\419\Exercises\Ex41 (-web or –desktop).

Select desktop or Web as appropriate. If you have forgotten


how to do this, refer to a previous exercise.

This continues from the bonus solution of the previous


exercise.

© All rights reserved. Not to be reproduced without prior written consent. 51


419-MA-51
Hands-On Exercise 4.1:
Defining Classes
(continued)

Create a new class library for the playing card–related classes.

1.  If it is not already visible, open the Solution Explorer by selecting


View | Solution Explorer from the VS menu bar.

2.  Right-click the solution Tehi (not the project) and select Add | New
Project. In the dialog box that pops up, select a Project Type of
Visual C# | Windows | C# | Class Library and then enter
Name: CardLib
Location: C:\Course\419\Exercises\Ex41-web
or C:\419\Exercises\Ex41-desktop
as appropriate. Click OK.

A new project will be created for you with a single class in it


called Class1.cs.

3.  In the Solution Explorer window, right-click Class1.cs and rename


it PlayingCard.cs. When a dialog appears asking if other
references should be renamed, select Yes. Get a clean compile.

Add the basic fields for a playing card.

The rank field will be used to indicate if the card is an ace, a 2


through king, etc. We will implement this as an integer because it will
be used numerically throughout the application. The suit field will
be used to indicate if the card is a spade, heart, etc. We will first
declare an enum to define these values.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-52
Hands-On Exercise 4.1:
Defining Classes
(continued)

4.  Move to before the class declaration and add a public enum called
CardSuit. The elements are Clubs, Diamonds, Hearts, and
Spades.

5.  Move to the first line inside of the class and insert an integer field
called rank. It should be declared private and readonly (cannot
be changed except in a constructor).

6.  Repeat for the suit field, but its type should be CardSuit.

In the real world, once the rank and suit of a playing card are
established, they cannot be changed. This is why we made these
fields readonly.

7.  Add a private Boolean field called faceUp to track if the front or the
back of the card is showing. If the card is face-up, then the front will
be showing. It should not be declared readonly!

8.  Get a clean compile—ignore any not used warnings.

Add a constructor to force a playing card to be initialized when


it is created.

9.  After the field definitions, add a constructor with the signature:


public PlayingCard(int rank, CardSuit suit)

10.  In the body of the constructor, add the code to assign the rank
parameter to the rank field. You will need to use the this reference
to discriminate between them.

11.  Repeat for the suit.

© All rights reserved. Not to be reproduced without prior written consent. 53


419-MA-53
Hands-On Exercise 4.1:
Defining Classes
(continued)

12.  In the next line of code, initialize faceUp to be false.

13.  Get a clean compile—ignore any not used warnings.

Add the logic for flipping cards to change them from face-up to
face-down and vice versa.

14.  Add the method public void Flip(). It should flip the state of
the faceUp field. This can be done in one line of code without the
use of any if/else statements.

Use the ! operator.

15.  Get a clean compile—ignore any not used warnings.

Add ToString to provide a convenient output format.

Warning! Note that ToString should not do any output; it


should only return a string representation of the card.

16.  Move to the line after the Flip() method. Enter the word override
and press the <Spacebar>. Select ToString() from the drop-down
list and the method’s framework will be implemented for you.

17.  Delete all of the code inside this method.

18.  Add the logic to detect whether the card is face-up or face-down. If it
is face-up, return rank + " " + suit; If it is not face-up,
return "XX"; indicating the card is hidden.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-54
Hands-On Exercise 4.1:
Defining Classes
(continued)

19.  Get a clean compile.

We are now ready to test our playing card abstraction.

Add a reference in the Tehi project to the CardLib project.

20.  In Solution Explorer, right-click the References folder under the


Tehi project (not Solution) and select Add Reference. In the dialog
box, click the Projects tab (under Solutions) and select CardLib by
selecting the checkbox. Click OK.

Modify the DealButton_Click method to test the creation and


use of our playing cards.

Depending on the environment you are working in (desktop or


Web), the event method names might vary by capitalization. If this is
the case, the instructions will only give one name for simplicity.

21.  Right-click Form1.cs or Default.aspx in Solution Explorer and


select View Code.

22.  Add using CardLib; at the appropriate place.

23.  Move to the DealButton_Click method and delete the line that
displays the spade symbol.

24.  After the line that clears the list box, create an instance of a playing
card. Call its reference card. Use a rank value of 5 and a suit of
clubs (CardSuit.Clubs).

© All rights reserved. Not to be reproduced without prior written consent. 55


419-MA-55
Hands-On Exercise 4.1:
Defining Classes
(continued)

25.  Next, display the card’s information using something like:


LogListBox.Items.Add("Card: " + card);

26.  Compile (use <F5>) and test by clicking the Deal button.

What was displayed and why?

27.  Before the card is displayed in the list box, add card.Flip();

28.  Compile and test.

a. Now what was displayed?

b. How did ToString get called?

It is more typical to use a symbol for a playing card’s suit and


use a two-digit format. For example, the five of clubs would be 5♣.
Let’s implement this now!

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-56
Hands-On Exercise 4.1:
Defining Classes
(continued)

Modify the ToString() method to use standard two-digit card


codes.

One approach to doing this would be to use if/else logic, but


it’s easier to look up the appropriate values using string indexing.

29.  Open PlayingCard.cs, move to the ToString() method, and


start by adding definition of two strings with the appropriate
characters. When done, your code should look something like:
if (!faceUp) return "XX";
string suits = "\u2663\u2666\u2665\u2660";
string ranks = " A23456789TJQK";

30.  Replace the return statement with the Indexing logic. Note that the
CardSuit enum must be cast to int to be used as an index.
return "" + ranks[rank] + suits[(int)suit];

31.  Get a clean compile and test. Ensure that you got the correct two-
digit code, 5♣.

It would be more convenient for users of the playing card class if


some constant values were defined for the “named ranks.” It can be
confusing to remember that, for example, 12 is a queen. We will start
by defining constants for the special rank values (ace, jack, queen, and
king). This is not necessary for the suit since it is an enumeration.

Although it is tempting to try to make rank an enum too, this


turns out to be very inconvenient later. Rank is used almost
exclusively as an integer value, so we will leave it that way. At the
end of the course, if you like, you can try making rank an enum to
see the problems that it causes.
© All rights reserved. Not to be reproduced without prior written consent. 57
419-MA-57
Hands-On Exercise 4.1:
Defining Classes
(continued)

Add constant values in the playing card class for the named
ranks.

32.  Move to the top of the PlayingCard class and, before the fields,
insert constants for ace, jack, queen, and king. Jack is 11; king is 13.
Use something like: public const int Ace = 1;

33.  Get a clean compile.

In the preceding statements, const means the value is


constant and known at compile time. By definition, const values are
static so the static keyword is not required. The Microsoft coding
style is to use initial-cap format, not the all-uppercase convention
followed in some other languages.

Select the Form1.cs/Default.aspx.cs, and modify the


DealButton click method to use the constants.

34.  Select Form1.cs/Default.aspx.cs for editing and, in the


DealButton_Click method, modify the call to the constructor to
create a queen of clubs. Use PlayingCard.Queen

35.  Compile and test. Ensure that you got Q♣.

Congratulations! You have successfully completed the


exercise. If you have more time, please continue to the bonus.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-58
Hands-On Exercise 4.1:
Defining Classes
(continued)

If you have more time, make the following improvements to the


playing card class.

Modify the constructor of PlayingCard to validate the range


of the rank being provided.

When writing a class, it is usually a good idea to protect the


fields from being set to an invalid value. Right now the constructor of
a playing card will accept any integer value for the rank. It should be
limited to between 1 and 13. Let’s fix this now.

36.  Add a private method to the PlayingCard class to validate the


range of an integer. Use something like the following or copy it from
C:\419\CopyAndPaste\ValidateRange.txt:

private void ValidateRange(int val, int min, int max)


{
if ((val < min) || (val > max))
{
throw new ArgumentException("Value of " + val +
" is not between " + min + " and " + max);
}
}

Warning! Make sure you add this to the PlayingCard


class and not to Form1.cs/Default.aspx.cs, the main test
program. Do not write any try/catch code!

37.  Modify the constructor to call ValidateRange to check that the


rank is between Ace and King.

38.  Compile and test. The program should work as before.

© All rights reserved. Not to be reproduced without prior written consent. 59


419-MA-59
Hands-On Exercise 4.1:
Defining Classes
(continued)

39.  Modify the DealButton_Click method in the view and attempt to


construct a playing card with an invalid value. Try a rank of 15.

40.  Compile and test. The program should throw an exception. Select
from the VS menu bar Debug | Stop Debugging.

41.  Restore the program back to the queen so that it works again.

42.  Compile and test to ensure that it is working again.

Congratulations! You have completed the bonus.

This is the end of the exercise.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-60
Hands-On Exercise 4.2:
Implementing Properties

Objective
Become familiar with using properties, both auto-implemented and manual.
Currently we have no way of obtaining the rank or suit values, or setting or
getting the face-up status. We will implement properties for these now.

Close the previous solution if you have not already done so.

Open the solution Tehi.sln located in the directory


C:\419\Exercises\Ex42 (-web or –desktop).

If you have forgotten how to do this, refer to a previous


exercise.

This continues from the bonus solution of the previous


exercise.

Manually implement Rank and Suit get-only properties.

The Rank and Suit properties cannot be auto-implemented


because they are readonly. Also, they should not have a setter,
only a getter.

1.  Select PlayingCard.cs for editing and find the rank field.

2.  Right-click rank and select Refactor | Encapsulate Field. From the


dialog box, ensure that the property name is Rank (capital R) and click
OK and then Apply. The get-only property should have been written.

© All rights reserved. Not to be reproduced without prior written consent. 61


419-MA-61
Hands-On Exercise 4.2:
Implementing Properties
(continued)

3.  Repeat for the suit field.

We are now ready to test our properties.

Modify the DealButton_Click method to test the properties.

4.  Right-click Form1.cs/Default.aspx in Solution Explorer, select


View Code, and move to the DealButton_Click method.

5.  After the card is displayed in the list box, add the logic to display its
rank and suit individually. Rank, for example:
LogListBox.Items.Add("Rank: " + card.Rank);

6.  Compile and test (use <F5>). The queen should have a rank of 12.

Replace the faceUp field with an auto-implemented FaceUp


property.

It would be more convenient if the client code could just set or


get the face-up status of a playing card, rather than needing to “flip”
the card. We need a FaceUp property.

7.  Open PlayingCard.cs for editing and find the faceUp field.

8.  Make its declaration public and modify it to start with a capital F.

9.  Modify the declaration so that it becomes a property, for which get


and set are allowed.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-62
Hands-On Exercise 4.2:
Implementing Properties
(continued)

10.  Try to get a clean compile. You should get a number of errors
indicating that faceUp (lower case f) is undefined.

When using auto-implemented properties, all methods that


reference it must use the property.

11.  Fix these errors and get a clean compile.

Modify DealButton_Click() in the view to set the FaceUp


status instead of flipping the card.

12.  Open Form1.cs/Default.aspx.cs for editing and find the line of


code where the playing card is flipped.

13.  Change this to simply set the FaceUp property to true.

14.  Compile and test. The program should behave as before.

Congratulations! You have successfully completed the


exercise. If you have more time, please continue to the bonus.

© All rights reserved. Not to be reproduced without prior written consent. 63


419-MA-63
Hands-On Exercise 4.2:
Implementing Properties
(continued)

If you have more time, add the following properties to the


playing card class.

Add a manually implemented unique code property to the


playing card class.

A unique code property is very similar to ToString(), except


it is a property and gives only a two-digit ASCII result. This you will
find this convenient later in the course when adding images to the
user interface.

15.  Continue editing PlayingCard.cs and move to before the


ToString() method.

16.  Insert the framework for a property called Code. It should look
something like:
public string Code
{
get
{
}
}

17.  Copy the entire body of the ToString() method and paste it into
the body of the get of Code.

18.  Change the suit string to plain ASCII: "CDHS"

19.  Get a clean compile.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-64
Hands-On Exercise 4.2:
Implementing Properties
(continued)

Add a manually implemented unique-index property to the


playing card class.

A unique-index property returns a unique integer value for each


card. If the card is face-down, the index is 0. This you will also find
this useful later in the course when adding images to the user
interface.

20.  Insert before the Code an Index property. If the card is face-up,
return (int)suit * 13 + rank, else return 0

21.  Get a clean compile.

Test the Code and Index properties in the user interface.

22.  Open Form1.cs/Default.aspx.cs for editing and move to the


DealButton_Click(…) method. After the line that reports the suit,
add:

LogListBox.Items.Add("Code: " + card.Code);


LogListBox.Items.Add("Index:" + card.Index);

23.  Compile and test. The unique index should be 12 for the QC.

Congratulations! You have completed the bonus.

This is the end of the exercise.

© All rights reserved. Not to be reproduced without prior written consent. 65


419-MA-65
© All rights reserved. Not to be reproduced without prior written consent.
419-MA-66
Hands-On Exercise 4.3:
Leveraging Inheritance

Objective
Use inheritance to create a derived class, called FaceCard, to track the
number of eyes that a “royal” card has. Royal cards are also called “court” or
“face” cards. The number of eyes is an example of the kinds of extensions a
royal card might have.

All face cards have two eyes, except the jack of hearts, the jack
of spades, and the king of diamonds—they have only one. Ask your
instructor to explain this if it is not clear.

Close the previous solution if you have not already done so.

Open the solution Tehi located in the directory


C:\419\Exercises\Ex43 (-web or –desktop).

Add a new class to the CardLib project called FaceCard.cs.

1.  In the Solution Explorer, right-click the CardLib project and select


Add | Class. In the dialog box’s Name field, enter FaceCard.cs
and click Add.

2.  Open FaceCard.cs for editing (if it isn’t open already).

3.  Make the class declaration public and add the code to indicate that
FaceCard inherits from PlayingCard.

© All rights reserved. Not to be reproduced without prior written consent. 67


419-MA-67
Hands-On Exercise 4.3:
Leveraging Inheritance
(continued)

Add an auto-implemented property to track the number of


eyes.

4.  Define a public auto-implemented integer property called Eyes


that has a get with a private set. It should look like:

public int Eyes { get; private set; }

5.  Attempt to get a clean compile.

Why does the program not compile?

The PlayingCard class requires that it be provided the rank


and the suit when it is constructed. Since we are inheriting from the
PlayingCard class, we must do the same.

Add a constructor to force a face card to be initialized when it


is created.

6.  Continue editing FaceCard.cs and add a constructor. Type


ctor<tab><tab> to generate the method stub then change the
specification public FaceCard(int rank, CardSuit suit)

7.  Add a call to base at the appropriate position to call the base-class


constructor. Pass rank and suit to the base class.

Warning! There is no semicolon after the call to base.

8.  Move to the body of the constructor and set Eyes to 2.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-68
Hands-On Exercise 4.3:
Leveraging Inheritance
(continued)

9.  Get a clean compile—use Build | Rebuild Solution.

Modify the DealButton_Click method in the view to create a


FaceCard instead of a playing card.

10.  Move to DealButton_Click in Form1.cs/Default.aspx.cs


and find the code PlayingCard card = new PlayingCard(…).
Change all occurrences of PlayingCard in that line to FaceCard

11.  Compile and test.

How does the program behave now?

We have not yet done anything to make the behavior of a face


card any different than a playing card, so it does just what a playing
card did.

Add logic to determine the number of eyes.

It is not necessary or desirable that this be done in one


complicated if statement. Use three simple if statements.

12.  Edit FaceCard.cs and move to the constructor. After the line that
sets the number of eyes to 2, add the code to change the number of
eyes to 1 if the card is any of jack of hearts, jack of spades, or king
of diamonds. Use something like the following and repeat for each of
the one-eyed cards, then get a clean compile.

if ((rank == Jack) && (suit == CardSuit.Hearts)) Eyes = 1;

© All rights reserved. Not to be reproduced without prior written consent. 69


419-MA-69
Hands-On Exercise 4.3:
Leveraging Inheritance
(continued)

Override ToString to report the number of eyes for a face


card.

13.  Following the constructor, type the word override followed by one
press of the <Spacebar> and select ToString from the list. This
will produce the framework for the ToString method.

14.  In the body, if the card is not face-up, return base.ToString();


otherwise, return base.ToString() + Eyes;

15.  Compile and execute.

What is different now?

Test with a one-eyed card.

16.  Open Form1.cs/Default.aspx.cs for editing and move to the


DealButton_Click method. Change the card constructed to be
the jack of spades.

How many eyes are shown now?

17.  Try setting the card to be face-down. It should just show XX.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-70
Hands-On Exercise 4.3:
Leveraging Inheritance
(continued)

18.  Set the card back to being face-up.

19.  Add the code to display the number of eyes. Use something like:

LogListBox.Items.Add("Eyes: " + card.Eyes);

20.  Compile and test.

Congratulations! You have completed the exercise.


Continue to the bonus if you have more time.

Improve the protection of the face card’s data.

Add logic in the constructor to validate that the rank is a valid


rank for a face card.

21.  Return to FaceCard.cs and before the line Eyes = 2; add a call
to check that the card’s rank is appropriate for a face card. Type the
following (IntelliSense will not work here):

ValidateRange(rank, Jack, King);

22.  Try to compile.

What happens?

© All rights reserved. Not to be reproduced without prior written consent. 71


419-MA-71
Hands-On Exercise 4.3:
Leveraging Inheritance
(continued)

Change ValidateRange to be accessible to the derived class.

To allow a member of a base class to be accessed by a


derived class, but not to an outside client class, we can use
protected encapsulation.

23.  Edit PlayingCard.cs and change the ValidateRange function to


be protected.

24.  Compile and run. The program should behave as before. Try testing
with a bad rank value. Restore it to a good value when done.

This is the end of the exercise.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-72
Hands-On Exercise 5.1:
Associations and Collections

Objective
Become familiar with using collection classes from the .NET library
specifically to produce a deck of playing cards. A stack collection will most
closely match the behavior of a card deck.

Part A: Creating the card deck

Close the previous solution if you have not already done so.

Open the solution Tehi.sln located in the directory


C:\Course\419\Exercises\Ex51 (-desktop or –web)

This exercise continues from the bonus of the previous


exercise, plus the background color serialization has been added as
demonstrated by your instructor.

In Solution Explorer, add a new class to CardLib called


CardDeck.cs. Make its declaration public.

Make sure you add CardDeck.cs to the CardLib project, not


the Tehi project. If you’ve forgotten how to add a class to a project,
refer back to Exercise 4.3.

© All rights reserved. Not to be reproduced without prior written consent. 73


419-MA-73
Hands-On Exercise 5.1:
Associations and Collections
(continued)

Add a field of type Stack<PlayingCard> to hold the cards.

1.  Define a private field called deck within the CardDeck class. It


should be a generic stack, as in:
private Stack<PlayingCard> deck = new Stack<PlayingCard>();

2.  Get an error-free compile at this point. Ignore any unused field


warnings.

Copy and paste the constructor code—make sure you know


what it is doing.

3.  Open C:\Course\419\CopyAndPaste\CardDeckCtor.txt. It
contains a framework for the constructor—but it will not compile
without changes! Copy and paste it into the inside of the CardDeck
class and indent as appropriate. Review for a few minutes and make
sure you know what it is doing.

The line of code that declares Array suitChoices is a


technique that lets us obtain an array containing all the possible
values for an enum. The typeof keyword is used to determine the
type of the items.

4.  At the place indicated, insert the code to add the card to the deck.
You are “pushing” something onto the deck stack.

5.  Get a clean compile. Tidy up the code if you need to.

74 © All rights reserved. Not to be reproduced without prior written consent.


419-MA-74
Hands-On Exercise 5.1:
Associations and Collections
(continued)

Create a ToString method for the CardDeck class.

6.  Following the constructor, insert the overall layout for


public override string ToString().

Type override and press <Spacebar> to have Visual Studio


do it for you.

7.  In the body of ToString, create a string variable and initialize it to


an empty string: string rep = string.Empty;

8.  Create a foreach loop to go through each card in the deck:


foreach (PlayingCard card in deck)

9.  In the body of the foreach loop, concatenate the string


representation of the playing card using
rep = rep + card + " ";

Remember that each PlayingCard has its own ToString.

10.  Return rep.Trim() to the caller.

11.  Get a clean compile—use Build | Rebuild Solution.

© All rights reserved. Not to be reproduced without prior written consent. 75


419-MA-75
Hands-On Exercise 5.1:
Associations and Collections
(continued)

Modify the view to test the new CardDeck class.

12.  Open Form1.cs/Default.aspx.cs for editing and add as a field:


Desktop: private CardDeck deck = new CardDeck();
Web: private CardDeck deck;

Don’t confuse the variable deck in your user interface


Form1.cs/Default.aspx.cs with the deck list in the
CardDeck class. They have different scopes.

13.  Web only: Move inside the Page_Load(…) method and add the
logic to retrieve the user’s card deck from the session. You can use
the code from the copy-and-paste file DeckSessionLogic.txt if
you like. It should look something like:
deck = (CardDeck) Session["deck"];
if (deck == null)
{ deck = new CardDeck();
Session["deck"] = deck;
}

14.  Move to the DealButton_Click method, and comment out all of


the code except the line that clears the list box.

15.  After the line that clears the list box, add the code:
LogListBox.Items.Add(deck.ToString());

16.  Compile and test.

You should see the deck displayed. The list box is not wide
enough to show the whole deck and there is no horizontal scroll bar
in the Web version—so please estimate that all 52 cards are there.

76 © All rights reserved. Not to be reproduced without prior written consent.


419-MA-76
Hands-On Exercise 5.1:
Associations and Collections
(continued)

Part B: Dealing cards from the deck

Create a method to deal cards from the card deck.

17.  Select CardDeck.cs for editing and position the cursor on a new
blank line before the ToString() method.

18.  Insert the layout for a method called Deal using the specification
public PlayingCard Deal()

19.  In the body of Deal, check if there are fewer than two cards left in
the deck. If so, throw a new InvalidOperationException with
the message Too few cards in the deck.

20.  Return the top card to the caller face down. Use something like:
a. Pop the card off the stack first (into a temporary variable).
b. Set popped card to be face down (FaceUp = false)
c. Return the card to the caller.

21.  Get a clean compile.

Modify the view to test the dealing of cards.

22.  Select the DealButton_Click method in Form1.cs or


Default.aspx. After displaying the deck, add the code to deal one
(and only one) card into a PlayingCard reference. Use
PlayingCard card = deck.Deal();

© All rights reserved. Not to be reproduced without prior written consent. 77


419-MA-77
Hands-On Exercise 5.1:
Associations and Collections
(continued)

23.  Remove the comment characters from the six lines of code that set
the card to face up and display information about it. Do not
uncomment the line that creates the face card or the line that shows
the eyes.

24.  Compile and test. Repeat many times (50+) to confirm that cards are
being removed permanently from the deck and that finally the
exception will be thrown. Use Debug | Stop Debugging to recover
from the exception.

Provide a method to allow cards to be added back into the


deck.

Just as in the real world, cards need to be returned to the deck.

25.  Select CardDeck.cs for editing and position the cursor on a new
blank line after the end of the Deal method.

26.  Insert the overall layout for an additional method called Add using
public void Add(PlayingCard card)

27.  In the body of Add, set the card back to facing up, and then push it
back on the stack.

28.  Get a clean compile.

78 © All rights reserved. Not to be reproduced without prior written consent.


419-MA-78
Hands-On Exercise 5.1:
Associations and Collections
(continued)

Modify the view to test returning the cards to the deck.

29.  Select the DealButton_Click method in Form1.cs or


Default.aspx for editing and, after the line that displays the index,
add a call to deck.Add(card)

30.  Compile and test. The same card should be repeatedly dealt, since
we are always putting it back. Click Deal more than 52 times to
ensure the exception is never thrown.

Congratulations! You have successfully completed the


exercise. Continue to the bonus if you have more time.

Add the ability to shuffle the card deck.

For most card games, the deck is shuffled before it is dealt. If


you don’t know what “shuffling the deck” means, ask your instructor.

© All rights reserved. Not to be reproduced without prior written consent. 79


419-MA-79
Hands-On Exercise 5.1:
Associations and Collections
(continued)

Provide a method to allow cards to be shuffled.

31.  Select CardDeck.cs for editing and add the field


private Random rnd = new Random(). This is the .NET
random number generator. It will seed from the time of day.

32.  Position the cursor to after the Add method, and insert the overall
layout for an additional method using the specification:

public void Shuffle()

Add logic to shuffle the deck.

A good algorithm for shuffling is to loop through the deck one


time, swapping each card with some randomly selected card. This is
called the “Simple Knuth Shuffle.” Unfortunately, a stack collection
doesn’t support indexing, so we’ll need to first convert it to an array.
This will improve performance, too.

33.  Convert the deck to an array and then clear the cards from the deck:

PlayingCard[] cards = deck.ToArray();


deck.Clear();

34.  Now loop through the array using a for loop to select every card in
the deck: for (int i = 0; i < cards.Length; i++)

80 © All rights reserved. Not to be reproduced without prior written consent.


419-MA-80
Hands-On Exercise 5.1:
Associations and Collections
(continued)

35.  In the body of the for loop, add the logic to shuffle the cards. Pick
the random card using something like:
int swapIndex = rnd.Next(0,cards.Length);

This will return a random number within the array index range.

36.  Swap cards[i] with cards[swapIndex]. It is not necessary to


clone cards for this, but you will need a temporary playing card
reference. This is the “classic” swap algorithm.

37.  After the for loop, use a foreach loop to push every card in the
now-shuffled cards array back into the deck stack.

38.  Get a clean compile.

Modify the test program to check the Shuffle method.

39.  Select Form1.cs/Default.aspx.cs for editing and, after the


code that clears the list box in DealButton_Click, call
deck.Shuffle();

40.  Compile and test. Note that every click of the Deal button will change
the order of the cards in the deck and a new card will be dealt.

This is the end of the exercise.

© All rights reserved. Not to be reproduced without prior written consent. 81


419-MA-81
© All rights reserved. Not to be reproduced without prior written consent.
419-MA-82
Hands-On Exercise 6.1:
Down-Casting

Objective
Become familiar with casting up and down inheritance hierarchies.
Specifically, we will create a control class to encapsulate the game logic for
Tehi. If you are not familiar with how Tehi is played, your instructor will
explain. There are two parts to implementing the TehiGame class—
manipulating the cards and then evaluating the hand.

Part A: Manipulating cards (dealing) in the TehiGame class

Close the previous solution if you have not already done so.

Open the solution Tehi.sln located in the directory


C:\Course\419\Exercises\Ex61 (-web or –desktop).

This project contains the solution files from the previous


exercise. We will use copy-and-paste code to expedite the
development of the TehiGame class since much of it is very similar
to the other classes we have previously implemented.

Add a new class called TehiGame to the CardLib project and


make its declaration public.

If you have forgotten how to do this, see the instructions in


Exercise 4.3.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-83
Hands-On Exercise 6.1:
Down-Casting
(continued)

Add the fields to hold the card deck and the game hand.

1.  Within the TehiGame class, declare a private field for the card deck
using CardDeck deck = new CardDeck();

2.  Add a private field called hand that is a generic List. It should be


declared and instantiated to hold PlayingCards:

List<PlayingCard> hand = new List<PlayingCard>();

3.  Get a clean compile. Ignore any unused field warnings.

Add a method to deal cards into the hand.

4.  Create the framework for a method with the specification


public void Deal(). This method will be called each time the
player clicks the Deal button. This method should:
• Return any cards already in the hand back to the deck
• Clear the hand
• Shuffle the deck
• Loop five times in for loop
• Deal a card from the deck
• Set the card face up
• Put the card in the hand

To save time, please use the copy-and-paste code found in


C:\Course\419\CopyAndPaste\TehiDealLogic.txt.

5.  Get a clean compile.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-84
Hands-On Exercise 6.1:
Down-Casting
(continued)

6.  Add a ToString() method that lists all the cards in the hand.
Again, please use the copy-and-paste code found in
C:\Course\419\CopyAndPaste\TehiGameToString.txt.

7.  Get a clean compile.

Modify the user interface to use the TehiGame class.

8.  Open Form1.cs/Default.aspx.cs for editing and replace the


deck field with a game field. Use:
private TehiGame game = new TehiGame();

9.  Web only: Move to the Page_Load method and replace the deck-
saving logic so it becomes the game-saving logic; i.e., change all six
occurrences of deck to game and both occurrences of CardDeck to
TehiGame.

10.  Move to the DealButton_Click method and delete all of the code
except the line that clears the list box. After it, add:
game.Deal();
ShowOutput();

11.  Right-click on the word ShowOutput() and when the drop-down list
appears, select Generate | Method Stub. Delete the exception code
that is generated.

12.  Cut the line of code to clear the list box from DealButton_Click
and paste it into ShowOutput.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-85
Hands-On Exercise 6.1:
Down-Casting
(continued)

13.  After the line that clears the list box, display the game. Use
LogListBox.Items.Add(game.ToString());

14.  Compile and test. You should see different hands being dealt.

Part B: Evaluating the hand

Now that we have cards being dealt into a hand, we need to


evaluate the score and keep the running total. Evaluating a hand in
Tehi is simple. Basically multiply the total eyes on all face cards by
the total rank of the non-face cards. For example, a hand that has
the cards 2D, 7S, 9C, and KC showing would be (2 + 7 + 9)*(2) = 36.
Note that the score of a hand with no face cards or no non-face
cards would be 0.

Add the scoring code to the game hand.

15.  Select TehiGame.cs for editing and move the cursor to after the
fields.

16.  Add the framework for a Score property. It should look like:
public int Score
{
get
{
}
}

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-86
Hands-On Exercise 6.1:
Down-Casting
(continued)

17.  Insert into the get of the Score property the logic to evaluate the
hand. It should look something like the following (finish the logic for
the … portions):
int totalEyes = 0;
int totalRank = 0;
foreach (PlayingCard card in hand)
{
… Determine if it is a FaceCard by checking its type, not its rank…
… If so, cast it as a FaceCard and add the number of
eyes to totalEyes …
… If not, add the rank to the totalRank …
}
return totalRank * totalEyes;

18.  Get a clean compile.

Report the evaluation of the hand to the user.

19.  Open Form1.cs/Default.aspx.cs for editing again and move to


the ShowOutput method.

20.  Add the code to show the game score in the LogListBox with some
appropriate message.

21.  Compile and test. Double-check the calculations.

Congratulations! You have successfully completed the


exercise. Continue to the bonus if you have more time.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-87
Hands-On Exercise 6.1:
Down-Casting
(continued)

Add support for tracking the number of games played (hands


dealt) and the best score on an individual hand.

Add the logic to track the total hands dealt and the best hand
score.

22.  Open TehiGame.cs for editing and as the first line of code within
the class, add two auto-implemented properties—one called
HandsDealt and one called BestHandScore. They should both be
declared public, return an integer, and have a private set.

23.  Move to the Deal(…) method and after the loop add the logic to:
a. Count the HandsDealt.
b. Determine if this score is the best score and, if so, record it.

24.  Get a clean compile.

Display the total hands played and best hand scored.

25.  Open Form1.cs/Default.aspx.cs for editing, and in the


ShowOutput method, display with an appropriate message the total
hands played and best hand scored in the status label.

26.  Compile and test.

What happens when you start a new game via the menu?

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-88
Hands-On Exercise 6.1:
Down-Casting
(continued)

Construct a new game when a new game is requested by the


user.

27.  Open Form1.cs/Default.aspx in design mode and double-click


the New menu item. This will take you to its event method.

28.  Add the code to create a new game instance using:


game = new TehiGame();

29.  Web only: Store the game back into the session.
Session["game"] = game;

30.  Compile and test. Ensure that your best score is restarted for each
new game (it will be the same as the first score you achieve).

This is the end of the exercise.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-89
© All rights reserved. Not to be reproduced without prior written consent.
419-MA-90
Hands-On Exercise 6.2:
Implementing Interfaces

Objective
Although the ToString() method allows us to display a game hand, the
application will need to be able to loop through and obtain individual playing
cards in order to display them graphically (future exercise). We can support
looping through the cards by realizing IEnumerable<PlayingCard> in the
TehiGame class.

Close the previous solution if you have not already done so.

Open the solution Tehi located in the directory


C:\Course\419\Exercises\Ex62 (-web or –desktop).

This project contains the solution files from the bonus of the
previous exercise.

Implement the IEnumerable<PlayingCard> interface in


TehiGame controller.

1.  Open the file TehiGame.cs into the edit area.

2.  Move to the class declaration and add the specification that


TehiGame implements IEnumerable<PlayingCard>.

3.  Right-click in the word IEnumerable and when the underline


appears, click it. From the drop-down list, select Implement
interface IEnumerable<PlayingCard>.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-91
Hands-On Exercise 6.2:
Implementing Interfaces
(continued)

4.  Scroll to the end of the class and find the newly added methods.

It is very convenient that TehiGame controller uses a


List<PlayingCard> internally to hold the cards in the hand. It
already has an enumerator that we can return.

5.  Replace the automatically generated throw code in each


GetEnumerator() with return hand.GetEnumerator();

6.  Get a clean compile.

Test our enumerator via the user interface.

7.  Open Form1.cs/Default.aspx.cs for editing and move to the


ShowOutput method.

8.  Before the line that shows the game.ToString(), add a foreach


loop to go through each playing card in the game and display it
individually in the list box. Use something like:

foreach (PlayingCard c in game)


{
LogListBox.Items.Add(c.ToString());
}

9.  Compile and test. In the desktop version, you can resize the form as
necessary to see all cards. Note that the individual cards are shown
in the same order as in the game.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-92
Hands-On Exercise 6.2:
Implementing Interfaces
(continued)

Modify the loop to output the cards in reverse order.

10.  Change the foreach loop to output the cards in the reverse order;
i.e., call the Reverse() extension method on the game.

11.  Compile and test.

The order should now be reversed from before.

Congratulations! You have successfully completed the


exercise. Continue to the bonus if you have more time.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-93
Hands-On Exercise 6.2:
Implementing Interfaces
(continued)

Finish the game logic by adding support for swapping cards.

The game logic is not complete. When actually playing, the


user can optionally swap a single card after each hand is dealt in
order to improve their score. Let’s implement this now.

Add the logic to support the swapping of cards.

12.  Open TehiGame.cs for editing and after the BestHandScore


property, add an auto-implemented bool property called
CanSwapCards. This is to track if swapping is allowed or not. The
set clause of the property should be private.

13.  Move to the Deal() method and at the end set CanSwapCards to
true. Cards can only be swapped after dealing.

14.  After the end of the Deal() method, add the framework for a new
method: public void SwapCard(int cardIndex)

15.  Add the logic to swap the card specified below or use
C:\Course\419\CopyAndPaste\SwapCardLogic.txt.
• Add hand[cardIndex] back into the deck
• Shuffle the deck
• Deal a card back into hand[cardIndex]
• Set hand[cardIndex].FaceUp = true;
• Record if this new hand produces the best hand score (copy
the line of code from the Deal() method)
• Set CanSwapCards to false (no more swapping until the
next deal operation)
16.  Get a clean compile.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-94
Hands-On Exercise 6.2:
Implementing Interfaces
(continued)

Modify the user interface to support card swapping.

17.  Open Form1.cs/Default.aspx.cs for editing and move to the


ShowOutput() method. Delete the for loop that outputs each
individual playing card—this will make it easier to see the swapping.

18.  Insert the logic to enable/disable the Swap buttons based on whether
the game can swap cards. Use something like:
SwapButton0.Enabled = game.CanSwapCards;

19.  Repeat for the remaining buttons (1 to 4).

20.  Open Form1.cs/Default.aspx in design mode, and set each


Swap button’s Enabled property to false

21.  Compile and test. The buttons should be disabled until the Deal
button is clicked.

Add event processing for the Swap buttons.

22.  Open Form1.cs/Default.aspx.cs in edit mode and move to the


SwapCard(…) method.

23.  In this event method, insert the statements:

game.SwapCard(ix);
ShowOutput();

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-95
Hands-On Exercise 6.2:
Implementing Interfaces
(continued)

24.  Compile and test. Confirm that the corresponding card in the output
is being changed each time you click a Swap button.

Clean up the new game logic.

25.  Move to the event method for the new game menu item and replace
its logic with:

game = new TehiGame();


ShowOutput();
LogListBox.Items.Clear();
StatusLabel.Text = string.Empty;
Session["game"] = game; // Web only

26.  Compile and test.

Congratulations! You have completed the bonus material.

This is the end of the exercise.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-96
Hands-On Exercise 7.1a:
Adding Desktop Card Images—COM Components

Objective
So far, our game is not very graphical. We really should be showing card
images, not just text. Because many components are available to render the
images of playing cards, it is probably quickest to reuse one of these rather
than write our own.

Close the previous solution if you have not already done so.

Install the playing-card-image control.

This control is an OCX, very typical of the type of COM


components that can be purchased (or found free on the Internet).
Before we can assemble it into our game program, it must be
installed on the system in a standard fashion.

1.  The “distribution” for the playing-card control we will be using can be


found in C:\Course\419\Tools\COM_Card. Using Windows
Explorer, navigate to this directory.

2.  Execute the Setup program by double-clicking it. Accept all the


defaults.

Warning! Verify that the program reports that the


component was successfully installed. If not, notify your
instructor.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-97
Hands-On Exercise 7.1a:
Adding Desktop Card Images—COM Components
(continued)

Prepare Visual Studio to import the card control element.

The idea here is to add the control to the VS toolbox so that we


can use it in our game.

3.  Start Visual Studio if it is not already running.

4.  Close any open solutions.

5.  Open the solution Tehi.sln in the directory


C:\Course\419\Exercises\Ex71-desktop-com.

6.  Open Form1.cs in the Forms Designer.

Import the Tehi.dll COM control into the VS Forms Designer.

7.  Right-click within the body of the All Windows Forms tab of the
ToolBox and select Choose Items from the pop-up menu.

8.  In the dialog that appears, click the COM Components tab.

9.  Click the Browse button.

10.  In the Open dialog that appears, navigate to the directory


C:\Program Files\Tehi and select Tehi.ocx.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-98
Hands-On Exercise 7.1a:
Adding Desktop Card Images—COM Components
(continued)

11.  Click the Open button.

Notice that the component Tehi.Card has been added into


the COM component list and the checkbox for it is selected.

12.  Click the OK button.

Notice in the toolbox that a new component called Tehi.Card


has been added as a COM component. It will be at the very bottom
of the items in the All Windows Forms tab. This is actually the proxy
for our .NET version of the component.

Add playing card images to our game table.

13.  Click the Tehi.Card component in the toolbox.

14.  Move to the game table and drag an outline where you want a card
image to be (above the first Swap button). Adjust the position so that
it looks correct. Adjust the height of the form and the list box if
necessary.

Note that the size is fixed, so the card image will snap to the
predefined size.

15.  Right-click and select Properties. In the Properties sheet, set:


• Visible to false (cards don’t show until they are dealt)
• Anchor to the bottom only

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-99
Hands-On Exercise 7.1a:
Adding Desktop Card Images—COM Components
(continued)

16.  Copy the first card image and paste it so that there are a total of five
card images on the game table.

It should look something like the screenshot below. The card


images might show as card backs in the forms designer.

17.  Compile and execute the program. The cards should not yet appear.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-100
Hands-On Exercise 7.1a:
Adding Desktop Card Images—COM Components
(continued)

Implement a method to paint the cards.

Our business logic is in the PlayingCard class. We need to


transfer the appropriate data from it to the playing card image
generator (AxTehi.AxCard).

18.  Open Form1.cs for editing and move before the button1_Click
method. Add the framework for a method with the specification:
private void PaintCard(AxTehi.AxCard image, PlayingCard card)

19.  In the body of this method, set image.Visible = true;

20.  Set the image’s Card property to the card’s rank using something
like image.Card = card.Rank

21.  In the next line, set the image’s suit to the card’s suit. Use something
like image.suit = (int)card.Suit.

22.  Assign to the image’s FaceUp property the card’s FaceUp property.

23.  Get a clean compile. Use Build | Rebuild Solution.

Modify ShowOutput() to call PaintCard(…).

We now want to output the playing card images. This could be


set up as a loop, but it turns out to be quicker/easier to just make five
calls to PaintCard(…).

24.  Find the ShowOutput() function and move to just before the end of
the method.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-101
Hands-On Exercise 7.1a:
Adding Desktop Card Images—COM Components
(continued)

25.  Insert a conditional to check if any cards have been dealt. Use:
if (game.Count() > 4)
{
}

26.  Inside the body of this conditional, insert five calls to a card-painting
method. Use PaintCard(axCard1, game.ElementAt(0));
and so on.

Watch out—the cards are numbered 1 to 5, but the hand


element indexes are 0 to 4.

27.  Compile and test.

The card images should now show when you click deal. Your
screen should look something like the screenshot below:

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-102
Hands-On Exercise 7.1a:
Adding Desktop Card Images—COM Components
(continued)

Modify the Game | New menu option to clear the cards.

28.  Move to the event method for the new game menu item and at the
end, set the Visible property of each axCard to false.

29.  Compile and test. Try starting a new game.

The card images should disappear.

Congratulations! You have completed the exercise.

This is the end of the exercise.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-103
© All rights reserved. Not to be reproduced without prior written consent.
419-MA-104
Hands-On Exercise 7.1b:
Adding Desktop Card Images—Image List Component

Objective
In this exercise, you will use a .NET image list component to add playing card
images to your Tehi game.

Open the starting point for this exercise.

This exercise starts with the bonus solution from the previous
Exercise 6.2.

1.  In Visual Studio, close any open solutions and launch Tehi.sln


from the directory C:\Course\419\Exercises\Ex71-desktop.

2.  Open Form1.cs in the Forms Designer.

3.  Drag a PictureBox control to the position where you want the first
card image. In its property sheet, set:
• Anchor to the bottom only
• Size: Height to 96
• Size: Width to 69
• Visible to false\

Adjust its position so that it looks correct. Resize the list box if
necessary to make room for the card image.

4.  Copy this picture box and paste it in four more times. Position the
picture boxes so that they look right.

It should look something like the screenshot on the next page.


The card images will show in green.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-105
Hands-On Exercise 7.1b:
Adding Desktop Card Images—Image List Component
(continued)

5.  Compile and execute the program. The cards should not yet appear.

Obtain a playing card image list for our game-table form.

An image-list component has been pre-populated with playing


card images. We will copy and paste this onto our game-table form.

6.  Launch a second instance of Visual Studio and open the solution in


C:\Course\419\Tools\PlayingCardImageListForm. Then
open PlayingCardImageListForm.cs in design mode.

7.  At the bottom of the design pane, find the PlayingCardImageList


control in the component bar at the bottom. Right-click it and select
Copy.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-106
Hands-On Exercise 7.1b:
Adding Desktop Card Images—Image List Component
(continued)

8.  Return to Form1.cs in design mode in the first instance of Visual


Studio. Right-click the component bar at the bottom and select
Paste.

9.  Close the second instance of Visual Studio.

Modify our game-table form to use the picture boxes and the
image list.

Our business logic is in the PlayingCard class. We need to


transfer the appropriate data from it to the picture box images.

Each image in the image list is accessible by an index value. 0


will provide the face-down image; 1 to 52 will provide the appropriate
playing card face.

10.  Open Form1.cs for editing and move to after the end of the
ShowOutput() method. Add a method to paint the cards on the
display as shown below or use the copy-and-paste code in
C:\Course\419\CopyAndPaste\PictureBoxPaintCard.txt.

private void PaintCard(PictureBox image, PlayingCard card)


{
image.Visible = true;
int ix = card.Index;
image.Image = PlayingCardImageList.Images[ix];
}

11.  Get a clean compile. Use Build | Rebuild Solution.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-107
Hands-On Exercise 7.1b:
Adding Desktop Card Images—Image List Component
(continued)

Modify ShowOutput() to call PaintCard(…).

We now want to output the playing card images. This could be


set up as a loop, but it turns out to be quicker/easier to just make five
calls to PaintCard(…).

12.  Find the ShowOutput() method, and insert at the end a conditional
to check if any cards have been dealt. Use:

if (game.Count() > 4)
{
}

13.  Inside the body of this conditional, insert five calls to a card-painting
method. Use:
PaintCard(pictureBox1, game.ElementAt(0)); and so on.

Watch out—the picture boxes are numbered 1 to 5, but the


hand element indexes are 0 to 4.

14.  Compile and test. The card images should now show. After dealing a
few hands, click the New menu item. Note the card images were not
cleared.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-108
Hands-On Exercise 7.1b:
Adding Desktop Card Images—Image List Component
(continued)

Modify the Game | New menu option to clear the cards.

15.  Move to the event method for the new game menu item and, before
the call to ShowOutput(), create an array of image components
using something like:

PictureBox[] images = {pictureBox1, pictureBox2 …};

16.  In the next line, loop through all the images and set their Visible
property to false.

17.  Compile and test. Try starting a new game. The card images should
disappear.

Congratulations! You have completed the exercise.

This is the end of the exercise.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-109
© All rights reserved. Not to be reproduced without prior written consent.
419-MA-110
Hands-On Exercise 7.1c:
Adding Web Card Images—Image Component

So far, our game is not very graphical. We really should be showing card
images, not just text. Delivering images to a browser in a Web application is
straightforward.

Open the starting point for this exercise.

1.  In Visual Studio, close any open solutions and launch Tehi.sln


from the directory C:\Course\419\Exercises\Ex71-web.

Add playing card images to the Web sites assembly.

2.  In Solution Explorer, right-click the Images folder and select Add |


Add Existing Item. Select All Files (*.*) from the drop-down.
Navigate to the directory C:\Course\419\Graphics
\CardImages and click in the body of the file display in the dialog
box. Press <Ctrl><A> to select all images. Click Add and all the
images will be copied into our assembly.

Add playing card images to the desktop using image buttons.

3.  Open Default.aspx in design mode and set the Align property of


each cell in the fourth row to center

4.  Drag and drop an ImageButton onto the table in the first cell of the
fourth row. Set its properties as follows:
• Enabled to false
• Height to 96px
• ImageUrl to ~/Images/green.bmp
• Width to 69px

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-111
Hands-On Exercise 7.1c:
Adding Web Card Images—Image Component
(continued)

Putting green on green is the equivalent of setting the card


images to not visible. It has the advantage, though, of avoiding the
resizing of the table that HTML will do when controls are set to
visible/not visible.

5.  Right-click the first Image button and copy it. Paste it four times into
each of the adjacent cells in the same row.

6.  Run the program.

You should still see just a green rectangle; green on green


should not show.

Implement a method to display individual cards on the game


table.

The filenames for the playing card images we have are in the
form 5D.gif. We can use the Code to compose the filename.

7.  Open Default.aspx.cs for editing and move to after the


DealButton_Click(…) method. Add the following method:

private void PaintCard(ImageButton image, PlayingCard card)


{
image.ImageUrl = "~/Images/" + card.Code + ".gif";
}

8.  Get a clean compile.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-112
Hands-On Exercise 7.1c:
Adding Web Card Images—Image Component
(continued)

Modify ShowOutput() to call PaintCard(…).

We now want to output the playing card images. This could be


set up as a loop, but it turns out to be quicker/easier to just make five
calls to PaintCard(…).

9.  Find the ShowOutput() method and at the end, insert a conditional


to check if any cards have been dealt. Use:

if (game.Count() > 4)
{
}

10.  Inside the body of this conditional, insert five calls to a card-painting
method. They should look like:

PaintCard(ImageButton1, game.ElementAt(0));.

Watch out—the cards are numbered 1 to 5, but the hand


element indexes are 0 to 4.

11.  Compile and test. The card images should now show. After dealing a
few hands, click the New link button. Note the card images were not
cleared.

You might notice that the screen flashes a bit when it updates
now that the card images are showing. Don’t worry—we’ll fix this in
the bonus.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-113
Hands-On Exercise 7.1c:
Adding Web Card Images—Image Component
(continued)

Modify the New menu to clear the cards (set their images back
to green).

12.  Move to the event method for the new game menu item and at the
end, create an array of image buttons using something like:

ImageButton[] images = {ImageButton1...};

13.  In the next line, loop through all the images and set their ImageUrl
property to "~/Images/green.bmp".

14.  Compile and test. Try starting a new game after dealing a few hands.

The card images should disappear.

Congratulations! You have added playing card images to


your game table. If you have more time, continue to the bonus.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-114
Hands-On Exercise 7.1c:
Adding Web Card Images—Image Component
(continued)

If you have more time, add event handling for the image
buttons (card swapping).

Although there are standard buttons on the page to allow


swapping cards, the user will probably try to click the card images
directly. Let’s improve their experience by adding support for this.

15.  Return to Default.aspx in design mode and double-click the first


ImageButton. In its event method, add SwapCard(0);

16.  Repeat for the remaining buttons, adjusting the card index each time.

17.  Move to the ShowOutput() method and enable/disable the image


buttons using ImageButton1.Enabled = game.CanSwapCards;

18.  Repeat for the remaining image buttons.

19.  Compile and test.

Card swapping by clicking an image should be working.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-115
Hands-On Exercise 7.1c:
Adding Web Card Images—Image Component
(continued)

Use an Ajax Update Panel to smooth out the display rendering


and stop the flashing that happens on postback.

Ajax, Asynchronous JavaScript and XML extensions, come


packaged as standard with ASP.NET. An UpdatePanel can be used
to smooth the responsiveness of the display. Let’s do this now to get
rid of the “flash” that happens sometimes when the screen updates.

20.  Open Default.aspx in HTML source view. From the AJAX


Extensions tab in the toolbox, drag a ScriptManager control onto
the form and place it immediately inside the opening <form> tag.

21.  Highlight and cut the entire table element—from start tag to end tag.

22.  From the AJAX Extensions tab in the toolbox, drag an UpdatePanel
into the div area.

23.  Place the cursor between the <UpdatePanel> and </UpdatePanel>


tags and enter <ContentTemplate></ContentTemplate>

24.  Place the cursor between the <ContentTemplate> and


</ContentTemplate> tags and press <Ctrl><V> to paste the
game table back in.

25.  Compile and test. The annoying flashing of the display should have
disappeared.

Congratulations! You have completed the bonus material.

This is the end of the exercise.


© All rights reserved. Not to be reproduced without prior written consent.
419-MA-116
Hands-On Exercise 8.1:
Using LINQ/EF

Objective
Implement the logic to display the top 10 players listed by their best game
scores in the fewest number of hands played.

A SQL Server database called Tehi.mdf has been populated


with player scores. LINQ/EF will be used to provide access to this
database by coupling it to a Player entity class.

Close the previous solution if you have not already done so.

Open the solution Tehi located in the directory


C:\Course\419\Exercises\Ex81 (-web or –desktop).

This project contains the solution files from the bonus of the
previous exercise.

Add a new project called Tehi.Data to the solution.

1.  In Solution Explorer, right-click the Tehi solution (not project) and


select Add | New Project. Select Visual C# | Windows | Class
Library and enter the name Tehi.Data. Click OK.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-117
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

Add a connection to the Tehi player database.

2.  From the main menu bar, select View | Server Explorer. This
window should appear on the left side.

3.  In the Server Explorer window, right-click Data Connections and


select Add Connection.

4.  If the Add Connection dialog appears, click the Change button to the
right of the data source text box.

5.  In the Choose Data Sources dialog, click Microsoft SQL Server


Database File and from the drop-down list, select .NET Framework
Data Provider for SQL Server. Click OK.

6.  In the Add Connection dialog that will reappear, click the Browse
button and select the file C:\Course\419\Data\Tehi.mdf. Click
Open.

7.  Click the Test Connection button to make sure everything is


working, then click OK to dismiss the connection dialog.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-118
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

Generate an Entity Data Model for the Tehi database.

8.  Right-click the Tehi.Data project and select Add | New Item.


Select Visual C# | Data | ADO.NET Entity Data Model. For the
name, enter TehiEntities.edmx. Click Add.

9.  In the next dialog, select Generate from database and click Next.
The next page of the wizard should appear.

10.  On this page, ensure that:


• Tehi.mdf is showing in the data connection drop-down
• TehiEntities is entered for the App.config name

Click Next. If you get a message asking to move the local data file,
click No.

11.  In the next dialog, expand the tree menu to expose the Player table
and select it. After ensuring that TehiModel has been entered for the
model namespace, click Finish. If you get a dialog indicating that the
template should be from a trusted source, select the Do not show
again checkbox and click OK. Because we created the template, we
know it is trusted.

The design surface should appear with the single Player


entity class on it. Notice that the name of the model is
TehiEntities.edmx. This is the entity data model.

12.  In the Server Explorer window, expand the Data Connections tree
menu to find the Player table, right-click it, and select Show Table
Data. Briefly review the players in the table and notice the column
names. Close the table view when done by clicking the [x] in its tab.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-119
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

Now that our EDM has been constructed by the Entity


Framework, we can use it as a provider so that LINQ can be used to
query the database.

13.  From the main menu, select Build | Rebuild Solution.

Add a data accessor class to load the player data from the
database.

14.  In the Tehi.Data project, right-click Class1.cs and rename it


DataAccessor.cs. When prompted, select Yes to change all
occurrences. Ensure the class is declared public.

15.  In the newly created DataAccessor class, add as a field a


private TehiEntities object called db. Construct a new object
in its declaration, as in:
private TehiEntities db = new TehiEntities();

16.  Add the framework for a get-only property, something like:

public List<Player> Top10Players


{
get
{
}
}

We will first obtain all the player records unsorted. Later we will
return and modify the query to select the top 10.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-120
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

17.  In its get block, create a query to simply obtain all the players. Use
something like the following, but replace the ??? as appropriate.
IEnumerable<???> result = from p in db.? select p;

18.  Finish with a statement that returns the result converted to a list:
return result.ToList();

19.  Get a clean compile.

This will return all of the players in no particular order. We’ll


improve on this later, but let’s first see what we have.

Deploy the App.config or Web.config file and add


appropriate references to the Tehi application.

We cannot run the program just yet. We will need to add


appropriate references and deploy the configuration files.

20.  Desktop only: In Solution Explorer in the Tehi.Data project, right-


click App.config and select Copy; then right-click the Tehi project
and select Paste. If asked, replace the one that is already there.

The App.config file should also be in Tehi project. We keep


it in both places to ensure that all features work both at run-time and
during development.

21.  Web only: Double-click the App.config file in the Tehi.Data


project. Highlight and copy the whole <connectionStrings> tag
(start to end). In the Web project, open Web.config and paste it
into the <configuration> element.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-121
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

22.  In Solution Explorer for the form or Web project, add references to
the .NET assembly System.Data.Entity and the project
assembly Tehi.Data. Don’t forget to click the checkboxes.

23.  Open Form1.cs/Default.aspx.cs for editing and add at the top


using System.Data.Entity and using Tehi.Data

24.  Get a clean compile.

Add the logic to display the players in the user interface.

25.  In design mode, double-click the Top 10 menu in its event method
loop through all players and display them. Use something like:

LogListBox.Items.Clear();
DataAccessor da = new DataAccessor();
foreach (Player p in da.Top10Players)
{
LogListBox.Items.Add(p.Name + " " +
p.BestHandScore + " " +
p.HandsDealt);
}

26.  Compile and test. Select Top 10 to display the players. Do not click
the Deal button by mistake. That doesn’t test what we want.

All players and their scores should be listed, unsorted.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-122
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

Modify the top-10 query to filter and sort the result.

27.  Open DataAccessor.cs for editing and return to the top-10 query.
Add a where clause to remove any players whose best hand score
is 0; i.e., we want all players whose score is not 0.

28.  Compile and test.

Players with scores of 0 should have been eliminated.

The “best” player is determined by who has the highest best


hand achieved in the fewest number of hands dealt.

29.  Add an orderby clause to the query to first sort by best hand score
in descending order, then by the number of hands dealt.

An orderby clause can have multiple terms separated by a


comma, as in orderby <first term>, <second term>.

30.  Compile and test.

Ensure that the listing is sorted; see Bill and Charles.

31.  Now use the Take(…) query method to limit the number of players
to 10. Insert it into the return statement before the call to
ToList().

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-123
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

32.  Compile and test.

Now just the top 10 players should be shown. Your data should
look something like this (probably with different values):

Congratulations! You have successfully completed the


exercise. Continue to the bonus if you have more time.

Use a partial class to add object-oriented logic to the


generated Player entity class.

Earlier in this exercise, forgoing the player’s information was


displayed by composing the output using
p.Name + " " + p.BestHandScore + " " ...
This is not very object-oriented; providing a ToString() would be
better. We can put it in another partial segment to the Player class.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-124
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

Add a ToString() method to the Player class by using a


second partial segment.

33.  Add a new class in a file called PlayerAdditions.cs to


Tehi.Data. Make its declaration public and partial and
change class name to just Player.

34.  Get a clean compile using Build | Rebuild Solution.

35.  Add the method:

public override string ToString()


{
return Name + " " + BestHandScore + " " + HandsDealt;
}

36.  Return to Form1.cs/Default.aspx.cs and, in the method that


displays the top 10 players, change the display line to:

LogListBox.Items.Add(p.ToString())

37.  Compile and test; the output should be the same.

Congratulations! You have completed the bonus.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-125
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

Super bonus: Add support for tracking players by logging in


and updating their best scores automatically in the database.

This super bonus is quite long and recommended for after


the course. In most cases, there will not be sufficient time to
complete it during regular course hours.

As each game is played, the best hand score and the number
of hands dealt are tracked. If this score is better than the one
previously recorded in the database, the database should be
updated. This is very easy with LINQ/EF!

Add logic in the data accessor to look up and add players in


the database.

38.  Open DataAccessor.cs and add a method to look up a player by


name or use the copy-and-paste code in LookupPlayer.txt.

public Player LookupPlayer(string name)


{
IEnumerable<Player> result = …query…
return result.FirstOrDefault();
}

39.  Next, add a method to add a new player to the database.

public void Add(Player player)


{
db.Players.Add(player);
}

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-126
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

40.  Add a method to save all changes.

public void SaveChanges()


{
db.SaveChanges();
}

41.  Get a clean compile.

Refactor the Tehi game controller and prepare it for adding the
login functionality.

42.  Open TehiGame.cs for editing and find the HandsDealt property.
Rename it HandsDealtInThisGame. This is to be clear that this
value is only for this game, not the all-time one stored in the
database. Hover over the red underscore at the end of
HandsDealtInThisGame and select Rename to change all
occurrences in the program.

43.  Rename BestHandScore to BestHandScoreInThisGame


following the same procedure in the previous step.

44.  Get a clean compile.

45.  Right-click the CardLib project and add references to Tehi.Data


and System.Data.Entity.

46.  In TehiGame, add using directives at the top for both of the
components added in the previous step.

47.  Get a clean compile.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-127
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

In order to update a player’s best score in the database, we


need to know who they are. TehiGame.cs needs to support a login
function. A player can no longer play without first logging in.

Add support for enabling/disabling dealing and logging in.

48.  In TehiGame, after the CanSwapCards property, add three new


auto-implemented properties: bool CanDeal, bool CanLogin, and
string Message. All should have a private set.

49.  Add a constructor. Type ctor<tab><tab> and in the body set the
CanLogin property to true and the message to "Enter your
game name and click login";

50.  Get a clean compile.

51.  Open Default.aspx.cs/Form1.cs for editing and move to the


ShowOutput() method.

52.  Modify the text messages reported in the list box to


"Hands in this game: " and
"Best score in this game: "

53.  Add at the last line in the ShowOutput() method:


StatusLabel.Text = game.Message;

54.  Move to the new game event method and delete the line that writes
to the status label.

55.  Compile and test. The messages will not yet be correct.

56.  Continue editing ShowOutput() and, after the line that clears the
list box, add DealButton.Enabled = game.CanDeal;

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-128
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

57.  Move to the Page_Load(…)/Form_Load(…) method and add at


the last line a call to ShowOutput().

58.  Compile and test. You should no longer be able to deal.

Add support in the Tehi game controller for logging in.

59.  Open TehiGame.cs and the following fields:

private DataAccessor tda = new DataAccessor();


private Player player;

60.  Move to after the SwapCard() method. Add the Login(…) method
using the copy-and-paste file LoginMethod.txt. It should be:

public void Login(string name)


{
if (name.Length < 3)
{
Message = "Game name must be 3 or more characters";
return;
}
CanDeal = true;
CanLogin = false;
player = tda.LookupPlayer(name);
if (player != null)
{
Message = "Player found. Overall best score is " +
player.BestHandScore + " in " + player.HandsDealt;
return;
}
player = new Player();
player.Name = name;
tda.Add(player);
tda.SaveChanges();
Message = "New player " + name + " added to database.";
}

61.  Get a clean compile.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-129
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

Add support for the login control in the view.

62.  Open Default.aspx/Form1.cs in design mode.

63.  Double-click the Login button to go to its event method. Delete all
existing code and add:

game.Login(NameTextBox.Text);
ShowOutput();

64.  Move to the ShowOutput() method and after the DealButton is


enabled/disabled, add:

LoginButton.Visible = game.CanLogin;

65.  Remove any superfluous calls to StatusLabel.Text = … in the


various event methods. Leave only the one in ShowOutput().

66.  Compile and test. You should be able to log in and play the game
again. Start a new game to log in again if necessary.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-130
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

Track and update players’ all-time highest score in the


database if they get a better score in the current game.

The best all-time would be:


• Any BestScoreInThisGame higher than the BestScore
recorded in the database
• Any BestScoreInThisGame equal to the BestScore in the
database if the number of hands played is less
Let’s add support for this now!

67.  Open TehiGame.cs for editing and before the ToString method,
add a new function called ScoreUpdate(…) or use the copy-and-
paste file ScoreUpdateMethod.txt. It should be:

private void ScoreUpdate()


{
if (Score > BestHandScoreInThisGame)
BestHandScoreInThisGame = Score;

if ((Score > player.BestHandScore) ||


((Score == player.BestHandScore) &&
(HandsDealtInThisGame < player.HandsDealt)))
{
player.BestHandScore = Score;
player.HandsDealt = HandsDealtInThisGame;
tda.SaveChanges();
Message = "New all-time best score " + Score +
" in " + player.HandsDealt + " hands";
}
else Message = "...";
}

68.  Get a clean compile.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-131
Hands-On Exercise 8.1:
Using LINQ/EF
(continued)

69.  Move to the Deal() method and replace the line of code that
checks if the score has improved with a call to ScoreUpdate().

70.  Repeat for the SwapCard(…) method.

71.  Compile and test. Login with a new game name (make one up). After
one or more hands, a message that a new all-time score has been
achieved will appear.

72.  Play for a bit—see if you can get on the high-scores list.

Congratulations! You have successfully completed the


super bonus!

This is the end of the exercise.

© All rights reserved. Not to be reproduced without prior written consent.


419-MA-132

You might also like