It will have the following features: • A button to click that punches you into work at the beginning of your shift • A button to click that punches you out at the end of the day • A plac
Trang 1• Create a deployment package so you can install it somewhere when you are done
• Manage all your projects
• Interface with both local and online help in a context-sensitive manner
• Suggest code for you to insert into your program
I can think of more things, but I will leave it at that For everything this C# IDE can do, the other IDEs can do the same In fact, as you know from the installation, the VWD IDE can also act as a small web server
The Look and Feel
Start up Visual C# and you should get a screen similar to that shown in Figure 4-1
Figure 4-1. The C# IDE start screen
Trang 2You will see a standard menu on top with a toolbar below Below this, you will see three
pinnable panes The first is the toolbox, which is on the left-hand side and is currently
mini-mized Run you mouse over it—you will see what looks like a pushpin in the top-right corner of
the pane This is shown in Figure 4-2
Figure 4-2. The toolbox pushpin, showing Auto Hide
Click this pushpin—it will rotate vertically and the toolbox will stay maximized Note that
the Solution Explorer acts this way as well
This pinnable menu and pane system is a really big help in developing code Many times you
won’t need the toolbar or, in some cases, even the Solution Explorer This feature allows you to
maximize the screen space you have for visual screen development or coding
One last thing to note about the menu system is that it is completely configurable If you
do not like the way it looks, you can move panes around, add new ones, or delete some choices
from other toolbars It is up to you I would suggest, however, that you use the system as it is for
now just to get used to it
Creating a New Project
The project you will create in this chapter is a simple time sheet This time sheet will allow you
to press a button to punch in and out of work It will have the following features:
• A button to click that punches you into work at the beginning of your shift
• A button to click that punches you out at the end of the day
• A place that shows how many hours you’ve worked that day after you punch out
• A grid that shows how many hours you’ve worked in the current week
The intention of this project is to handle the design work and the business logic so you can
bring it over to the Web In Chapter 7, you will be creating a DNN module that will do this work
All the business logic you create in C# here will be used there
Trang 3Starting the Project
The name of this project will be “Punch.” Clever, eh?
Open the C# IDE and click the menu option File ➤ New Project Choose a Windows cation project and name it Punch This is shown in Figure 4-3
Appli-Figure 4-3. Creating a new project
Click OK and you will have a project with a single Windows form and a class that runs the code for this form Unfortunately, the name of the form is “form1” and the name of the code class is “program.” This is way too generic, and you should change it
Inside the Solutions pane, right-click the form1.cs file and select the Properties window It will show as in Figure 4-4
Change the file name from form1.cs to punch.cs Press Enter and you will get the prompt shown in Figure 4-5
Trang 4Figure 4-4. The Properties window
Figure 4-5. Prompt to propagate changes
Click Yes here to continue In previous versions of the C# IDE, the name change did not
propagate throughout the project I used to have to open every file and change every reference
myself This new functionality is a big help
Trang 5You now have a single form and a code file with which to write the program The next thing
to do is populate the form with controls so that the user can interact with your program.Click the form, and then click the Toolbox tab The tab will expand This is where you will click the pushpin to force the toolbox to stay open while you are using it You can see this in Figure 4-6
Figure 4-6. Opening the toolbox and making it stay open
Notice all the controls that Microsoft gives you for free here You have common things such as different types of buttons, labels, text fields, and so on It is possible (and probable) that when you create more Windows applications, you will need some more specialized controls not shown here There is a wealth of controls available for purchase online If you feel really comfortable with programming, you can even create new specialized controls out of the ones shown here If you feel so inclined, I wrote a book on how to write special data input controls,
called Data Entry and Validation with C# and VB NET Windows Forms This book is available
from Apress as well
Project Setup
Before diving into the project, I want to take a break here to explain the setup of a C# solution The setup of a web solution will be similar While I am on the topic, I will also show you some aspects of C# and programming itself This will not be anything too difficult, but it will be about the most complex thing you will see in programming the projects in this book
Trang 6The Solution Explorer
The Solution Explorer is the pane shown in the upper right of the screen It is essentially a list
of all the files in your project This project’s solution is shown in Figure 4-7
Figure 4-7. The Solution Explorer window
My list here is expanded to show some other files Let’s look at what some of these files are
AssemblyInfo.cs: This file includes information about your project that can be accessed by
other programs This information includes things such as version number and name
Resources.resx: This file is an XML file that includes localized text you can use in your
pro-gram You are not localizing this program, so your text is hard-coded in the class
Settings.settings: This file has information about user preferences You can store the last
known state of a program in here, and the next time a particular person logs in, the
pro-gram will return to the state that person left it
References: The files included under this folder contain the core functionality of NET If
you write a DLL with some neat methods, you can include it here so you can reference the
methods in your program
Program.cs: This is the most upper-level class that instantiates your Punch class Basically
it starts the program running
punch.cs: This is the visual form you see on the screen
Trang 7punch.Designer.cs: This is the code that Visual C# generates when you place and late controls on your form.
manipu-punch.resx: This file contains localized text that relates to your Punch class It will appear once you add components to your form
The blank form that you see in Figure 4-6 is the punch.cs file The code that runs this form
is called punch.Designer.cs This file contains all the code that places controls on the form It also contains all the code that handles the properties of the form Double-click the
punch.Designer.cs file name in the Solution Explorer and you will see the code shown
/// <param name="disposing">true if managed resources should be
/// disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
private System.Windows.Forms.Button cmdPunch;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox txtHoursToday;
private System.Windows.Forms.TableLayoutPanel tlp1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox txtMon;
Trang 8private System.Windows.Forms.ComboBox cmbWeek;
private System.Windows.Forms.TextBox txtSat;
private System.Windows.Forms.TextBox txtFri;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.TextBox txtSun;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.TextBox txtThu;
private System.Windows.Forms.TextBox txtWed;
private System.Windows.Forms.TextBox txtTue;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label8;
}
}
There are some things to note here First is the fact that there is a namespace called Punch
A namespace is a way to keep names of controls and methods from conflicting with some other
controls or methods that may be named the same A namespace is like the town part of an
address You may live on 5 Main Street, and I may live on 5 Main Street as well The way we
keep these addresses unique is to define the towns we live in A namespace allows you to avoid
naming conflicts and provide what is called a fully quallified name
The next thing to note is that you have a class called Punch It is actually a partial class, but I
will get to that later Writing code in NET—or any modern language nowadays—means writing
object-oriented code A class is a way of encapsulating a set of funtionality Functionality could
be the visual aspects and code that runs in the background Everything that has anything to do
with this form is encapsulated in this class
Next you will notice a region called Windows Form Designer generated code You may click
the plus sign next to it to expand and edit this section if you want I do not recommend this, and
neither does Microsoft Suffice it to say that this section is reserved for the IDE, and this is
where it puts code that places the controls on the form
■ Caution You may look at the code in the Windows Forms Designer region, but do not change it The
IDE relies on the code here to be exaclty what it put in here If you change it, you may change the behavior of
your form
Finally, you see a bunch of controls and their names These are definitions of all the
con-trols you will be placing on this form You will not have this code yet
The next file I want you to look at is the file called punch.cs There are a few ways to see
the code in this file The first and most common way is to double-click the form This adds what
is called an event handler for the form to the code, and the IDE shows the code The other way
is to click the View Code button on the Solution Explorer This is shown in Figure 4-8
Trang 9Figure 4-8. The View Code button
The code that you will see is shown in Listing 4-2
Listing 4-2. Initial code for the Punch class
Punch class is broken up between two files Hence the word partial You can define part of a
class in one file and another part in another file The reason for doing this is to keep the IDE forms designer–generated code away from the code that you will be writing It is a way of hiding what you really don’t need to see, and prevents some confusion
Trang 10I got this code to show up by double-clicking the form You will see from this piece of code
that there is a method called Punch_Load This is the event handler method that is given to you
by the IDE Since this code is in this file, you are free to edit it as you see fit
You do not have to add anything to the Page_Load event handler If you double-click the
form to get to the code page, the Page_Load event handler is what you get
So this is the basic layout of a C# Windows program As I said before, the layout of a web
solution, as far as the files go, is pretty much the same Now on to the visual layout
Designing the Form
Designing the form involves knowing what the user will need to see, and laying out the controls
correctly The controls you will need for this form are as follows:
• A button to punch in and out
• A table to see a week’s time
• Several labels to view in and out punches
• A drop-down control to choose which week to view
• A label to see daily time
The list that follows instructs you on placing the control on the form When you are done
with the form, it should look like the one shown in Figure 4-9
1. From the toolbox, click the ComboBox control and place it on the form using your right
mouse button In the Properties window, name it cmbWeek
2. Choose a button from the toolbox and place it on the form as shown in Figure 4-9
Name this button cmdPunch Fill in the Text property as Punch In Make the Font
prop-erty for this button 14-point bold You’ll use just one button here to do double duty; it
punches the user in and out
3. Choose a label from the toolbox and place it on the form as shown in Figure 4-9 No
need to name this label Fill in the Text property as Hours Worked Today
4. Below this label, add a text box called txtHoursToday Change the BorderStyle property
to FixedSingle Change the ReadOnly property to True
5. Add seven labels to the form, representing the days Sunday through Saturday There is
no need to name these labels Change the Text property of each label to represent each
day of the week, as shown in Figure 4-9
6. Add seven text boxes to the form below the day-of-week labels, as shown in Figure 4-9
Name the text boxes txtSun, txtMon, txtTue, txtWed, txtThu, txtFri, and txtSat,
respec-tively Change the BorderStyle of each to FixedSingle Change the ReadOnly property of
each to True
Trang 11Figure 4-9. Final layout of controls on the form
Your final layout should look like that shown in Figure 4-9 You should now have a able form with absolutely nothing behind it It is time to add some code to this form
work-Adding the Code
There are two events you need to handle in this form The first is when a user clicks the down box The second is when the user clicks the Punch button There are two ways to add the event handlers to this code The first way is the way I prefer, which involves some hand-coding and a good deal of knowledge about the way the IDE generates code So, let’s get started Just kidding
drop-The easy way to add event handlers to the code is to click the control So click the drop-down box, and you will see a method appear in the punch.cs file This is the code you will see generated:
private void cmbWeek_SelectedIndexChanged(object sender, EventArgs e)
Trang 12Whenever someone clicks the button, the code in this method will run You can generate
event handling methods this way for any control However, just as an aside, there are many
more events that you can handle for these and all other controls These other events must be
wired up manually You will not be handling any other events in this project
You are now over the easy part
When it comes to software engineering, nothing is ever a single-syllable word I think that
these three words are meant to confuse the uninitiated, and should be used as ammunition to
ask for a raise Use these three words in a single sentence, and when your boss gives you a
quiz-zical look, ask for a raise
When I first learned object-oriented programming (OOP) with C++, I spent a lot of time
trying to use these words with my colleagues It soon became apparent that developers never
really talked this way Here is what they actually mean:
Polymorphism: This feature allows you to have the same function for different objects
While the function Circle.Draw() may render a circle, the function Square.Draw() does a
completely different thing, even though they both draw a shape
Inheritance: This feature allows you to have a generic class—for example, one called House.
This class could have some basic properties, such as bedrooms, doors, a kitchen, and so on
You could then derive a class—for example, RanchHouse—from House, and it would “inherit”
House’s properties You could then add properties that are specific to a RanchHouse—for
example, that it has only one floor
Encapsulation: This feature allows you to store data and functionality inside an object
while limiting access to them from outside This is the OOP feature you will be using most
often in this project and other projects in this book It’s often called “data hiding,” but one
can also “hide” functionality
The following is a small side project to show you how you will use classes I will use the
IntelliSense feature of the IDE to show how classes work You can join in the fun or not
Start a project for a Windows Console Application This is the simplest application, with
virtually no IDE-generated code to get in the way Name the project “Encapsulation.” The
Program.cs file should look like Listing 4-3
Trang 13Listing 4-3. Start of the Encapsulation project
private int mPrivate_integer;
private string mPrivate_string;
public int mPublic_integer;
public string mPublic_string;
Trang 14//This is a constructor It is used to initialize the object
// that is created from this class
//Property to get and set the private integer
public int Private_integer
{
get { return mPrivate_integer; }
set { mPrivate_integer = value; }
}
//Property to get and set the private string
public string Private_string
{
get { return mPrivate_string; }
set { mPrivate_string = value; }
}
}
// This is the method that gets run when the program is started
static void Main(string[] args)
{
}
}
}
The variables that are not allowed to be accessed by any code outside this class are
declared Private The variables that can be accessed outside this class are declared Public
Notice that the variables have an m in front of them I use this convention to let myself know
that these variables are internal members of a class and not directly accessible
Trang 15The properties called Private_Integer and Private_String are the ways to get and set the vate variables from outside the DataHiding class These properties allow you to control what values are allowed, and whether or not a variable can be just read, or both read and written.The best way to see how this all works is to create an object and use the IntelliSense feature
pri-of the IDE to tell you the level pri-of accessibility pri-of this class This will be done inside the Mainmethod Listing 4-5 shows the Main method with the appropriate code
Listing 4-5. Accessing the new class
// This is the method that gets run when the program is started
static void Main(string[] args)
{
//Create the new object fom the class
DataHiding dh = new DataHiding();
//get the public values
Figure 4-10. IntelliSense showing what is available
Trang 16IntelliSense shows here that you can access the public variables directly, because it shows
mPublic_integer and mPublic_string, but not mPrivate_integer and mPrivate_String
IntelliSense also shows that you can access the private variables though the properties
Private_integer and Private_string This is encapsulation for you!
■ Tip IntelliSense is fantastic in NET It tells you everything you need to know about a method or an object
If you expect a variable to show and IntelliSense does not show it, you know you are doing something wrong
Polymorphism
Let’s use IntelliSense once more to show polymorphism at work I had you use the
Console.WriteLine method to output some variables to the screen The WriteLine method of
the Console object is one of the most “overloaded” methods in NET When you were typing it
in and you typed the opening parenthesis after Console.Write, IntelliSense showed 18 ways to
use it This is shown in Figure 4-11
Figure 4-11. Method overloading shown via IntelliSense
See how IntelliSense shows 18 different ways to use this method? This is because you can
write out any of the types that NET allows, with and without formatting Outside the Console
class, it looks like there is only one Write method
Now that I have explained some of what you will see as far as object-oriented
program-ming goes, let’s get to the code of this main project
Back to the Project
Writing code in C# or VB entails some basic knowledge of object-oriented programming I
already told you about classes, namespaces, variables, methods, and properties There are a
few other concepts you need to be aware of before you go on, such as how to use them
This project is about keeping time on a per-person basis for two weeks The two weeks
in question are last week and this week The module you will write for the DNN project will
encompass as many weeks and as many people as you want
Trang 17If you think about the data, you’ll find that you need to keep the times that a person punched in and out on a daily basis To further organize the data, it would be nice to keep this data in a weekly format So the data you need is as follows:
This data will enable you to figure the hours worked for any day There is no need to keep the actual hours worked because there are rules (not included here) that adjust the hours worked based on rounding rules It is not necessarily true that the total hours worked in a day are continuous from start to end
The best way to keep and manage this data is with classes You have seen the class that encompasses the form and its controls You will need to define your own class that encom-passes a person and the time associated with punching in and out Once you define the proper class, you can scale the program to include as many weeks of data for as many people as you need, with no extra code I will show you how to do this
The Private Class
You need a class to hold all the information necessary to run this form The information you need is the in and out times of each day of the week Therefore, you will create a WeekPunchesclass Go into your punch.cs class file and add a new class Listing 4-6 shows the complete code for this class Put this class within the Punch class, near the top
Listing 4-6. The new WeekPunch class
private class WeekPunches
{
#region Class local variables
private DateTime mMondayStart;
private DateTime mMondayEnd;
private DateTime mTuesdayStart;
private DateTime mTuesdayEnd;
private DateTime mWednesdayStart;
private DateTime mWednesdayEnd;
private DateTime mThursdayStart;
private DateTime mThursdayEnd;
Trang 18private DateTime mFridayStart;
private DateTime mFridayEnd;
private DateTime mSaturdayStart;
private DateTime mSaturdayEnd;
private DateTime mSundayStart;
private DateTime mSundayEnd;
#endregion
#region Accessor Get / Set Methods
public DateTime MondayStart
{
get { return mMondayStart; }
set { mMondayStart = value; }
}
public DateTime MondayEnd
{
get { return mMondayEnd; }
set { mMondayEnd = value; }
get { return mTuesdayStart; }
set { mTuesdayStart = value; }
}
public DateTime TuesdayEnd
{
get { return mTuesdayEnd; }
set { mTuesdayEnd = value; }
get { return mWednesdayStart; }
set { mWednesdayStart = value; }
}
Trang 19public DateTime WednesdayEnd
{
get { return mWednesdayEnd; }
set { mWednesdayEnd = value; }
get { return mThursdayStart; }
set { mThursdayStart = value; }
}
public DateTime ThursdayEnd
{
get { return mThursdayEnd; }
set { mThursdayEnd = value; }
get { return mFridayStart; }
set { mFridayStart = value; }
}
public DateTime FridayEnd
{
get { return mFridayEnd; }
set { mFridayEnd = value; }
get { return mSaturdayStart; }
set { mSaturdayStart = value; }
}