|
|||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
Building Windows ApplicationsIn This Chapter
The Way Things WereFor most of Visual Basic's history, you did not need to specify you were building a rich-client application—all the applications you built were rich-client apps. Web development has never been the purpose of Visual Basic. This focus on developing stand-alone or client/server applications with a Windows user interface created a very tight bond between the VB language and the forms engine within it. There was no need to distinguish between the language and the tools for building an interface in VB6, but there certainly is in .NET. In Visual Basic .NET, the technologies that enable you to create "standard" Windows applications are part of the .NET Framework, available to any .NET language. This is a huge change from the way things were. In each of the following sections, before going into detail on how the new Forms technology works in Visual Basic .NET, I briefly describe some of the relevant details about Visual Basic 6.0 forms. The Windows Forms ModelForms in Visual Basic 6.0 were distinct files from other types of code (such as modules and classes) stored in two parts—a .FRM file that contained the code and the layout of the form and a .FRX file, which was a special kind of resource file that held any embedded resources needed by the form. When you designed a form using the visual tools, controls were added to forms and properties were set (such as the size and position of various controls) without any visible effect on your code. Changing the position of a button would change some hidden (not shown in the IDE at least) text (shown below for a simple one button "Hello World" application) that you could access and change using a text editor, but all of these properties were not part of your code. Setting a property in code was therefore very different than setting it through the visual interface. Listing 3.1 The Code Behind a Visual Basic 6.0 FormVERSION 5.00
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 3090
ClientLeft = 60
ClientTop = 450
ClientWidth = 4680
LinkTopic = "Form1"
ScaleHeight = 3090
ScaleWidth = 4680
StartUpPosition = 3 'Windows Default
Begin VB.CommandButton Command1
Caption = "Hello World"
Default = -1 'True
Height = 495
Left = 840
TabIndex = 0
Top = 480
Width = 1335
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
This special area of the form would also contain object references (in the form of GUIDs) for any ActiveX controls you used. Although editing the .FRM file directly was not encouraged, that was exactly what you had to do to fix a corrupt form. Forms in .NET change everything just described. Forms are no longer "special" files; they are just code (.VB files in .NET), although they certainly can have associated resource files with them. Editing the properties of the form or of the controls on the form does not add hidden text to the form file; it generates real VB .NET code that sets the properties in the same way that you would in your own code. If you follow along with me and create a sample VB .NET form, you can explore the new forms designer and browse the code generated by your visual editing. Building a Hello World SampleFirst, go ahead and fire up Visual Studio .NET. Although it is possible to create Visual Basic .NET applications without using any IDE (another example of how VB has changed in its move to .NET), this book assumes that you have at least VB .NET Standard Edition and are therefore using the Visual Studio IDE. Once it is loaded, you should see a start page. This start page has a few tabs and several different areas of information, but the main area (which is displayed by default) has all of the functionality you need at this point, including a list of recently opened projects and a New Project button. Click the New Project button, or select File, New, Project from the menu to bring up the New Project dialog box. If you are new to Visual Studio .NET, this dialog box contains a lot more options than the equivalent from Visual Basic 6.0, including the capability to create Web Services, Windows Services, Console Applications, and more. For now though, pick the standard project for creating a new Windows Application: Windows Application. Selecting this project type (and picking a name and location, and then clicking OK) creates a new solution containing a single project that contains one blank Windows form and a code file called AssemblyInfo.vb. At this point, if you look around the Visual Studio .NET IDE, you will see an interface that is somewhat similar to Visual Basic 6.0, but many things have changed. In the first chapter of this book, I covered the IDE, detailing the key changes from Visual Basic 6.0 and many of the important features. Moving along with this quick sample, you will build the application's user interface by placing a button onto the form. To work with the form, you need to use its design view, which is accessed through the same steps as in VB6. Double-click the form (in the Solution Explorer) to bring it up in the design view or right-click it and pick View Designer (this was View Object in VB6, but the meaning is the same) from the context menu. Once you have the form's design view up, you can use the toolbox to select controls and place them onto your form. The toolbox looks a little different from the one in VB6. It has sliding groups to categorize all the different types of controls and lists the controls with an icon and text by default. It works a little differently as well. When you worked with the toolbox in Visual Basic 6.0, you had two choices of how to interact with it:
In the Windows forms designer, you have those two methods of placing a control and an additional option:
Using any one of the three possible methods, place a single button from the toolbox onto the form. It is a minor change, but it is worth noting that the Listing 3.2 Hello World Does Not Look Too Different in .NETPrivate Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
MsgBox("Hello World!")
End Sub
You can run the project at this point if you want; F5 works fine for that purpose or you can select Start from the Debug menu. The real reason for building this form was to look at the code generated by your actions in the designer. Exploring the Designer Generated CodeSwitch to the code for the form (right-click the form in the designer or the Solution Explorer and select View Code) and you will see your button's click procedure and an area called Windows Form Designer generated code, as shown in Figure 3.1.
Figure 3.1 Regions allow you to hide blocks of code. That area is a region, a new feature of the code editor in Visual Studio .NET that allows you to collapse areas of code down to a single line to simplify the experience of browsing code. We discussed regions in Chapter 1, but all you have to know now is that the designer (the visual tool for creating forms) has used this feature to hide all of the code that it generated as you built the form. As a rule, you are not supposed to go into this area of code, which is why it is hidden by default, but you should at least understand the code in this area. In some cases, you might even need to change it. You can expand the designer code region by clicking the plus symbol next to the region name. Inside the region, you will find a few key elements:
The Constructor and the Listing 3.3 In VB .NET, You Can View and Even Edit All the Code that Builds Your Form's Interface'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(96, 88)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.Add(Me.Button1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
The comment on the top of this routine lets you know that you can modify anything in here by using the visual designer, and that you should not change the code directly. This is pretty good advice, but let's ignore it for a moment and see what happens. If you look at lines 12-15 in Listing 3.3, you can see that they are setting the properties of the button, including the size. If you add some of your own code in there, even something as simple as outputting some text to the debug window, it could produce surprising results. In this case, just adding a line (see Listing 3.4) causes the Windows Form Designer to fail when trying to parse the code, producing the helpful little error message shown in Figure 3.2. Listing 3.4 Editing the Windows Forms Designer Generated Code May Produce Unexpected Results'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(96, 88)
Me.Button1.Name = "Button1"
Debug.WriteLine("Testing!")
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
Figure 3.2 The Windows Forms Designer does not deal well with someone changing its code. Other, less fatal, changes to the code are often undone the next time you change something in the designer (because the Handling Events in .NETEvent handling has changed, for the better, in .NET. I never really thought anything of it, but event procedures in Visual Basic 6.0 were attached to the appropriate object and event based solely on the procedure's name. This reliance on names meant that if you had already created and written code for If event handling is no longer based on procedure names, how do you connect a specific event handler with an object's event? There are two ways; one combines the familiar Using WithEvents and the Handles KeywordAlthough event handling in VB .NET has changed, as I described, using the Returning to the first example, a simple button on a form, look at the code generated by the Windows forms designer to see how the designer wired the Friend WithEvents Button1 As System.Windows.Forms.Button
The button is declared using the Listing 3.5 Designer Generated Event Handlers Use the Handles KeywordPrivate Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
MsgBox("Hello World!")
End Sub
Up to this point, the syntax might be a little different, but the general idea is the same as in Visual Basic 6.0. The only change, the addition of the Listing 3.6 The Windows Forms Designer Automatically Creates a Handler for the Default Event When You Double-Click a ControlPrivate Sub Button2_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button2.Click
End Sub
This procedure declaration is followed by Listing 3.7 Listing More than One Object's Events After a Procedure Declaration Allows You to Consolidate CodePrivate Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click, Button2.Click
MsgBox("Hello World!")
End Sub
Now, when either button is clicked, the same code will run. Any number of events can be handled by the same event procedure, assuming that all of the events have the same signature (the same set of arguments to their event procedures). It is also possible to have a single event handled by multiple procedures (see Listing 3.8) by having that event specified in multiple Listing 3.8 One Event, Such as a Button's Click, Can be Handled by Multiple RoutinesPrivate Sub ClickEvent1( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button2.Click
MsgBox("ClickEvent1")
End Sub
Private Sub ClickEvent2( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button2.Click
MsgBox("ClickEvent2")
End Sub
When Listing 3.9 If You Handle the Events of Many Different Objects, the Sender Parameter Tells You which Object Caused the Current EventPrivate Sub LotsOfButtons( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click, Button2.Click, _
Button3.Click, Button4.Click, _
Button5.Click, Button6.Click, _
Button7.Click, Button8.Click, _
Button9.Click, Button10.Click
Dim clickedBtn As Button
If TypeOf sender Is Button Then
clickedBtn = DirectCast(sender, Button)
MsgBox(clickedBtn.Text)
End If
End Sub
It is worth noting, although perhaps a bit confusing, that you could have also written this routine using Listing 3.10 All Windows Forms Controls Inherit from Control, so a Variable of that Type Can Be Used to Hold Any Control on Your FormPrivate Sub LotsOfButtons( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click, Button2.Click, _
Button3.Click, Button4.Click, _
Button5.Click, Button6.Click, _
Button7.Click, Button8.Click, _
Button9.Click, Button10.Click
Dim clickedCtrl As Control
If TypeOf sender Is Control Then
clickedCtrl = DirectCast(sender, Control)
MsgBox(clickedCtrl.Text)
End If
End Sub
The reason this works, and it does work, is due to the way in which Windows Forms controls have been written. All Windows Forms controls share the same base class, Wiring Up Events Manually with AddHandler/ RemoveHandlerThe
Figure 3.3 The check box on this form, which is using the new toggle button appearance, turns event handling on and off for the button. Listing 3.11 The CheckedChanged Event of the Check Box Is Used to Add and Remove an Event Handler for the Button's Click EventPrivate Sub CheckBox1_CheckedChanged( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles CheckBox1.CheckedChanged
If CheckBox1.Checked Then
AddHandler Button1.Click, _
AddressOf myClickHandler
Else
RemoveHandler Button1.Click, _
AddressOf myClickHandler
End If
End Sub
Private Sub myClickHandler( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs)
MsgBox("Event Handled!")
End Sub
Adding and removing an event handler is a more useful technique with non-form classes that raise events, but the procedure is the same.
Coding Without Control ArraysOne of the more noticeable changes for a Visual Basic 6.0 developer who is getting started in Windows forms is the lack of control arrays. This feature of pre-.NET VB allowed you to configure a set of controls with a single name by assigning index values to each control. Once a control array was created, a single event procedure could be used to handle the events of all the controls in the array and you could also loop through the controls in an array based on index. These features made control arrays useful for a great many projects, but I mostly remember using this feature to handle groups of option buttons (radio buttons in .NET). Consider this form in VB6 (see Figure 3.4), which displays a six-item option button (radio button) collection using a control array. A single event handler (see Listing 3.12) can be written for this array that will run whenever any of the options are selected, or the array can be looped through to find the one option button with a Listing 3.12 VB6 Event Handler for an Option Button Control ArrayPrivate Sub optFruit_Click(Index As Integer)
MsgBox "Selected Item: " & optFruit(Index).Caption
End Sub
Figure 3.4 A group of option buttons on a VB6 form can all be part of a control array. Due to the changes in event handling, allowing multiple objects' events to be mapped to the same event handler, achieving the same effect in Windows forms is not impossible, but it is not quite as simple as it was in VB6. Combining the event handling features of .NET with the use of a standard array, here is a walkthrough of handling some radio buttons on a .NET Windows form. This example creates an array to hold a set of radio buttons and shows you how you can use that array along with a shared event handler to determine which option button is currently selected. If you follow along with these steps, you can try out the code for yourself.
If you were to run this code, you would see the label changing every time a different option was selected. The flexibility of event handling in .NET allows you to work with a set of five radio buttons without having to have five different event handlers. Configuring Your Form for ResizingEvery time I built a resizable form in Visual Basic 6.0 (which includes every form I built except for the simplest of dialog boxes), I had to write code into the form's I had to decide how I wanted each control to adjust to the new size of the form, what size was too small for my interface to be usable, and I had to remember to check if the form had been minimized before trying to do any resizing. This code was not particularly hard to write, and after 50 or 60 forms I could do it without much thought, but it still took time and effort for every form I created. In Windows forms, a variety of features have come together to allow you to configure your controls for auto-resizing without having to write a single line of code. By combining the docking and anchoring features with the careful use of panels, you can set your form up to resize in almost any way you can imagine. If you add in the auto-scroll feature, you can even have parts of the form that do not resize at all, but instead extend right off the visible area of the form.
Using Docking to Handle ResizingDocking windows and toolbars have been in use for quite some time, so the general concept is not new; a docked item is attached to one of the edges of its container (such as a form). Consider a form that contains only a single
Figure 3.5 Docking a control to the left makes it stick to the left side, while filling the vertical space of the container. In addition to docking to one of the four sides, controls also support a fifth (sixth if you count Remember that you are docking the control to its container, which in this example is the The container (
Figure 3.6
Docking gets a little more complicated when multiple docked controls are involved. If you dock more than one control to the same edge, the second control will dock alongside the first instead of directly to the container. Going back to the example with the
Figure 3.7 Multiple controls docked to the same side will stack instead of overlap. Both of the controls are docked to the form and will resize as the form is resized. If you have controls docked to one or more sides of your container, and then you set another control's To add a splitter to your form, you need to be careful of the order in which you add your controls. Try adding a A little confusing? It can appear very complex, but the best bet is to try it out on your own, adding a variety of controls to a blank form and playing around with the various Anchoring as an Alternative Resizing TechniqueAfter docking, this has to be the coolest layout feature. Anchoring is a little simpler than docking, but it can be a powerful tool. Using a graphical property editor (see Figure 3.8), you can set the
Figure 3.8 The property editor for anchoring is a nice little graphical control. To anchor a control to a specific side means that the distance between the control and that side of its container becomes fixed. Therefore, if you anchor a control to a specific side and then resize the form, the control's distance from the anchored side(s) will not change. To maintain a constant position relative to one or more sides of your container, the control might have to be resized when the form's size changes. By default, controls are anchored to the top and left, which makes them behave exactly as controls did in previous versions of Visual Basic. When you resize the form, they do not move or resize. If you want to create a
Figure 3.9 Anchored controls maintain a fixed distance between themselves and the container edge(s) they are anchored to.
Figure 3.10 As the form changes size, the controls move and resize automatically. AutoScrolling FormsDocking and anchoring are designed to resize your controls when the form is resized, but resizing the contents of your form is not always appropriate. In some cases there is a minimum size at which your form is usable, so resizing below that needs to be avoided. There are also situations when the content on your form is a fixed size, making resizing inappropriate. Windows forms provides a few additional features to allow you to deal with these situations. Forms have minimum/maximum height and width properties (allowing you to constrain resizing to a specific range of sizes) and the
Figure 3.11 This form would be hard to resize, so the solution is to allow users to scroll. If the user were to resize this form, making it smaller than the area required for all of its controls, the
Figure 3.12
In addition to the Using PanelsPanels enhance all of the other layout features discussed so far because they can act as a container for other controls, much like a form does. Because they are containers, panels have their own Some Common Resizing ScenariosNow that you have been told what docking, anchoring, and auto-scrolling are, here are a few forms that demonstrate using the new layout features. A Standard One-Large-Control Dialog BoxA large control, such as
Figure 3.13 Allowing the users to resize your form makes your application work better on a range of screen sizes. If it were not for those two buttons, docking would be a possible answer, but anchoring saves the day here. Assuming a desired border around the form's contents of 10 pixels:
A Long List of QuestionsYou have a long list of questions that must be answered before a user can submit an order, and additional questions keep being added. There also needs to be an OK and Cancel button on the form; OK to move onto submitting the order, and Cancel to close the form and cancel the order.
A Multi-Column FormYou have a form with multiple columns of text boxes, each with associated labels, a single large text box, and the OK and Cancel buttons at the bottom (see Figure 3.16).
Figure 3.16 Multiple columns are trickier to resize. This gets a little trickier because of the two columns at the top of the form, but panels can make it all work out.
Note that I used the An Explorer-Style ApplicationYou are attempting to produce an interface in the format of the Windows Explorer, Outlook, and other applications. This interface will have a
Figure 3.17 The standard Explorer style of form layout. This style of layout is easy to accomplish with the new features of Windows forms, but the specific order in which you add items to your form is important.
That's it. The That is all of the sample resizing scenarios covered in this chapter, but that certainly is not the extent of layouts that can be created. Programming Without Default Form InstancesClasses and objects existed in Visual Basic 6.0, but they were not as pervasive as they are in .NET. Objects are everywhere when you are developing in Visual Basic .NET, and that large change has lead to many small changes that can trip you up when you are coming from a VB6 background. One of the more commonly encountered problems for a VB6 developer is the lack of default form instances in .NET, but the term default form instance is confusing enough that I will need to go into more detail about the problem before we look at any solutions. When you are dealing with classes and objects, it is helpful to think of a class as the blueprint of a house, whereas an object is an instance of a specific class and is more like an actual house that was built from the blueprint. In general, you don't work with classes, just like you don't live in blueprints. You create instances from your classes and it is those instances that get used throughout your applications. This is not a .NET issue; this is just how classes and objects work, even in VB6. Even in VB6, forms are considered classes, which is why you can create multiple copies (instances) of a single form in your VB6 code if you wish. The two snippets of code in Listings 3.17 and 3.18, assuming you have a Listing 3.17 VB6 Code to Display 11 Copies of a Form'VB 6 Code
Dim i As Integer
Dim myFrm As Form1
For i = 0 To 10
Set myFrm = New Form1
myFrm.Show
Next
Listing 3.18 The Very Similar VB .NET Code for Displaying 11 Copies of a Form'VB .NET Code
Dim i As Integer
Dim myFrm As Form1
For i = 0 To 10
myFrm = New Form1()
myFrm.Show()
Next
In each case, the code examples created 11 new instances of the class Form2.Show
Form2.TextBox1.Text = "dfsdf"
That code would not work in .NET, because it is treating the class Dim myFrm As New Form2()
myFrm.Show()
This is a major behavioral change from VB6, but the difference in code is not extreme. The removal of default instances changes more than just the code to show a form though. The second part of the problem is that these special default form instances were global to your entire project in Visual Basic 6.0. Taking the two facts together means that (in Visual Basic 6.0 or earlier) you can refer to any form in your project from anywhere in your code and you will always be referring to the same instance of that form. In Visual Basic .NET, if you need to access an instance of Working with Multiple Forms in VB .NETThe previous section described a major change in the forms model from VB6 to VB .NET—the removal of default form instances. This is not a major technical problem; programmers (including VB6 programmers) have been working without default instances of non-form classes for a very long time, but it is a big change if you are used to building Windows applications using VB6. The result of this change is that you need a reference to a particular instance of a form to be able to use it. I will start with a very simple example to illustrate the concept. I will create a new Windows application that contains two forms. Select File, New, Project from the main menu in Visual Studio .NET, and then pick a Visual Basic Windows Application to create. A form will be created with a default name of Creating and Displaying an Instance of a FormThe first step is to add code to Listing 3.19 Simple Code for Displaying a FormPrivate Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim myForm As New Form2
myForm.Show()
End Sub
Instead, you will move the Listing 3.20 Code That Will Create and Display Only One Copy of a FormDim myForm As Form2
Private Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
If myForm Is Nothing Then
myForm = New Form2
End If
myForm.Show()
End Sub
Using the Communicating Between Two FormsIf you want Public Class Form2
Inherits System.Windows.Forms.Form
Public myCaller As Form1
Then, right after you create an instance of Listing 3.21 You Can Pass a Form Reference with a PropertyDim myForm As Form2
Private Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
If myForm Is Nothing Then
myForm = New Form2
myForm.myCaller = Me
End If
myForm.Show()
End Sub
If code in Listing 3.22 Now that Form2 Has a Reference to Form1, it Can Access Form1's PropertiesPrivate Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
If Not myCaller Is Nothing Then
myCaller.Text = Now.ToLongTimeString
End If
End Sub
Clicking the button on Creating and Using a Form as a Dialog BoxTechnically speaking, every window/form in an application could be called a dialog box. When I use the term, however, I am referring specifically to a window that is displayed to request some information from the users and return that information back to the application that displayed the dialog box. For the most part, the calling application does not care what happens between displaying the form and the user clicking OK or Cancel to close it; all it is concerned with is the information gathered by the dialog box. To illustrate how you can create a standard dialog box using Visual Basic .NET, this section walks you through the creation of a dialog box that is designed to allow the users to enter in an address (see Figure 3.18).
Figure 3.18 An Address entry dialog box. Setting Up Your FormFirst, you create the sample application and form. Open a new project, a Visual Basic Windows Application, and add a new form named If you want your dialog box to be resizable, select the Once you have created your dialog box, the key to using it is to determine a method for putting starting data into the dialog box and for pulling out the information the user entered. You could access the various controls (the text boxes) directly, but I strongly advise against it. If you work directly with the controls, you will have to change that code if you ever modify the dialog box. Instead, I suggest one of two approaches. Either create a property procedure for each of the values you are exchanging (street, city, postal code, and country in this example) or create a new class that holds all of these values and then create a single property for that object. This section shows you both methods; you can use whichever one you prefer. For the first case, using multiple properties, create a property for each of the four values you are dealing with, as shown in Listing 3.23. Listing 3.23 You Can Insert and Remove Values from Your Dialog Box Using PropertiesPublic Property Street() As String
Get
Return Me.txtStreet.Text
End Get
Set(ByVal Value As String)
Me.txtStreet.Text = Value
End Set
End Property
Public Property City() As String
Get
Return Me.txtCity.Text
End Get
Set(ByVal Value As String)
Me.txtCity.Text = Value
End Set
End Property
Public Property PostalCode() As String
Get
Return Me.txtPostalCode.Text
End Get
Set(ByVal Value As String)
Me.txtPostalCode.Text = Value
End Set
End Property
Public Property Country() As String
Get
Return Me.txtCountry.Text
End Get
Set(ByVal Value As String)
Me.txtCountry.Text = Value
End Set
End Property
For now, these property procedures are just working with the text boxes directly. The value in using property procedures instead of direct control access is that you can change these procedures later, without affecting the code that calls this dialog box. The properties are all set up now, but to make the dialog box work correctly, you also need some code (shown in Listing 3.24) in the OK and Cancel buttons. Listing 3.24 Don't Forget to Provide a Way to Close Your FormsPrivate Sub saveAddress_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles saveAddress.Click
Me.Close()
End Sub
Private Sub cancelAddress_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles cancelAddress.Click
Me.Close()
End Sub
Although both button click events do the same thing, close the dialog box, the Listing 3.25 If Users Click OK, You Must Copy the Values Back, Otherwise You Don't Want to Change Anything Because They Must Have Clicked CancelPrivate Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim address As New addressDialog
Dim Street As String = "124 First Street"
Dim City As String = "Redmond"
Dim Country As String = "USA"
Dim PostalCode As String = "98052"
address.Street = Street
address.City = City
address.Country = Country
address.PostalCode = PostalCode
If address.ShowDialog = DialogResult.OK Then
Street = address.Street
City = address.City
Country = address.Country
PostalCode = address.PostalCode
End If
End Sub
The other method I mentioned, using a class to hold a set of values instead of passing each value individually, requires just a few modifications to the code. First, you need to create the class. Add a new class to your project, named Listing 3.26 With a Class being Used to Hold Multiple Values, You Can Add New Properties to it without Having to Change the Code to Pass it AroundPublic Class address
Dim m_Street As String
Dim m_City As String
Dim m_PostalCode As String
Dim m_Country As String
Public Property Street() As String
Get
Return m_Street
End Get
Set(ByVal Value As String)
m_Street = Value
End Set
End Property
Public Property City() As String
Get
Return m_City
End Get
Set(ByVal Value As String)
m_City = Value
End Set
End Property
Public Property PostalCode() As String
Get
Return m_PostalCode
End Get
Set(ByVal Value As String)
m_PostalCode = Value
End Set
End Property
Public Property Country() As String
Get
Return m_Country
End Get
Set(ByVal Value As String)
m_Country = Value
End Set
End Property
End Class
This class is nothing more than a convenient way to package data into a single object, but it allows you to have only a single property procedure (Listing 3.27) in the dialog box and to simplify the calling code in Listing 3.27 The Number of Properties Is Reduced to One if You Switch to Using a Class Versus Individual Properties on Your FormPublic Property Address() As address
Get
Dim newAddress As New address
newAddress.City = txtCity.Text
newAddress.Country = txtCountry.Text
newAddress.PostalCode = txtPostalCode.Text
newAddress.Street = txtStreet.Text
Return newAddress
End Get
Set(ByVal Value As address)
txtCity.Text = Value.City
txtCountry.Text = Value.Country
txtPostalCode.Text = Value.PostalCode
txtStreet.Text = Value.Street
End Set
End Property
Listing 3.28 A Single Property to Exchange Data Simplifies the Calling Code as well as the FormPrivate Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim addr As New address
Dim address As New addressDialog
Dim Street As String = "124 First Street"
Dim City As String = "Redmond"
Dim Country As String = "USA"
Dim PostalCode As String = "98052"
addr.Street = Street
addr.City = City
addr.Country = Country
addr.PostalCode = PostalCode
address.Address = addr
If address.ShowDialog = DialogResult.OK Then
addr = address.Address
End If
End Sub
The simple addition of a return code when displaying a modal form makes it easier to implement dialog boxes within Visual Basic .NET, but the lack of default form instances can make all multiple form applications difficult. In BriefThis chapter presented a detailed overview of the new Windows client development model in Visual Basic .NET. Here are the important points of this chapter:
| ||||||||||||||||||||||||||||||||||||