Click here to Skip to main content
Click here to Skip to main content
Go to top

Microsoft Visual Basic .NET 2003 Kick Start Chapter 3: Building Windows Applications

, 2 Mar 2004
Rate this:
Please Sign up or sign in to vote.
An introduction to building Windows applications using Visual Basic .NET.
Sample Image - 0672325497c.jpg
Authors Duncan Mackenzie, Andy Baron, Erik Porter, Joel Semeniuk
Title Microsoft Visual Basic .NET 2003 Kick Start
Publisher Sams
Published NOV 21, 2003
ISBN 0672325497
Price US$ 34.99
Pages 336

Building Windows Applications

In This Chapter

The Way Things Were

For 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 Model

Forms 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 Form

VERSION 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 Sample

First, 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:

  • You could double-click a control and a new instance of that type of control would be added to the form with a default size and location.
  • You could also select a control and then click the form to set the top-left location and drag an outline out to represent the size of the control.

In the Windows forms designer, you have those two methods of placing a control and an additional option:

  • You can drag a control from the toolbox onto the desired location on your form and it will be placed at that position with a default size.

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 CommandButton control from Visual Basic 6.0 has changed to the Button control in VS .NET 2002 and 2003. Just like in Visual Basic 6.0, you can double-click this new button to start writing an event handler for its most common event (in this case Click). All you want to do is pop up a message box, which you can do with the exact same line of code that you would use in Visual Basic 6.0 (see Listing 3.2).

Listing 3.2 Hello World Does Not Look Too Different in .NET

Private 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 Code

Switch 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:

  • A constructor for the form (a Sub New())
  • A Dispose procedure
  • Declarations of all of the controls on the form
  • A sub called InitializeComponent

The Constructor and the Dispose routines are new to Visual Basic .NET, but they are relatively equivalent to the Class_Initialize and Class_Terminate events of Visual Basic 6.0 classes. The constructor is called when an instance of your form is created; the Dispose is called before the form is destroyed. The real meat of the designer-generated code is the other two code elements—the list of declarations for all of the controls on the form and the InitializeComponent routine that sets up the properties of the controls on the form and of the Form itself. You did not set up many controls or even change many properties when creating this simple sample, but let's take a look at the generated code, shown in Listing 3.3.

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 InitializeComponent procedure is regenerated), which can be quite frustrating. Code generators (such as the designers in Visual Studio .NET) work well in many situations, but when they have to support round tripping (where the code isn't just generated once; it is read back in and used by the designer whenever the form needs to be displayed), they tend to be very fragile. In this case, you cannot make code changes to most of the designer-generated area. The place where you can change code is in the constructor; you can freely add code after the call to InitializeComponent as long as you do not remove that line! The best bet is to ignore all of the code inside this special region, other than the constructor, and make all of your property changes through the visual interface. Now let's go back to the button's click procedure and take a closer look at how .NET is handling events.

Handling Events in .NET

Event 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 CommandButton1_Click and you renamed your button to the more meaningful saveFile, your event procedure would no longer be attached to this button.

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 WithEvents keyword in your variable declarations with a new keyword Handles, and the other dynamically connects an object's event to an event handling procedure at runtime.

Using WithEvents and the Handles Keyword

Although event handling in VB .NET has changed, as I described, using the Handles keyword is the closest model to pre-.NET Visual Basic and it is the model used by default by the Windows forms designer. Objects, such as controls, that expose events are declared using the WithEvents keyword, like they were in Visual Basic 6.0, and event procedures provide a Handles myObj.myEvent clause after the procedure declaration. Those two parts, the Handles and WithEvents, wire up a specific event handling procedure.

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 Button's Click event to a code procedure. The first line to look at is the declaration of the button itself:

Friend WithEvents Button1 As System.Windows.Forms.Button

The button is declared using the WithEvents keyword, which is required if you want to use the Handles keyword on the event handling procedure. Only having both will make the proper connection between this object (the button) and the event procedure. Next, you double-click the Button1 and the Windows forms designer automatically creates a new event procedure for the default event (Click). Controls can specify one of their events to be the default. If they do, the Windows forms designer will assume you want to work with that event when you double-click the control. The designer knows that the button was declared using the WithEvents keyword, so it creates the procedure declaration with Handles Button1.Click appended to the end (see Listing 3.5).

Listing 3.5 Designer Generated Event Handlers Use the Handles Keyword

Private 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 Handles keyword, is just a way to get around relying on the name of your event handling procedure. Even using WithEvents and Handles though, there is a new feature built into this method of handling events. It is possible to specify that a specific event procedure handles more than one event. If you were to add a second button to the form, (automatically named Button2) and to double-click it, the Windows forms designer would create a second event procedure (see Listing 3.6).

Listing 3.6 The Windows Forms Designer Automatically Creates a Handler for the Default Event When You Double-Click a Control

Private Sub Button2_Click( _
    ByVal sender As System.Object, _
    ByVal e As System.EventArgs) _
    Handles Button2.Click
End Sub

This procedure declaration is followed by Handles Button2.Click, but you could instead modify the first Click procedure to handle both buttons' Click events, as shown in Listing 3.7.

Listing 3.7 Listing More than One Object's Events After a Procedure Declaration Allows You to Consolidate Code

Private 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 Handles clauses.

Listing 3.8 One Event, Such as a Button's Click, Can be Handled by Multiple Routines

Private 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 Button2 is clicked, the code in both ClickEvent1 and ClickEvent2 is executed. You will use the first concept (multiple events being handled by a single event handler) more often than the second (multiple handlers for a single event), but it is good to know that the functionality exists if you need it. In the case of multiple events all being handled by a single event handler, you will likely need to know which specific control is raising (firing or causing) the event. For most events, the object that raises the event is passed in as the first parameter (usually named "sender") to the event procedure. The sender parameter is typed as an Object, which means that you have to convert it into a more useful type (such as a Control or a Button) before you can work with it. Listing 3.9 shows a sample event procedure that is handling the Click event of 10 buttons; it casts (views an object as a different type) the sender parameter from Object to Button to determine the Button's text (caption).

Listing 3.9 If You Handle the Events of Many Different Objects, the Sender Parameter Tells You which Object Caused the Current Event

Private 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 Control instead of Button, and this alternative is shown in Listing 3.10.

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 Form

Private 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, System.Windows.Forms.Control, and that class provides them with a set of common properties, events, and methods. Text is one of those common properties, so you can cast to Control instead of Button and everything will still work. What does that mean to you? It means you can write code to handle any control on a form and you never have to know what type of control it is. Without casting it to a specific type of control, you can work with any of the common properties available on the Control class including position and size properties, color properties, and many more. Combining the new flexibility in event handling with this common control class, there is a lot you can accomplish using WithEvents and Handles. There are a few cases though, when even more flexibility is required, and that is where the other method of event handling comes in.

Wiring Up Events Manually with AddHandler/ RemoveHandler

The WithEvents/Handles method of event handling is designed for when you know at design time which controls and which event handling procedures you are dealing with. If you are going to be working with objects and event procedures in a more dynamic fashion, you can use the AddHandler and RemoveHandler statements to connect an object's event to an event procedure at runtime. This is more of an advanced technique, and it will not likely be necessary in most applications, but here is a basic example to illustrate how these statements could be used. In this example, there is a Button and a CheckBox (set to look like a button) on an otherwise empty form (see Figure 3.3). When the CheckBox is pressed (see Listing 3.11), the button's Click event is attached using AddHandler to a simple event handler that displays a MsgBox. When the CheckBox is in its up position, the button is detached from its event handler using RemoveHandler.

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 Event

Private 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.


Dynamic Event Handling - The AddHandler/RemoveHandler statements open up a completely new form of event handling, one that wasn't available in Visual Basic 6.0. There are many occasions where you will find yourself dynamically creating objects such as controls, but also including such things as forms, database objects, socket objects for TCP/IP communication, and more. By using AddHandler, you can still trap events from these objects even though you never declared them using WithEvents.

Behind the scenes, AddHandler and RemoveHandler are doing work with the delegate related Framework classes, wrapping the functionality of adding and removing additional methods (event handlers) to the same delegate (event). If you need to, you can still work natively with the System.Delegate class instead of, or in addition to, using AddHandler and RemoveHandler.


Coding Without Control Arrays

One 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 Value = True.

Listing 3.12 VB6 Event Handler for an Option Button Control Array

Private 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.

  1. Create a new Visual Basic .NET Windows application.
  2. A blank Form1 will be created and opened in Design View. Select the form and then drag a new radio button onto it from the toolbox.
  3. Copy and paste the radio button four times onto the form. This is likely the fastest way to end up with five radio buttons, but you can also drag four more radio buttons from the toolbox.
  4. Add a label to your form.
  5. Double-click one of the radio buttons to jump into its CheckedChanged event (see Listing 3.13) and modify the Handles clause to include all five of the radio buttons' events.

    Listing 3.13 Creating an Event Handler for All Five Radio Buttons

    Private Sub RadioButton1_CheckedChanged( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles RadioButton1.CheckedChanged, _
            RadioButton2.CheckedChanged, _
            RadioButton3.CheckedChanged, _
            RadioButton4.CheckedChanged, _
            RadioButton5.CheckedChanged
    
    End Sub
  6. Declare an array of radio buttons as a private member variable in your form (put the declaration anywhere in your code outside of a procedure):
    Dim radioButtons(4) As RadioButton
  7. Declare an integer private member variable as well:
    Dim selectedOption As Integer = 0
  8. Add code into the constructor of the form (the sub New() procedure contained within the Windows Forms Designer generated area) to fill up the array with the radio buttons (see Listing 3.14).

    Listing 3.14 Filling Up Your Own Radio Button Array

    Public Sub New()
      MyBase.New()
    
      'This call is required by the Windows Form Designer.
      InitializeComponent()
    
      'Add any initialization after the InitializeComponent() call
      radioButtons(0) = RadioButton1
      radioButtons(1) = RadioButton2
      radioButtons(2) = RadioButton3
      radioButtons(3) = RadioButton4
      radioButtons(4) = RadioButton5
    End Sub
  9. Finally, write code into the shared CheckedChanged event handler that will loop through the radio button array and determine the currently selected option (shown in Listing 3.15). Store the appropriate array index into selectedOption and change the Text property of the Label control.

    Listing 3.15 Loop Through the Radio Buttons and Determine which One Is Clicked

    Private Sub RadioButton1_CheckedChanged( _
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles RadioButton1.CheckedChanged, _
            RadioButton2.CheckedChanged, _
            RadioButton3.CheckedChanged, _
            RadioButton4.CheckedChanged, _
            RadioButton5.CheckedChanged
      Dim i As Integer = 0
      Dim found As Boolean = False
      While i < radioButtons.GetLength(0) And Not found
        If radioButtons(i).Checked Then
          found = True
          selectedOption = i + 1
          Label1.Text = CStr(selectedOption)
        End If
        i += 1
      End While
    End Sub

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 Resizing

Every 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 Resize event.

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 the Layout Event in Windows Forms - This section is all about avoiding the code you used to have to write into your Resize event handler, but even if you did write code, it wouldn't be in the same event handler in .NET. A new event, Layout, is available in Windows forms, and if you need to write code that adjusts the form after a resize, the Layout event is the best place for it.

The following sections explain how each of these three features works and how the use of panels can increase your flexibility of control arrangement. Once you have learned about all the features, the chapter will detail a few of the more common form layout scenarios, showing you how to set them up for proper resizing.


Using Docking to Handle Resizing

Docking 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 ListBox control. If you set the ListBox's Dock property to Left (see Figure 3.5), the height of the control will be fixed to the height of the form's client area (causing the list box to fill the form from top to bottom), while the position of the control will be locked to the left side of the form. The only thing you can change about the size of the list box at this point is its width, controlling how far out from the left side it extends. Docking to the right is essentially the same; the list box becomes attached to the right side of the form, but you can still change its width as desired. Docking to the top or bottom will cause the width to be fixed to fill the width of the form, but the height of the control can still be modified.

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 None for no docking) docking setting, Fill. If you set the Dock property to Fill, that control becomes attached to all four sides of the container, adjusting itself automatically as the form is resized. You cannot adjust any size or position settings for a control that has been docked to fill the container.

Remember that you are docking the control to its container, which in this example is the Form, but could be a container control such as a GroupBox or Panel. This flexibility leads to more layout options, as you will see later in the section on "Using Panels."

The container (Form, Panel, or other type of container controls) has a DockPadding property, which allows it to specify a certain amount of padding between it and docked controls. The padding values can be specified individually for the four sides of the container, or an overall padding value that applies to all of the sides at once. If a container has specified a DockPadding value of 10, for example, a control docked to the left will be positioned 10 pixels away from the left edge. The DockPadding setting is great for creating a more visually pleasing user interface as it results in a border around the form while still enabling the automatic resizing of docked controls (see Figure 3.6).

Figure 3.6

DockPadding allows you to dock, without sacrificing a bit of white space around the edge of your controls.

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 ListBox on a form, you can try multiple docked controls to see what happens. If you docked the ListBox to the bottom and then added a new DataGrid to the form, setting its Dock property also to Bottom, you would have produced an interface similar to Figure 3.7, where the ListBox appears below the DataGrid.

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 Dock property to Fill, the control set to Fill will be automatically sized to use all of the remaining area of the container. If you have multiple controls docked on a form, you might want to use the Splitter control. Splitter is a special Windows Forms control that, when docked between two other controls, allows you to resize the two controls at runtime. Using the Splitter control and a few other key controls, you can create a standard Explorer view form in a matter of minutes.

To add a splitter to your form, you need to be careful of the order in which you add your controls. Try adding a ListBox to an empty form, and docking it to the left. Then add a Splitter control, and dock it to the left as well (it is by default). Finally, add a DataGrid control, dock it to the left as well, or set its dock property to Fill, and you will have a working example of using a splitter!

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 Dock/DockPadding settings.

Anchoring as an Alternative Resizing Technique

After 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 Anchor property for a control to any combination of Top, Left, Bottom, and/or Right.

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 TextBox that grows as you make your form wider, you can anchor it to the top, left, and right sides. If you want the TextBox to grow in height as well as width, anchor it to the bottom as well. Figure 3.9 shows a form with some anchored controls, and Figure 3.10 shows what happens when that form is resized. You will see a few more examples of how anchoring can be used to lay out your form in the samples throughout the rest of this book.

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 Forms

Docking 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 AutoScroll feature. AutoScroll allows a form to be resized by the users, but instead of shrinking the controls on the form, scroll bars appear to allow the users to view the entire form area even if they have resized the window. The form shown in Figure 3.11 is a perfect candidate for AutoScroll; it contains a large number of controls and buttons and cannot be resized using docking or anchoring.

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 AutoScroll feature of Windows forms will save the day by adding horizontal and/or vertical scroll bars as required (see Figure 3.12).

Figure 3.12

AutoScroll automatically adds scroll bars when the form becomes small enough to hide any part of any of the controls on the form.

In addition to the AutoScroll property, which you set to True to enable auto scrolling, there are two other properties, AutoScrollMargin and AutoScrollMinSize, that are used to configure exactly how scrolling occurs.

Using Panels

Panels 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 DockPadding property and all of the auto-scroll features described for forms. A control can be placed into a panel and anchored to the bottom-right corner of that panel, while the panel itself was docked or anchored to a specific location on a form. By combining panels with forms, you can design more complicated layouts that still support resizing. Panels are used in several of the examples in the next section.

Some Common Resizing Scenarios

Now 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 Box

A large control, such as TextBox, ListBox, or DataGrid, needs to resize properly on a Form with two buttons (OK and Cancel), as shown in Figure 3.13.

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:

  • Position the large control with its top, left, and right edges 10 pixels in from the corresponding form edges. Note that you don't have to be exact about these positions, anchoring will lock the control in whatever place you put it. A precise border is just for aesthetics.
  • Add your two buttons to the bottom of the form, placing their bottom edge 10 pixels up from the bottom of the form. The right edge of one button should be 10 pixels in from the right edge of the form. Place the other button so that its right edge is five pixels away from the left edge of the first button.
  • Adjust the height of the large control so that its bottom edge is 10 pixels from the top of the two buttons.
  • Now, set the large control's Anchor property to "Top, Bottom, Left, Right" and both buttons' Anchor property to "Bottom, Right".

A Long List of Questions

You 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.

AutoScroll is the key for this layout, either for the entire form or for a panel, depending on whether you want to keep the OK and Cancel buttons visible at all times or if you want the user to have to scroll down to find them.

  • For the first option (Figure 3.14), where you want the buttons to be visible at all times, set up your form just like in Example 3.1, but use a Panel control as the large control.

    Figure 3.14

    A Panel allows you to restrict which parts of the form scroll and which parts are always visible.

  • Set the panel's AutoScroll property to True and then place all of your individual questions into the panel.
  • For the second option (Figure 3.15), set the Form's AutoScroll property to True and place all of your questions onto the form.

    Figure 3.15

    You can use the entire form surface for your scrolling area.

  • Add your OK and Cancel buttons at the very bottom of your form below all of the questions.

A Multi-Column Form

You 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.

  • Create a panel (mainPanel) that is tall enough to contain all of your controls for the top section of the form.
  • Create two more panels (rightPanel and leftPanel) and place them in the first panel you created.
  • Select one of the new panels (rightPanel) and make its Dock property equal to Right; make the other panel's Dock property equal to Fill.
  • Now, leftPanel will always fill the space not taken by rightPanel, but there is no way (in the designer) to force those two panels to equally share the available space. Instead you have to go to code.
  • View the code for your form, and then select mainPanel from the object drop-down list (left side) and Layout from the event drop-down list (right side). Enter the code from Listing 3.16, assuming your panel names are mainPanel, rightPanel, and leftPanel, into the Layout event handler.

    Listing 3.16 Using Code to Make Two Panels Share the Available Space

    Private Sub mainPanel_Layout( _
        ByVal sender As Object, _
        ByVal e As System.Windows.Forms.LayoutEventArgs) _
          Handles mainPanel.Layout
      rightPanel.Width = mainPanel.Width \ 2
    End Sub

Note that I used the Layout event, which is a new event in Windows forms that was not available in Visual Basic 6.0. In Visual Basic 6.0, I would have used the Resize event, but Layout is actually more precise as it occurs when the position and size of controls within a container might need adjusting, as opposed to occurring upon every resize of the form. If a form were set to AutoScroll, for example, the Resize event would fire whenever the form was resized (as it should), but the controls inside the form would not need to be rearranged.

An Explorer-Style Application

You are attempting to produce an interface in the format of the Windows Explorer, Outlook, and other applications. This interface will have a TreeView along one side of the form and a ListView on the other, and have the capability to move the dividing line between the two controls to resize them (see Figure 3.17).

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.

  • Starting with a blank form, add a TreeView control and set its Dock property to Left.
  • Add a Splitter control; it will automatically dock to the left and take its place along the right side of the TreeView.
  • Add a ListView control and set its Dock property to Fill.

That's it. The ListView will fill whatever space isn't being used by the TreeView and the Splitter will allow you to adjust the relative size of the two areas.

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 Instances

Classes 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 Form1 in your project, would produce the same result (11 open copies of Form1) in VB6 or VB .NET. The only differences between these two examples are syntax issues; they are otherwise identical.

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 Form1 and then called a method (Show) on each of those new instances. Code you wrote in VB6 that worked with multiple instances of a single Form class will probably work in .NET without too many changes, but consider this VB6 code:

Form2.Show
Form2.TextBox1.Text = "dfsdf"

That code would not work in .NET, because it is treating the class Form2 as if it were an instance of Form2. In Visual Basic 6.0 and earlier versions, a special default instance of each form is automatically created, and allows you to use the form's name to access this instance. What this means is that the Visual Basic 6.0 code Form2.Show has the effect of showing the "default" instance of Form2, but it doesn't work in Visual Basic .NET. If you want to show a form in VB .NET, you need to create an instance, writing code like this to make Form2 visible:

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 Form2 from some other part of your application (such as another form or a module), you need to pass the reference to Form2 around your application. The next section explores some of the ways in which you can work with multiple forms.

Working with Multiple Forms in VB .NET

The 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. Form1, which will be shown automatically when the project runs, will create and display an instance of Form2 when you click a button. To illustrate communication from one form to another, Form2 will also has a button, and it will change the caption of Form1 whenever it is clicked. To get things started, create the new project and add a new form.

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 Form1. Add a second form by right-clicking the project and selecting Add, Add Windows Form from the menu that appears. Accept the default name of Form2 for the new form and click the Open button to finish the wizard.

Creating and Displaying an Instance of a Form

The first step is to add code to Form1 to create and display an instance of Form2. Add a button to Form1, leaving it with a default name of Button1. Now, double-click the button to enter its event procedure for the Click event. If you used the code shown in Listing 3.19, a new form would open every time you click the button, which is likely not the desired result.

Listing 3.19 Simple Code for Displaying a Form

Private 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 Form variable to a module level value, and then determine if it already exists in the Click event (Listing 3.20). Then, you will create the form if it does not already exist and show it either way.

Listing 3.20 Code That Will Create and Display Only One Copy of a Form

Dim 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 myForm variable allows you to hang on to a reference to your newly created form. Hanging onto the reference returned from creating a new form is useful so that you can talk to this second form if need be. The main reason for using this variable though, is so that you can create and track a single instance of Form2, instead of creating a new one on every button click. Now, let's make Form2 talk back to Form1.

Communicating Between Two Forms

If you want Form2 to be able to communicate with Form1, you need to supply a reference to Form1. Once you do this, you will be set up for two-way communication, as both forms will be holding a reference to the other. The simplest way to accomplish this is to add a Public variable (of type Form1) to Form2, like this:

Public Class Form2
  Inherits System.Windows.Forms.Form

  Public myCaller As Form1

Then, right after you create an instance of Form2 in the button click event (see Listing 3.21), you can set this property.

Listing 3.21 You Can Pass a Form Reference with a Property

Dim 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 Form2 needs to access Form1, it can now do so through the myCaller variable. Add a button to Form2 and put this code into it, as shown in Listing 3.22.

Listing 3.22 Now that Form2 Has a Reference to Form1, it Can Access Form1's Properties

Private 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 Form1 will create an instance of Form2 and populate Form2's myCaller variable with a reference to Form1. Clicking the button on Form2 will access Form1 through the myCaller variable (if it was set) and change its window title. This was a very simple example of communicating between multiple forms, but there will be additional examples as part of the sample applications in Chapters 4 and 5. The next section covers creating and using a form as a dialog box.

Creating and Using a Form as a Dialog Box

Technically 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 Form

First, you create the sample application and form. Open a new project, a Visual Basic Windows Application, and add a new form named GetAddress. There should now be two forms in your project, which is exactly what you want because we will launch the GetAddress dialog box from Form1. Now, you need to set up the look of GetAddress to match the expected appearance of a dialog box. Set up four text boxes named txtStreet, txtCity, txtPostalCode, and txtCountry on your form and arrange them somewhat like the form shown in Figure 3.18. Now, add two buttons to your form, saveAddress and cancelAddress, with captions of OK and Cancel, respectively. The two buttons should be positioned in the lower-right corner. If you are planning to make your dialog box resizable, you will want to anchor the two buttons to bottom and right. Select the form itself (click any empty area of the design surface) and set its AcceptButton and CancelButton properties to the saveAddress and cancelAddress buttons. Setting these properties allows the users to use the Enter and Escape keys as the equivalent of OK and Cancel. The AcceptButton property also makes the saveAddress button into the default for the form, which causes it to be highlighted. So that you can tell what button was pressed to exit the form, you should also set the DialogResult property of both buttons. Set the DialogResult property for saveAddress to OK, and set it to Cancel for cancelAddress.

If you want your dialog box to be resizable, select the Sizable option for the FormBorderStyle property. For a fixed sized dialog box, you select FixedDialog for FormBorderStyle and set MinimizeBox and MaximizeBox both to False.

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 Properties

Public 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 Forms

Private 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 DialogResult property of each button is set appropriately so it will result in the correct result value being returned to the calling code. In the calling procedure, a button click event on the first form, you populate the dialog box using the property procedures, display it using ShowDialog(), and then retrieve the property settings back into the local variables. ShowDialog is the equivalent of showing a form in VB6 passing in vbModal for the modal parameter, but with the added benefit of a return value. ShowDialog returns a DialogResult value to indicate how the user exited the dialog box. The example in Listing 3.25 checks for the OK result code before retrieving the properties from the dialog box.

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 Cancel

Private 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 Address, and enter the class definition shown in Listing 3.26.

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 Around

Public 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 Form1 (see Listing 3.28).

Listing 3.27 The Number of Properties Is Reduced to One if You Switch to Using a Class Versus Individual Properties on Your Form

Public 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 Form

Private 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 Brief

This chapter presented a detailed overview of the new Windows client development model in Visual Basic .NET. Here are the important points of this chapter:

  • Windows forms is the new forms model for Visual Basic. Although it is similar to the forms model for Visual Basic 6.0, it supports many new features.
  • In .NET, you can see and sometimes edit all of the code that creates and configures your user interface.
  • Event handling in .NET is no longer based on the name of the event-handler procedure, instead a new Handles keyword has been added.
  • Form layout is more powerful in .NET than in VB6 due to the addition of new features for docking and anchoring.
  • There are no default instances of forms in VB .NET, which means you cannot work with the form's name as if it were always available.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Sams Publishing

United States United States
No Biography provided
Group type: Organisation

1 members


Comments and Discussions

 
GeneralMy vote of 5 Pinmembermanoj kumar choubey20-Feb-12 23:57 
GeneralCreating TreeView In Datagrid PinmemberRevathij12-Jun-07 1:45 
Generalhi!! PinmemberAinJheL_mi28-Jun-06 0:22 
GeneralRe: hi!! Pinmemberrymnnit20-May-07 4:20 
GeneralThanks Pinmemberspoodygoon9-Mar-06 9:58 
GeneralSocket class in VB.net PinsussAnonymous7-Aug-05 20:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 3 Mar 2004
Article Copyright 2004 by Sams Publishing
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid