.NET for Visual FoxPro Developers Chapter
9 Microsoft has placed a tremendous emphasis on .NET being a
platform to create, consume, and deploy XML Web Services. Unfortunately, it
caused many developers among the uninitiated to believe that .NET is only for building applications that
access the Internet. I’ve heard the question over and over again: “Why should I
use .NET if I’m not creating Web applications”? This chapter aims to dispel
this notion. You can use .NET to create standard, Windows desktop
applications (known in .NET as Windows Form or WinForm applications). Truth be
told, you can quite happily create C# and Visual Basic .NET applications that
never think twice about the Internet. However, should you decide to provide Web
access to your desktop applications, all the tools are ready and waiting for
you. This chapter shows you how to take advantage of Visual Studio
.NET to create Windows Forms Applications. You’ll be amazed at how easy it is
to do things you could never do in Visual FoxPro (or things you had to kludge).
Most importantly, you’ll see how to use business objects in a Windows Forms
application. Creating a Windows Forms application In this chapter you will learn about Windows Forms
applications by building a simple Windows Forms application and taking a look
behind the scenes each step of the way. Chapter 2, “Visual Studio .NET” showed
the very basics of creating a Windows application. This chapter takes you
beyond the basics and explores the process in greater detail. A Windows Forms application typically contains a main
application form, a main menu, toolbars, a variety of forms, code files
containing business object classes, and references to external .NET assemblies.
In this walk-through you’ll see how each element is used in a .NET Windows
Forms application. To create a new Windows Forms application: 1. From
the Visual Studio .NET Start Page,
click the New Project
button. 2. In
the New Project dialog
look in the Project Types pane
on the left and select Visual C#
to create a C# Windows application or Visual
Basic .NET to create a VB .NET Windows application. Then in the Templates pane on the
right, select Windows
Application. 3. In
the Name text box,
enter the name you want to give your new Windows application. In this example
I’ll enter “Simple Windows Application”. 4. Make
sure the Location box
contains the directory you want to create your new application in and click OK. At this point, VS .NET creates a new application for you,
using the Windows Application template you selected. After a few moments, a new
form named Form1 is displayed in design mode in the Visual Studio .NET IDE (Figure
1). Figure 1. Visual Studio .NET creates a Windows
application from the template you select in the New Project dialog. You may be wondering what this form is for—is it supposed to
be a login form or maybe just one of the forms in the application? By default,
this form is meant to be your main application desktop, more or less equivalent
to the main Visual FoxPro window. Take a Because namespaces are handled a bit differently in C#
versus Visual Basic .NET, I’ll talk about namespaces for each language
separately. If you’re using C#, notice the namespace declaration at the top of
the code file: namespace Simple_Windows_Application This is the namespace automatically created by Visual Studio
.NET when you created the new project—it’s basically the project name with
spaces replaced by underscores. Before going any further, change the namespace
to something more meaningful. Microsoft recommends that you use the
“Company.Product” naming convention for your namespaces. For example, the
following namespace specifies the company HW (Hentzenwerke), the product
NetBook (.NET for VFP Developers Book), and I’ve added an extra “.Samples”
section to indicate these are the samples for the book: namespace HW.NetBook.Samples Now you need to change the project’s default namespace to
the same namespace. The default namespace specifies the namespace that is used
for all new code files added to the project. To change the default namespace,
right-click on your project in the Solution Explorer and select Properties from the
shortcut menu. In the Property
Pages dialog, expand the Common
folder in the left pane and select General.
Change the Default Namespace
(Figure 2) to the new namespace, “HW.NetBook.Samples”. Figure 2. You change your project’s default, or
root namespace, in the project’s Property Pages dialog. Namespaces in Visual Basic .NET If you’re using Visual Basic .NET, there is no
namespace declaration in the Form1.vb code file—that’s because VB .NET handles
namespaces differently than C#. In VB .NET there is the concept of a root
namespace for each project, which is different than C#’s default
namespace. This root namespace acts as a prefix for any namespace you
declare within a code file. For example, if the project’s root namespace is
“HW.NetBook.Samples”, and you specify an additional “Business” namespace, the
full namespace is “HW.NetBook.Samples.Business”. To set the VB .NET project’s root namespace, right-click on
the project and select Properties
from the shortcut menu to launch the Property
Pages dialog (Figure 3). In the Root
namespace text box, enter “HW.NetBook.Samples”, and click OK to save changes. Figure 3. You change a Visual Basic .NET
project’s root namespace in the Property Pages dialog. If you created a C# Windows Forms application, scroll
down to the bottom of the code file and you will see the following method
declaration: static void { Application.Run(new
Form1()); } As mentioned in chapter 3, “Introduction to C#”, all C#
programs must have a static method named If you’re using C#, the compiler automatically finds the
class with the Main method at compile time. If you’re using Visual Basic .NET,
you must specify in your project’s Property
Pages dialog which object in your application is the startup
object. The ability to change your startup object is useful when you are creating
a more robust application with an application object that you want to
instantiate first. After doing some application startup processing, you can
instantiate your main application form. For now, I’ll leave this method in the
Form1 class. Within the Main method, there is the following code: Application.Run(new Form1()); The Application object belongs to the System.Windows.Forms
namespace. Its static Run method runs an application message loop that
processes messages from the operating system to your application. In this line
of code, a new instance of the Form1 class is passed as a parameter to the Run
method. This causes the message processing to begin and the main application
form to be made visible. If you leave out this line of code the application
will start up and immediately exit—similar to Visual FoxPro’s READ EVENTS. Behind the scenes with Visual Basic .NET If you created a Visual Basic .NET Windows application,
you will not see a Main method declaration in the form’s code as you do in C#.
What’s going on here? In a VB .NET Windows application, Form1 is specified as the
startup object by default; however, a form-level Main method is not exposed in
the source code. Behind the scenes, the Visual Basic .NET compiler inserts a
Main method into the IL code to satisfy .NET’s requirement that all programs
must have a Main method. This model was chosen to help simplify VB .NET Windows
Forms applications. If you don’t want a form to be the first object instantiated
in your VB .NET application, you can create a new class and add a Main method
to it. For example: Public Class MainClass Shared Sub Application.Run(New
Form1()) End Sub End Class Next, you need to change the startup object from Form1 to
your Main method. Right-click on your project and select Properties from the
shortcut menu to launch the Property
Pages dialog (Figure 3). In the left pane, expand the Common Properties folder
and select General. In the Startup object combo box,
change the selection from “Form1” to “Sub Main”. Modifying the main application form To learn more about .NET forms, click Form1 in design
mode and bring up the Properties Window. Follow these steps to change some key
properties of the form: 1. Change
the form’s Text property from
“Form1” to “My Simple WinForm Application”. When you press Enter or move off
the Text property, the
caption of the form changes to the new text. 2.
Scroll to the top of the Properties Window and find the
(Name) property to
specify the name of the form class. Change the (Name)
property to MainAppForm. 3.
Go to the Size
property in the Properties
Window and change the size to 640, 480. Note that if you expand
the Size property by
clicking on the plus sign (+) you can change just the Height or just the Width of the form. 4.
Select the IsMdiContainer
property and set its value to “True”. “MDI” stands for Multiple Document
Interface. An MDI form can contain child forms. If you don’t set this property
to “True”, any child forms you launch will exist outside of the main
application form. Note when you change this property to “True”, the back color
of the form changes to the “Application Background” color in your Windows color
scheme (on my computer, it’s dark grey). 5.
Now change the WindowState property. The default value
is “ Before compiling and running the application, you need to
make one more change to the Form1 code file. When you changed the name of the
form class from “Form1” to “MainAppForm”, it changed the name of the class in
the code file. However it did not change the name of the form class
being passed to Application.Run(). Go back to the Main method and change the
call to the Application class’s Run method as follows. In C#: Application.Run(new MainAppForm()); In Visual Basic .NET, rather than adding this line of code,
right-click on the project and select Properties
from the shortcut menu. In the Property Pages dialog’s Startup object combo box,
select “MainAppForm”, and then click OK
to close the dialog. Next, for the sake of consistency, go to the Solution
Explorer, right-click on the Form1 source code file, select Rename from the shortcut
menu, and change the name from “Form1.cs” to “MainAppForm.cs” (in C#) or from
“Form1.vb” to “MainAppForm.vb” (in Visual Basic .NET). Now you’re ready to compile the application. To do so, select
Build | Build Solution
from the main menu. To run the application, select Debug
| Start from the menu or press the F5 shortcut key. Your main
application form should fill the entire screen. To close the application, click
the close button on the upper right side of the form. Creating a main application menu At this point, you need to create a main application
menu where you launch other application forms you build later on. In Visual
Studio .NET, you add a menu to any form in your application. To add a menu to
your main application form, select the form in design mode, and then drag and
drop a MainMenu class from the VS .NET Toolbox
onto the form. If the Toolbox is not visible, select View
| Toolbox from the main menu. When you drop the menu on the form, rather than showing up on
the form’s design surface, it is displayed in the component tray beneath the
form (Figure 4). Figure 4. When you add a menu to a form, it is
displayed in the component tray beneath the form rather than on the form’s
design surface. If you’ve ever struggled with Visual FoxPro’s menu designer,
you’re going to like the menu designer in VS .NET. To kick the tires a bit, add
a few menu pads and menu bars using the menu designer. To create a File menu pad, click in
the rectangle labeled Type Here
at the top of the form, and enter the text “&File” as shown in Figure 5.
The “&” indicates the “F” is the menu item’s access key. At run time,
pressing ALT+F selects this menu pad. When you add a new menu item Visual
Studio .NET automatically gives it a generic name such as “menuItem1”. It’s
best if you change this name to something more meaningful, such as “FilePad”.
To do this, select the menu item, bring up the Properties Window, and set the
value of the (Name) property to
“FilePad”. Figure 5. You indicate the access key of a menu
item by placing an ampersand in front of it. Next, add an Exit
menu bar to the File
menu pad. To do this, click in the rectangle labeled Type
Here below the File
pad and enter the text “E&xit”. Next, change the name of the new menu bar
to “FileExitBar” in the Properties Window. Add a second menu pad called Customers by clicking in
the Type Here box to
the right of the File
menu pad, entering the text “&Customers”, and changing the name of the menu
pad to “CustomersPad”. Add a menu bar to this pad by clicking in the Type Here box beneath the
pad, entering the text “&Orders”, and changing the name of the menu bar to
“CustomerOrdersBar”. This bar will be used to launch a Customer Orders form
that you will create later in this chapter. Most applications have a Window menu pad containing
a list of all forms open on the desktop. In Visual FoxPro, you had to write
code adding a menu bar to the Window menu pad whenever a new form was
instantiated. In Visual Studio .NET, all you have to do is add a menu bar with
the text “Window” and set a single property in the Property Window. To create
the Windows menu pad, click in the Type
Here box to the right of the Customers menu pad and enter the
text “&Window”. In the Properties Window, change the name of the menu pad
to “WindowsPad”. Next, change the value of the MdiList
property from False to True. If this property is set to True, when an MDI child
form is instantiated at run time, a corresponding menu bar is automatically
added to this menu pad. At this point, your menu system looks good, but doesn’t do
much (other than the Windows menu pad). Now add some code to the Exit menu bar that closes
the application when the user selects it at run time. To do this, double-click
on the Exit menu bar and
the following code is automatically added to your form. In C#: private void FileExitBar_Click(object sender,
System.EventArgs e) { } And in Visual Basic .NET: Private Sub FileExitBar_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles FileExitBar.Click End Sub This code is a form-level method acting as an event handler
for the FileExitBar’s Click() event. Any code you place in this method is
automatically executed at run time when a user selects File | Exit from the
menu. When you double-click on any user interface control, VS .NET
automatically adds event handler code for the control’s default event. The
default event for a menu bar is Click(). What mechanism automatically calls this event handler when
the Click event of the menu bar is executed? When you double-clicked the
FileExitBar in the menu designer, it actually adds another line of code to your
form that is hidden in the code editor. To see this code, scroll up in the code
editor until you see a rectangle containing the text “Windows Form Designer
generated code” (Figure 6), and expand this node. Figure 6. The Visual Studio .NET Form and Menu
Designers automatically add “behind-the-scenes” code to your form As you can see, the Form and Menu Designer have been adding
plenty of “behind-the-scenes” code to your form as you’ve been creating new
menu items and setting form properties. The C# editor hides less of this code
than the Visual Basic .NET editor which hides just about everything. Take a
look at some of this form-level code to see what’s going on. First, look at the form’s constructor code. This code is not
hidden in C#, but is hidden in Visual Basic .NET. Here’s the C# form constructor code: public MainAppForm() { // // Required for Windows
Form Designer support // InitializeComponent(); // // TODO: Add any
constructor code after InitializeComponent call // } Here’s the Visual Basic .NET form constructor code: Public Sub New() MyBase.New() 'This call is required by
the Windows Form Designer. InitializeComponent() 'Add any initialization
after the InitializeComponent() call End Sub In each constructor method, a call is made to a form-level
method named InitializeComponent. By default, this method is hidden in both C#
and Visual Basic .NET. Here are the first few lines of code in C#: private void InitializeComponent() { this.mainMenu1 = new
System.Windows.Forms.MainMenu(); this.FilePad = new
System.Windows.Forms.MenuItem(); this.FileExitBar = new
System.Windows.Forms.MenuItem(); private
System.Windows.Forms.MenuItem CustomersPad; private
System.Windows.Forms.MenuItem CustomerOrdersBar; this.WindowPad =
new System.Windows.Forms.MenuItem(); And here they are in Visual Basic .NET: <System.Diagnostics.DebuggerStepThrough()> Private
Sub InitializeComponent() Me.MainMenu1 = New System.Windows.Forms.MainMenu() Me.FilePad = New System.Windows.Forms.MenuItem() Me.FileExitBar = New System.Windows.Forms.MenuItem() Me.CustomersPad = New System.Windows.Forms.MenuItem() Me.CustomerOrdersBar = New System.Windows.Forms.MenuItem() Me.WindowsPad = New System.Windows.Forms.MenuItem() As you see by looking at this code, Visual Studio .NET added
a form-level, private variable for the main menu and each menu item. When the
form is instantiated and the constructor method calls this InitializeComponent
method, an instance of each menu class is created and stored in these
form-level variables. As you look down through the rest of the code in the
InitializeComponent method, you see code added by the Menu Designer and Form
Designer that changes the values of menu and form properties. For example, at
the bottom of each method, you find the following code setting various form
properties. In C#: this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(640, 480); this.IsMdiContainer = true; this.Name = "MainAppForm"; this.Text = "My Simple WinForm Application"; this.WindowState =
System.Windows.Forms.FormWindowState.Maximized; In Visual Basic .NET: Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me.ClientSize = New System.Drawing.Size(640, 480) Me.IsMdiContainer =
True Me.Menu = Me.MainMenu1 Me.Name = "MainAppForm" Me.Text = "My Simple WinForm Application" Me.WindowState = System.Windows.Forms.FormWindowState.Maximized This approach is very different from the Visual FoxPro form
and menu designers. In Visual Studio .NET, ultimately, every object you add to
a form or a menu is implemented as code in the form’s associated code file. In
design view, Visual Studio .NET interprets the code into a representation you
work with visually on a form. Getting back to the real reason you began looking at the
form’s code, if you look at the C# code, you find the following line: this.FileExitBar.Click += new System.EventHandler(this.FileExitBar_Click); This code links the Exit
menu bar’s Click event with the form-level FileExitBar_Click event handler
method shown earlier. The FileExitBar_Click method is registered as an event
handler (using the += operator) with the FileExitBar’s Click event,
establishing a link between the two. Now, look at the corresponding Visual Basic .NET code. You
may be surprised to find this code is not located in the InitializeComponent
method. This is because VB .NET establishes event handlers differently by using
the “Handles” keyword. The code you’re looking for is actually found right in
the FileExitBar_Click method declaration: Private Sub FileExitBar_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles FileExitBar.Click End Sub The Handles keyword indicates the FileExitBar_Click method
handles the FileExitBar.Click event. Now that you have a basic understanding of how this works,
it’s time to add code to the event handler that closes the application when the
user selects File | Exit from
the menu. Here’s the code in C#: private void FileExitBar_Click(object sender,
System.EventArgs e) { this.Close(); } And here’s the code in Visual Basic .NET: Private Sub FileExitBar_Click(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles FileExitBar.Click Me.Close() End Sub For more information on events, event handlers, and delegates,
see Chapter 5, “Object-Orientation in C# and Visual Basic .NET”. Now it’s time to test out your new menu. From the Build menu, select Build Solution. Next,
press F5 to start the
application. If everything’s working properly, your main application form
should maximize to fill your computer monitor, and you should have a main menu
containing File, Customers, and Window menu pads. When you
select File | Exit from
the menu, your application should exit. You can also exit the application by
clicking the close button [X] at the top right corner of the application
window. When you add another form to the project later in this
chapter, you will revisit the menu system to verify the Window menu pad is working
properly. For more information on creating menus, see the .NET Help topic
“Adding Menu Enhancements to Windows Forms”. Adding a new form to the project To demonstrate the capabilities of Windows Forms and
Visual Studio .NET, you’ll create a “Customer Orders” form that allows you to
view, edit, and create customer orders. First, you need to add a new form to the project. Right-click
on the project and select Add |
Add Windows Form from the shortcut menu. In the Add New Item dialog,
change the form name to “CustomerOrdersForm.cs” (in C#) or
“CustomerOrdersForm.vb” (in Visual Basic .NET), and click the Open button. This opens
the new form in design mode. Go to the Properties Window and change the Size to 580, 420 (this
makes the form a good size for the controls you will add later on), change the Text property to
“Customer Orders”, and change the StartPosition
property to “CenterScreen” (for information on the other settings of the StartPosition property,
see the .NET Help topic “FormStartPosition Enumeration”). “CenterScreen”
automatically centers the form in the middle of the screen. The .NET TabControl is equivalent to Visual FoxPro’s
page frame control. I recommend adding a TabControl to the form to give
yourself an idea of how to use it in your applications. The easiest way to add
the control is to double-click on it in the Toolbox,
which automatically adds the control to the upper left corner of the form.
Next, go to the Properties Window, change the TabControl’s Name property to
TabControl, change its Size
to 580,420, and set its TabStop
property to False. You may have noticed that, by default, the TabControl doesn’t
have any tabs. To add tabs, select the TabPages
property in the Properties Window, click the ellipses button (…) to launch the TabPage Collection Editor
(Figure 7), and click the Add
button to add the first page. This displays a Properties
sheet in the right pane of the dialog you can use to edit properties of the tab
page. Change the Text
property to “List” and change the Name
property to “ListPage”. Add a second tab and set its Text
property to “Properties” and the Name
property to “PropertiesPage”. Afterwards, click OK
to close the dialog. Figure 7. The TabPage Collection Editor allows
you to add, remove, and modify tab pages in the TabControl. Adding controls to the List page In this section, you’ll add a few controls to the List
page—a text box that allows you to enter a customer ID and a DataGrid that
displays all orders for the specified customer. You can drag and drop controls
any place on the form that, but if you want to end up with a form looking like
the one shown in this chapter’s figures, you should set location and size of
controls as specified. First, click on the List
page of the tab control. Add a label to the page by double-clicking on the Label item in the Toolbox (or by dragging
and dropping it on the form). Go to the Properties Window and change the
label’s Text property to
“Customer ID:” and its Name
property to “lblCustomerID”. Change its Location
property to 25,25. Next, add a text box control to the form from the Toolbox. Set its Name property to
txtCustomerID and remove all characters from its Text
property. Set the Location
property to 100,22. Finally, set the text box’s CharacterCasing
property to “Upper”. This causes the text box to automatically uppercase all
characters as they are typed (the Customer IDs in the Northwind database are
all uppercased). Add a DataGrid control to the form, set its Name property to
“grdOrders”, its Location
property to 25,65, and its Size
property to 425, 275. Finally, add three Buttons to the form and set their
properties as shown in Table 1. Table 1. Properties of Customer Orders form buttons Name Text Location btnNew &New 475, 85 btnDelete &Delete 475, 125 btnClose &Close 475, 285 When you’re done, the List
page should look like Figure 8. Figure 8. The Customer Orders form List page
allows you to view orders for a specified customer. Now add code to respond to the Close
button’s click event and close the form. First double-click on the Close button, which adds
a btnClose_Click event handler method to the form. You just need to add a
single line of code to this method to close the form. In C#: private void btnClose_Click(object sender,
System.EventArgs e) { this.Close(); } And in Visual Basic .NET: Private Sub btnClose_Click(ByVal sender As
System.Object, _ ByVal e As
System.EventArgs) Handles btnClose.Click Me.Close() End Sub Before adding any controls to the Properties
page, I’ll first get to something a little more interesting—adding code to the
form that displays all orders for a customer when the user enters a Customer
ID. Accessing data by means of business objects Many of the .NET samples available in books, magazines,
and on-line articles place data access code directly in the user interface. As
mentioned in Chapter 8, “.NET Business Objects”, a far better approach is
performing all data access and manipulation using business objects. In this
section, you will apply what you learned in the previous chapter and create
business objects to use with the Customer Orders form. First, you need to add two files to your Windows Forms
project that are found in the sample code for this book. If you’re working with
C#, add the files Business.cs and Data.cs to your project. To add these files
to your project, open the Solution Explorer, right-click on the project, and
select Add | Add Existing
item from the shortcut menu. In the Add
Existing Item dialog, navigate to the directory containing these
files and add them to the project. If you’re working with Visual Basic .NET, copy the existing
Business.vb and Data.vb files from the samples directory into your project’s
root directory using Windows Explorer. Afterwards, add the files to your
project as mentioned above. Next, change the namespace in the Business.vb file
to: Namespace Business And change the namespace in the Data.vb file to: Namespace Data Now you need to create an Orders business object that
retrieves data from the SQL Server Northwind database’s Orders table. To do
this, open the Solution Explorer, right-click your project, and select Add | Add New Item from
the shortcut menu. In the Add New
Item dialog’s right pane, select Code
File. Next, change the code file name to “OrdersBusiness.cs” (in
C#) or “OrdersBusiness.vb” (in Visual Basic .NET) and click the Open button. This opens
an empty code file in the IDE. At the top of the code file, enter the following code to
define a new Orders business object class. In C#: using
System.Data; namespace
HW.NetBook.Samples.Business { public class Orders : BusinessObject { public Orders() { this.TableName = "Orders"; } // Returns a DataSet containing all orders
for the specified customer public DataSet GetOrdersByCustomerID(string
custID) { custID = custID.ToUpper(); return this.GetDataSet("SELECT *
FROM Orders WHERE CustomerID = '" + custID + "'"); } /// Returns a DataSet containing the specified order public DataSet GetOrderByOrderID(int orderID) { return this.GetDataSet("SELECT * FROM Orders WHERE
OrderID = " + orderID); } } } And in Visual Basic .NET: Imports System.Data Namespace Business Public Class Orders Inherits BusinessObject Public Sub New() Me.TableName =
"Orders" End Sub 'New ' Returns a DataSet
containing all orders for the specified customer Public Function
GetOrdersByCustomerID(ByVal custID As String) _ As DataSet custID =
custID.ToUpper() Return
Me.GetDataSet(("SELECT * FROM Orders WHERE CustomerID = '" _ + custID +
"'")) End Function
'GetOrdersByCustomerID ' Returns a DataSet
containing the specified order Public Function GetOrderByOrderID(ByVal
orderID As Integer) As DataSet Return
Me.GetDataSet(("SELECT * FROM Orders WHERE OrderID = " & _
orderID.ToString())) End Function
'GetOrderByOrderID End Class 'Orders End Namespace 'Business Next, add a reference to the following namespaces to the top
of the code file. These references tell the compiler where to find the .NET
DataSet class as well as your business object classes. In C#: using System.Data; using HW.NetBook.Samples.Business; And in Visual Basic .NET: Imports System.Data Imports HW.NetBook.Samples.Business Now you need to add code to the form’s Load event that
instantiates the Orders business object when the form is first loaded. Add the
following private field declaration at the top of the CustomerOrdersForm class
declaration. This new field will hold a reference to the Orders business object
when it’s instantiated. While you’re at it, also add a private variable named
dsOrder to hold the Orders DataSet returned from the Orders business object. In C#: public class CustomerOrdersForm :
System.Windows.Forms.Form { private Orders
OrdersObj; private
DataSet dsOrders; And in Visual Basic
.NET: Public Class CustomerOrdersForm Inherits
System.Windows.Forms.Form Private OrdersObj As
Orders Private
dsOrders As DataSet Next, double-click on the form’s title bar in the Form
Designer to automatically In C#: private void CustomerOrdersForm_Load(object sender,
System.EventArgs e) { /// Instantiate the Orders
business object this.OrdersObj
= new Orders(); } And in Visual Basic .NET: Private Sub CustomerOrdersForm_Load(ByVal sender As
Object, _ ByVal e As System.EventArgs) _ Handles MyBase.Load '/ Instantiate the
Orders business object Me.OrdersObj = New
Orders() End Sub Now you need to add code to call the Orders business object
when a user enters a value in the Customer ID text box. In Visual FoxPro, you
may have placed this code in the Valid event of the text box. In .NET, you can
place this code in the text box’s Validating event. In .NET, user control focus events occur in the following order:
Enter, GotFocus, Leave, Validating, Validated, LostFocus The text box control’s default event is TextChanged, so you
can’t double-click on the text box to automatically add event handler code to
the form. If you’re using C#, you do this through the Properties Window. Make
sure the Customer Orders form is displayed in design mode and select the text
box. Go to the Properties Window and click the button with the lightning bolt
icon (the Events button). This displays all the events for the text box. If you double-click on the Validating
event (Figure 9), VS .NET automatically adds event handler code to the
form and displays the name of the event handler method in the second column of
the Properties Window (in this case, txtCustomerID_Validating). Remember, in C#
code is added both to the bottom of the form’s code file as well as within the
“hidden” area of the form’s code. If you want to delete both sets of related
code, in the Properties Window right-click on the event and select Reset from the shortcut
menu. Visual Studio .NET automatically removes both sets of code for you! Figure 9. Double-clicking on a user interface
control event in the Properties Window automatically adds event handler code
for that event to the form. If you are using Visual Basic .NET you can add an event handler to your
code by using the combo boxes at the top of the code editor. Just select the
control in the left combo box you want to create an event handler for and
select the desired event in the right combo box. When you do this, Visual Basic
.NET automatically adds event handler code to your form. At this point, you can add code to the Validating event
handler that calls the Orders business object with the specified Customer ID,
gets the returned DataSet, and stores it in the form-level private variable
dsOrder. Here’s the code in C#: private void txtCustomerID_Validating(object sender, System.ComponentModel.CancelEventArgs
e) { /// Get all orders for the
specified customer dsOrders=
this.OrdersObj.GetOrdersByCustomerID(this.txtCustomerID.Text.Trim()); } And here it is in Visual Basic .NET: Private Sub txtCustomerID_Validating(ByVal sender As
Object, _ ByVal e As
System.ComponentModel.CancelEventArgs) _ Handles
txtCustomerID.Validating '/ Get all orders for
the specified customer dsOrders = Me.OrdersObj.GetOrdersByCustomerID(Me.txtCustomerID.Text.Trim()) End Sub At this point, you have data and you have user interface
controls, but now you need to bring the two together so you can display and
edit the data—this requires data binding. In Visual FoxPro, you could bind user interface
controls to data by setting the ControlSource, RecordSource, or RowSource of a
control to a cursor, field, or object property. In a Windows Forms application, you can bind a user interface
control to a DataSet, Array, ArrayList, or any collection that implements the
IList interface (for information on implementing interfaces, see chapter 5,
“Object-Orientation in C# and Visual Basic .NET”). Simple data binding involves binding a single property
of a user interface control to a single data value. Controls that support
simple data binding usually only display one value at a time such as text
boxes, check boxes, and radio buttons. Binding a text box to the property of an
object is an example of simple data binding. Another example is binding a text
box to a single column in a DataTable. Simple-bound controls contain a collection of Binding objects
stored in a ControlBindingsCollection. Each binding object represents an individual
property bound to an individual data source value. This collection is
accessible through the control’s DataBindings property. You use the
DataBindings.Add method to add a Binding object to a control dynamically at run
time. You will see an example of this in the “Adding controls to the Properties
tab” section later in this chapter. Complex data binding involves binding a control to a
collection, such as a DataSet, Array, or ArrayList. Controls that support
complex data binding can display more than one value at a time—this includes
DataGrids, combo boxes, and list boxes. You will see examples of complex data
binding with DataGrids and combo boxes later in this chapter. Data binding controls at run time You can data bind controls at either design time or run
time. Visual Studio .NET has visual tools for adding a data source to a form
and binding user interface controls to that data source. However, as you might
imagine, using these VS .NET data binding tools creates a hard-coded monolithic
application. However, this book is showing you best practices, so I won’t use
these tools in this chapter, but will show you how to bind data dynamically at
run time instead. The following code sample shows the txtCustomerID_Validating
method with two new lines of code (shown in grey). The first new line calls the
DataGrid’s DataBindings.Clear method. This clears any existing data binding for
the grid, which is necessary because this code gets run every time the user
enters a new Customer ID. The second new line of code calls the grid’s
SetDataBinding method, passing the Orders DataSet and the Orders business
object’s TableName property (which is set to “Orders”). In C#: private void txtCustomerID_Validating(object sender, System.ComponentModel.CancelEventArgs
e) { /// Get all orders for the
specified customer } And in Visual Basic .NET: Private Sub txtCustomerID_Validating(ByVal sender As
Object, _ ByVal e As System.ComponentModel.CancelEventArgs)
_ Handles
txtCustomerID.Validating '/ Get all orders for
the specified customer dsOrders
= Me.OrdersObj.GetOrdersByCustomerID(Me.txtCustomerID.Text.Trim()) End Sub At this point, you’re almost ready to test what you’ve done
so far, but first you need to add code to launch your form when the user
selects Customers | Orders
from the menu. To do this, open the MainAppForm class in design mode by
double-clicking MainAppForm.cs or MainAppForm.vb file in the Solution Explorer
(if it’s not already open). Next, click on the Customers menu pad and
double-click the Orders menu bar below it. This adds a CustomerOrdersBar_Click
event handler method to the form (if you remembered to change the name of your
menu bar). Add the following code to instantiate and show the form. In C#: private void CustomerOrdersBar_Click(object sender,
System.EventArgs e) { /// Instantiate the form,
set its MdiParent and show the form to the user CustomerOrdersForm
OrdersForm = new CustomerOrdersForm(); OrdersForm.MdiParent =
this; OrdersForm.Show(); } And in Visual Basic .NET: Private Sub
CustomerOrdersBar_Click(ByVal sender As System.Object, _ ByVal e As
System.EventArgs) Handles CustomerOrdersBar.Click '/ Instantiate the
form, set its MdiParent and show the form to the user Dim OrdersForm As New
CustomerOrdersForm() OrdersForm.MdiParent =
Me OrdersForm.Show() End Sub The first line of code instantiates the Customer Orders form.
The second line of code stores a reference to the main application form in the
Order form’s MdiParent property. This is necessary if you want the Order form
to be contained within the main application form. If you do not set this
property, the Order form can be positioned outside the confines of the main
form. The last line of code makes the form visible to the user. Compiling and running the form Now you’re ready to compile and run the form. You can
perform each of these steps separately or you can just run the form (which is
what I usually do). Press F5
(the shortcut key for the Debug |
Start menu bar) and Visual Studio .NET first compiles the
solution and then runs the application. If there are any errors, VS .NET
displays a warning dialog asking if you still want to run the application. You
should select No
and fix the problems first before running it again. Although you can select Yes, since the compiler
encountered an error, you will be running the last successfully compiled
version of the application instead. When the main application form appears, select Customers | Orders from
the menu to launch the form. To test that the form and business object are
working properly, enter the text “QUEEN” in the Customer
ID box and press the Tab key. The grid should display a list of
all orders for the customer (Figure 10). If everything works properly,
you have permission to pump your fist in the air and do the .NET “dance of
joy”. Figure 10. Entering a Customer ID in the text box
and pressing Tab sends a request to the Orders business object, which returns a
DataSet that displays in the DataGrid. While you’re still flush with the feeling of success, click
the Windows menu pad
to see that a menu bar for your Customer Orders form has automatically been
added (Figure 11). Figure 11. When you set a menu pad’s MdiList
property to True, a menu bar is added to the pad for each form that is open in
the application. After the initial euphoria wears off, you will probably
notice that the data in the grid isn’t formatted as nicely as you’d like it to
be. First of all, the color scheme of the DataGrid could use some improvement,
and secondly, the DataGrid shows all columns in the DataSet (which you probably
don’t want to do). Select File |
Exit to close down the application, and you can take care of
these issues. There are several very cool features available in
Visual Studio .NET that simplify making your DataGrid look great, including a
number of features you probably wish were in Visual FoxPro.
Building .NET Windows Forms Applications
look behind the scenes by right-clicking on Form1 and selecting View Code from the
shortcut menu.



![]()
![]()
![]()
![]()


add event handler code to the form’s code file. Next, add code that
instantiates the Orders business object.
![]()

dsOrders=
this.OrdersObj.GetOrdersByCustomerID(this.txtCustomerID.Text.Trim());


