bt 0082 visual basic contents - bscit2012.weebly.com

315
BT 0082 Visual Basic Contents Unit 1 Visual Basic .NET An Introduction 1 Unit 2 Basic Concepts and Language Fundamentals 29 Unit 3 Flow Control Statements 50 Unit 4 Form Based Applications 64 Unit 5 Exception Handling in VB.NET 100 Unit 6 Data Access in VB.NET 124 Unit 7 Working with Records in VB.NET 140 Unit 8 Arrays in Visual Basic 152 Unit 9 ImageList and TreeView Controls 178 Unit 10 The ListView Control 198 Edition: Spring 2009 BKID B1093 9 th Oct. 2009

Upload: others

Post on 23-Nov-2021

3 views

Category:

Documents


0 download

TRANSCRIPT

BT 0082

Visual Basic

Contents

Unit 1

Visual Basic .NET – An Introduction 1

Unit 2

Basic Concepts and Language Fundamentals 29

Unit 3

Flow Control Statements 50

Unit 4

Form Based Applications 64

Unit 5

Exception Handling in VB.NET 100

Unit 6

Data Access in VB.NET 124

Unit 7

Working with Records in VB.NET 140

Unit 8

Arrays in Visual Basic 152

Unit 9

ImageList and TreeView Controls 178

Unit 10

The ListView Control 198

Edition: Spring 2009

BKID – B1093 9

th Oct. 2009

Unit 11

Classes and Objects 217

Unit 12

Inheritance and Interfaces – I 240

Unit 13

Inheritance and Interfaces – II 266

Unit 14

Multithreading in Visual Basic 290

Acknowledgements, References and

Suggested Readings 307

Director & Dean Directorate of Distance Education Sikkim Manipal University of Health, Medical & Technological Sciences (SMU DDE)

Board of Studies Dr. U. B. Pavanaja (Chairman) Nirmal Kumar Nigam General Manager – Academics HOP – IT Manipal Universal Learning Pvt. Ltd., Bangalore SMU DDE, Manipal Prof. Bhushan Patwardhan Dr. A. Kumaran Chief Academics Research Manager (Multilingual) Manipal Education Microsoft Research Labs India Bangalore. Bangalore. Dr. Harishchandra Hebbar Ravindranath P. S. Director Director (Quality) Manipal Centre for Info. Sciences, Yahoo India Bangalore Bangalore. Dr. N. V. Subba Reddy Dr. Ashok Kallarakkal HOD-CSE Vice President Manipal Institute of Technology, Manipal IBM India, Bangalore Dr. Ashok Hegde H. Hiriyannaiah Vice President Group Manager MindTree Consulting Ltd., Bangalore EDS Mphasis, Bangalore Dr. Ramprasad Varadachar Director, Computer Studies Dayanand Sagar College of Engg. Bangalore.

Content Preparation Team Content Writing Content Editing Mr. Nirmal Kumar Nigam Mr. Balasubramani R Asst. Professor & HoP – IT Asst. Professor – IT SMU DDE, Manipal SMU DDE, Manipal

Instructional Design Language Editing Mr. Kulwinder Pal Ms. Aparna Ramanan Asst. Professor – Education Asst. Professor – English SMU DDE, Manipal SMU DDE, Manipal

Mr. Balasubramani R Mr. Naveen Dias Asst. Professor – IT Sr. Lecturer – English SMU DDE, Manipal Government First Grade College, Mangalore

Edition: Spring 2009

This book is a distance education module comprising a collection of learning material for our students. All rights reserved. No part of this work may be reproduced in any form by any means without permission in writing from Sikkim Manipal University of Health, Medical and Technological Sciences, Gangtok, Sikkim. Printed and published on behalf of Sikkim Manipal University of Health, Medical and Technological Sciences, Gangtok, Sikkim by Mr. Rajkumar Mascreen, GM, Manipal Universal Learning Pvt. Ltd., Manipal – 576 104. Printed at Manipal Press Limited, Manipal.

This book is a comprehensive, hands-on guide to the Visual Basic .NET

programming language addressed to readers with some programming

background. No background in Visual Basic is required, however.

The book covers at the least the fundamentals of every technique that a

professional VB .NET developer will need to master. This is a book about

the techniques you need to master.

Finally, since most people reading this book will have programmed with

some version of Visual Basic before, the book tries to differentiate between

VB .NET and earlier versions of VB as I could. However, this book does not

assume any knowledge of earlier versions of VB, just some programming

experience.

Unit 1: Visual Basic .NET – An Introduction

This unit takes the reader through the basic concepts of Visual Basic.Net

and Visual Studio development environments. It also gives the concepts of

Window Forms, Web forms, and components of .Net framework. It guides

the reader through the process of compiling and running a Visual basic

application It walks through all the basic concepts involved in designing,

running, and executing a Visual Basic.Net application.

Unit 2: Basic Concepts and Language Fundamentals

It gives a walkthrough of all the basic concepts and theory behind the

language needed for a beginner or a developer to start with working on

VB.Net applications. It gives a broad picture of the data types, variables,

and constants in VB.Net.

Unit 3: Flow Control Statements

This unit makes the reader understand the concepts of Flow controls

statements used in VB.Net. It also goes through the looping structures and

arrays along with their syntax in VB.Net

Unit 4: Form Based Applications

This unit gives an extensive walkthrough of the desing and development of

windows form based application. It gives an in-depth coverage of all the

controls used in development of a form based application alogn with code

SUBJECT INTRODUCTION

snippets or complete programs covering each of them. It also discusses the

design of multi-form applications, SDI and MDI Interfaces.

Unit 5: Exception Handling in VB.NET

This unit starts with an introduction of error handling and exception handling

techniques. It describes the usage and application of Exception handling

techniques in VB.Net applications. It then describes the other keywords

associated with exception handling like Exit try, Source and Stacktrace. The

unit gives the user an insight into different ways of handling various

exceptions in various applications.

Unit 6: Data Access in VB.NET

This unit explains the mechanism of data access and the various techniques

of handling data like the usage of data form wizard in Visual Studio.Net. It

demonstrates the concepts of connections strings, opening the connection,

and so on necessary to connect and access the data to any data source. It

then describes the concepts of Structured Query language. The concepts of

filling the data sets, record navigation, and DML operations described.

Unit 7: Working with Records in VB.NET

This unit gives brief introduction to navigating records in VB.NET. Also you

will learn how to add new records, update existing records and deleting

unwanted records.

Unit 8: Arrays in Visual Basic

This unit illustrated the usage of a single variable to store n number of

values of homogenous data type. It also discussed the manipulation

operations on various types of arrays.

Unit 9: The ImageList and TreeView Controls

This unit described the features of all the Windows common controls

included in MsComCtr.ocx. In particular, the implementation and usage of

ImageList and TreeView controls have been described.

Unit 10: The ListView Control

This unit has illustrated the usage and applications of List View Control and

in the real world GUI design. The concepts of loading, retrieving, and

performing various operations on a ListView control have been described.

Unit 11: Classes and Objects

This unit describes the theoretical concepts of classes and objects, and their

applications in VB.Net programming.

Unit 12: Inheritance and Interfaces – Part I

This unit focuses on Inheritance concepts of VB.Net programming. It lets the

reader practice and apply the discussed concepts in real time programming

problems.

Unit 13: Inheritance and Interfaces – Part II

This unit describes the ins and outs of the Object class. This is the class that

all .NET objects ultimately inherit from. It also discusses implementation

inheritance by showing what .NET does to help solve the fragile base class

problem that is at the root of many of the implementation inheritance

problems in other OOP languages such as Java or C++.

Unit 14: Multithreading in Visual Basic

This unit describes the theory behind running various applications

simultaneously in VB.Net. using multithreading. It also discusses in detail

various multithreading related concepts like joining threads, making threads

to sleep, suspending or killing a thread, and the Daemon (Background)

threads.

Objectives of studying this subject

After studying this subject, you should be able to:

describe the architecture of VB.Net

explain the basic concepts of Visual Basic Language

illustrate the usage of various flow control statements

describe and illustrate form based applications

explain and use exception handling

explain the techniques of data accessing using VB.Net

explain and illustrate the working of records

discuss the usage of arrays in programming

explain and apply the ImageList and TreeView controls

explain and apply the ListView control

describe the Object Oriented Concepts in the context of VB.Net

define and explain basic inheritance concepts

describe the Object Class and Interfaces using VB.Net

describe and illustrate multithreading

Visual Basic Unit 1

Sikkim Manipal University Page No.: 1

Unit 1 Visual Basic .NET – An Introduction

Structure:

1.1 Introduction

Objectives

1.2 .Net Framework and Visual Studio.NET

1.3 Windows Forms and Web Forms Applications

1.4 The Components of the .NET Framework

1.5 Compiling and Running a Visual Basic Application

1.6 Visual Basic .NET and Visual Basic 6.0

1.7 Microsoft Development Environment 1.8 Customizing Visual Studio for Use With Visual Basic

1.9 Solutions and Projects in Visual Basic

1.10 Working with the IDE

1.11 The Code Editor Window

1.12 The Solution Explorer

1.13 Working with Windows in the IDE

1.14 Summary

1.15 Terminal Questions

1.16 Answers

1.1 Introduction

Before you can learn how to develop applications with Visual Basic .NET,

you need to become familiar with the .NET Framework, Visual Studio .NET,

and the Microsoft Development Environment. Along the way, you’ll learn

some basic concepts and some basic skills for working with the

Development Environment.

Objectives:

This unit introduces the reader to the basic concepts of Visual Studio.Net

and the .Net framework.

After studying this unit, you should be able to:

describe the importance of .Net Framework and Visual Studio.Net in

developing applications

design Windows Forms and Web Forms

describe the components of .Net Framework

compile and run a Visual basic Application

customize Visual Studio for use with Visual Basic.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 2

1.2 .NET Framework and Visual Studio .NET

The .NET Framework (pronounced “dot net framework”) defines the

environment that you use to execute Visual Basic .NET applications and the

services you can use within those applications. One of the main goals of this

framework is to make it easier to develop applications that run over the

Internet. However, this framework can also be used to develop traditional

business applications that run on the Windows desktop.

To develop a Visual Basic .NET application, you use a product called Visual

Studio .NET (pronounced “Visual Studio dot net”). This is actually a suite of

products that includes the three programming languages described in table

1.1. In this book, of course, you’ll learn how to use Visual Basic .NET, which

is designed for rapid application development.

Visual Studio also includes several other components that make it an

outstanding development product. One of these is the Microsoft

Development Environment, which you’ll be introduced to in a moment.

Another is the Microsoft SQL Server 2000 Desktop Engine (or MSDE).

MSDE is a database engine that runs on your own PC so you can use

Visual Studio for developing database applications that are compatible with

Microsoft SQL Server. SQL Server in turn is a database management

system that can be used to provide the data for large networks of users or

for Internet applications.

The two other languages that come with Visual Studio .NET are C# and

C++. C# .NET (pronounced “C sharp dot net”) is a new language that has

been developed by Microsoft especially for the .NET Framework. Visual

C++ .NET is Microsoft’s version of the C++ language that is used on many

platforms besides Windows PCs.

In this figure, you can see that Visual Studio .NET can be used on any PC

that runs Windows 2000 or later. You can also see that the applications that

are developed with Visual Studio .NET can be run on any PC that runs

Windows 98 or later, depending on which .NET components are used by the

application. From a practical point of view, though, you can assume that the

applications that you develop with Visual Basic .NET will be run on PCs that

are using Windows 2000 or later.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 3

This figure also shows that Visual Basic .NET comes in an inexpensive

Standard Edition that includes only the Visual Basic language, not C# or

C++. All but one of the Visual Basic features presented in this book work

with the Standard Edition as well as the full Visual Studio .NET.

Although the three languages shown in this figure are the only three

programming languages you can use within Visual Studio .NET, other

vendors are free to develop languages for the .NET Framework. For

example, Fujitsu has already developed a version of COBOL for the .NET

Framework.

Figure 1.1: Visual Studio .NET and the .NET Framework

Figure 1.1: .NET Framework

Table 1.1: Programming languages supported by Visual Studio .NET

Language Description

Visual Basic .NET Designed for rapid application development

Visual C# .NET A new language that combines the features of

Java and C++ and is suitable for rapid application

development

Visual C++ .NET Microsoft’s version of C++ that can be used for

developing high-performance applications

Web Services Web Forms

ASP.NET Application Services

ASP.NET Windows Forms

Controls Drawing

Windows Application Services

.NET Framework Base Classes

ADO.NET XML

Net

Threading IO

Security Diagnostics Etc.

Memory Management Common Type System

Life Cycle Monitoring

Common Language Runtime

Visual Basic Unit 1

Sikkim Manipal University Page No.: 4

Table 1.2: Two other components of Visual Studio .NET

Component Description

Microsoft SQL Server 2000

Desktop Engine

A database engine that runs on your own

PC so you can use Visual Studio for

developing database applications that are

compatible with Microsoft SQL Server

Platforms that can run Visual Studio .NET

Windows 2000 and later releases of Windows

Platforms that can run Visual Studio .NET applications

Windows 98 and later releases of Windows, depending on which .NET

components the application uses.

Visual Basic .NET Standard Edition

An inexpensive alternative to the complete Visual Studio .NET package

that supports a limited version of Visual Basic .NET as its only

programming language.

Description

The .NET Framework defines the environment that you use for

executing Visual Basic .NET applications.

Visual Studio .NET is a suite of products that includes all three of the

programming languages listed above. These languages run within the

.NET Framework.

You can develop business applications using either Visual Basic .NET or

Visual C# .NET. Both are integrated with the design environment, so the

development techniques are similar although the language details vary.

Besides the programming languages listed above, third-party vendors

can develop languages for the .NET Framework. However, programs

written in these languages can’t be developed from within Visual Studio

.NET.

1.3 Windows Forms and Web Forms Applications

You can use Visual Basic .NET for developing the two types of applications

shown in figure 1.2. A Windows Forms application is a typical Windows

application that runs on the user’s PC. Each Windows form (or just form) in

Visual Basic Unit 1

Sikkim Manipal University Page No.: 5

the application provides a user interface that lets the user interact with the

application. In the example in this figure, the application consists of a single

form that lets the user perform either of two calculations: a future value or a

monthly investment calculation. Many applications, though, require more

than one form.

As part of the user interface, a Windows Forms application uses Windows

Forms controls. For instance, the form in this figure uses radio buttons,

labels, text boxes, and buttons. In the next chapter, you’ll start learning how

to develop Windows Forms applications.

The other type of application that you can develop with Visual Basic .NET is

a Web Forms application. Like a Windows Forms application, a Web Forms

application consists of one or more web forms that can contain controls.

Unlike Windows forms, though, web forms are accessed by and displayed in

a web browser. For instance, the web form in this figure is displayed in the

Microsoft web browser, which is called Internet Explorer.

As part of the user interface, a web form uses Web Forms controls. These

controls are similar to the Windows Forms controls, but they work only with

web forms.

In contrast to a Windows Forms application, which runs on the user’s PC,

the code for a Web Forms application runs on a web server. As this code is

executed, it passes the visual portion of the application to the browser

running on the client in the form of HTML (Hypertext Markup Language).

The browser then interprets the HTML and displays the form. In chapters 19

and 20, you’ll learn how to develop Web Forms applications with Visual

Basic .NET.

A Windows Forms application running on the Windows desktop

Visual Basic Unit 1

Sikkim Manipal University Page No.: 6

A Web Forms application running in a Web browser

Figure 1.2: Windows Forms and Web Forms applications

Description

A Windows Forms application runs on the Windows Desktop and can

consist of one or more Windows forms. These forms provide the

graphical user interface (GUI) for the application.

Each Windows form can contain Windows Forms controls like labels,

text boxes, buttons, and radio buttons. These controls let the user

interact with the application.

A Web Forms application runs on a web server, but its user interface is

displayed in a web browser on the client machine.

A Web Forms application consists of one or more web forms that

provide the user interface for the application. Each form can contain

Web Forms controls like labels, text boxes, buttons, and radio buttons.

Self Assessment Questions

1. The _____ defines the environment that you use to execute Visual Basic

.NET applications and the services you can use within those

applications.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 7

2. To develop a Visual Basic .NET application, you use a product called

_____.

3. A _____ application runs on the Windows Desktop and can consist of

one or more Windows forms.

1.4 The Components of the .NET Framework

To give you a more detailed view of the .NET Framework, figure 1.3

presents the main components of this framework. As you can see, the .NET

Framework provides a common set of services that application programs

written in a .NET language such as Visual Basic .NET can use to run on

various operating systems and hardware platforms. The .NET Framework is

divided into two main components: the .NET Framework Class Library and

the Common Language Runtime.

The .NET Framework Class Library consists of segments of pre-written

code called classes that provide many of the functions that you need for

developing .NET applications. For instance, the Windows Forms classes are

used for developing Windows Forms applications. The ASP.NET classes

are used for developing Web Forms applications. And other classes let you

work with databases, manage security, access files, and perform many

other functions.

Although it’s not apparent in this figure, the classes in the .NET Framework

Class Library are organized in a hierarchical structure. Within this structure,

related classes are organized into groups called namespaces. Each

namespace contains the classes used to support a particular function. For

example, the System.Windows.Forms namespace contains the classes

used to create forms and the System.Data namespace contains the classes

you use to access data.

The Common Language Runtime, or CLR, provides the services that are

needed for executing any application that’s developed with one of the .NET

languages. This is possible because all of the .NET languages compile to a

common intermediate language, which you’ll learn more about in the next

figure. The CLR also provides the Common Type System that defines the

data types that are used by all the .NET languages. That way, you can use

more than one of the .NET languages as you develop a single application

without worrying about incompatible data types.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 8

If you’re new to programming, the diagram in this figure probably doesn’t

mean too much to you right now. For now, then, just try to remember the

general structure of the .NET Framework and the terms that I’ve presented.

As you progress through this book, you will become more familiar with each

of the terms.

Figure 1.3: The components of the .NET Framework

Description

.NET applications do not access the operating system or computer

hardware directly. Instead, they use services of the .NET Framework,

which in turn access the operating system and hardware.

The .NET Framework consists of two main components: the .NET

Framework Class Library and the Common Language Runtime.

The .NET Framework Class Library provides pre-written code in the form

of classes that are available to all of the .NET programming languages.

This class library consists of hundreds of classes, but you can create

simple .NET applications once you learn how to use just a few of them.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 9

The Common Language Runtime, or CLR, is the foundation of the .NET

Framework. It manages the execution of .NET programs by coordinating

essential functions such as memory management, code execution,

security, and other services. Because .NET applications are managed

by the CLR, they are called managed applications.

The Common Type System is a component of the CLR that ensures that

all .NET applications use the same basic data types regardless of what

programming languages were used to develop the applications.

1.5 Compiling and Running a Visual Basic Application

Figure 1.4 shows how an application is compiled and run when using Visual

Basic .NET. To start, you use Visual Studio .NET to create a project, which

is made of one or more source files that contain Visual Basic statements.

Most simple projects consist of just one source file, but more complicated

projects can have more than one source file. A project may also contain

other types of files, such as sound files, image files, or simple text files. As

the figure shows, a solution is a container for projects, which you’ll learn

more about in a moment.

You use the Visual Basic compiler, which is built into Visual Studio, to

compile your Visual Basic source code into Microsoft Intermediate

Language (or MSIL). For short, this can be referred to as Intermediate

Language (or IL).

At this point, the Intermediate Language is stored on disk in a file that’s

called an assembly. In addition to the IL, the assembly includes references

to the classes that the application requires. The assembly can then be run

on any PC that has the Common Language Runtime installed on it. When

the assembly is run, the CLR converts the Intermediate Language to native

code that can be run by the Windows operating system.

CLR is available for Unix System also, i.e. Mono. It is possible that the CLR

will eventually be available for other operating systems as well. In other

words, the Common Language Runtime makes platform independence

possible. Visual Basic applications will be able to run on those operating

systems as well as Windows/Unix operating systems. Whether this will

happen and how well it will work remains to be seen.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 10

1.6 Visual Basic .NET and Visual Basic 6

If you are an experienced Visual Basic 6 programmer, you’ll notice that

Microsoft has made many changes to Visual Basic for .NET. In fact, the

changes are so significant that it’s probably best to think of Visual Basic

.NET as a new language with a familiar syntax.

Although there are a few changes to the Visual Basic language itself, the

most significant change in VB.NET is its reliance on the .NET Framework

classes. These classes affect almost every aspect of VB.NET programming,

including creating and working with forms and controls, using databases and

even working with basic language features such as arrays and strings.

Although Visual Basic .NET provides an upgrade wizard that lets you

convert VB6 applications to VB.NET, it leaves much of the conversion work

up to the programmer. As a result, most companies will probably not

upgrade their existing VB6 applications to VB.NET. Instead, they’ll support

their existing VB6 applications and use VB.NET to develop new

applications.

Figure 1.4: Compiling and Running a Visual Basic application

Visual Basic Unit 1

Sikkim Manipal University Page No.: 11

Description

1. The programmer uses Visual Studio’s Integrated Development

Environment to create a project, which includes one or more Visual

Basic source files. In some cases, a project may contain other types of

files, such as graphic image files or sound files.

A solution is a container that holds projects. Although a solution can

contain more than one project, the solution for most simple applications

contains just one project. So you can think of the solution and the project

as essentially the same thing.

2. The Visual Basic compiler translates or builds the source code into

Microsoft Inter-mediate Language (MSIL), or just Intermediate Language

(IL). This language is stored on disk in an assembly that also contains

references to the classes that the application requires. An assembly is

simply an executable file that has an .exe or .dll extension.

3. The assembly is then run by the .NET Framework’s Common Language

Runtime. The CLR manages all aspects of how the assembly is run,

including converting the Intermediate Language to native code that can

be run by the operating system, managing memory for the assembly,

enforcing security, and so on.

Self Assessment Questions

4. You use Visual Studio .NET to create a project, which is made of one or

more _____ that contain Visual Basic statements.

5. The _____ consists of segments of pre-written code called _____ that

provide many of the functions that you need for developing .NET

applications.

6. The programmer uses Visual Studio’s Integrated Development

Environment to create a _____.

1.7 Microsoft Development Environment With that as background, you’re ready to take a tour of the Microsoft

Development Environment. This is the Integrated Development

Environment, or IDE, that you use for developing Visual Basic applications.

Along the tour, you’ll learn some of the basic techniques for working in this

environment. You’ll also see how some of the terms that you just learned

are applied within the IDE.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 12

How to use the Start page The Start page, shown in figure 1.5, is displayed when you start Visual

Studio. From this page, you can open existing projects or create new

projects, change your Visual Studio configuration settings, and access

various online Visual Studio resources.

Note that the first time you start Visual Studio after installing it, the My

Profile link rather than the Get Started link is displayed. You’ll find

information about the My Profile link in the next figure.

The Start page is actually the home page of a web browser that’s built into

Visual Studio. The built-in web browser is displayed whenever you access

the Start page or when you’re accessing Help information. You can return to

the Start page at any time by using the Help, Show Start Page command.

In case you aren’t familiar with the notation I just used, Help, Show Start

Page means to pull down the Help menu from the menu bar and then select

the Show Start Page command. We’ll use this notation throughout this book

because it makes it easier to find the command that you need. Usually, you

only need to pull down one menu and select a command. But sometimes,

you need to go from a menu to one or more submenus and then to the

command. In the second bulleted item in this figure, for example, you go

from the Programs menu to the Visual Studio .NET submenu and then to

the command.

If you’ve worked with a web browser such as Internet Explorer before, you’ll

have no trouble navigating among pages in the Visual Studio browser. A

special Web toolbar includes the buttons you can use to go to the previous

or next page, stop a download, refresh a page, or return to the home page.

This toolbar appears only when you are working in the web browser. When

you’re working with other Visual Studio tools, such as the Forms Designer or

Code Editor, the Web toolbar is replaced by other toolbars.

The nine links located on the left side of the Start page let you access other

Visual Studio resources, including a variety of online resources such as

online communities and download libraries. If you are an experienced Visual

Basic 6 programmer, you may want to explore these links now.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 13

Figure 1.5: Start Page

Description

When you develop applications with Visual Studio, you use its Integrated

Development Environment (IDE). The IDE contains all of the tools you

need to develop .NET programs using Visual Basic, C#, or C++.

To start the Visual Studio IDE, click the Start button in the Windows

task

Visual Studio .NET.

The Start page of the IDE has nine links on the left side that lead to a

variety of resources.

The first time you run Visual Studio after installing it, My Profile is

selected rather than Get Started as shown here. After that, Get Started

is selected when you start Visual Studio unless you configure Visual

Studio to display a different page at startup. The My Profile page is

described in figure 1-6.

As you work with Visual Studio, the Start page will be obscured by other

information. But you can return to the Start page at any time by clicking

the Start Page tab that’s located in the upper left portion of the window,

just below the toolbars, or by choosing the Help, Show Start Page

command.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 14

1.8 Customizing Visual Studio for Use with Visual Basic

The My Profile page, shown in figure 1.6, lets you customize the IDE so it

works the way you want it to. You can return to this page at any time to

change your settings by calling up the Start page and clicking the My Profile

link.

The My Profile page lets you select one of several profiles that configure the

Visual Studio environment. For Visual Basic programming, you’ll want to use

the Visual Basic Developer profile. This profile sets up the keyboard

shortcuts and the Visual Studio windows layout to work best with Visual

Basic.

You can also use the My Profile link to customize the way the IDE’s Help

feature works. I recommend you set the Help Filter option to Visual Basic

and Related so that when you access Help, you won’t have to wade through

pages of information on C# or C++. As for the Show Help option, leave it set

to Internal Help.

Finally, you can customize Visual Studio to display something other than the

Start page as its opening page. The other settings for the At Startup option

open the last project you worked on, display the Open Project dialog box so

you can open an existing project, display the New Project dialog box so you

can create a new project, or just start Visual Studio without opening any

page or dialog box.

Note that there are many ways to customize Visual Studio besides the

lets you customize Visual Studio’s toolbars, menus, and keyboard shortcuts

in the same way you can for Microsoft Off

command has literally hundreds of options you can set to customize Visual

Studio. As you become more proficient with Visual Studio, you may want to

explore some of these customization options. But while you’re just getting

started, I recommend you leave them alone.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 15

Figure 1.6: Customizing Visual Studio for use with Visual Basic

Description

The My Profile page lets you configure Visual Studio to work the way

you want. This page appears the first time you use Visual Studio, but

you can return to it at any time by clicking the My Profile link on the Start

Page.

To customize Visual Studio for use with Visual Basic, select Visual Basic

Developer for the Profile setting. The Keyboard Scheme and Window

Layout settings automatically change to Visual Basic 6, and the Toolbox

is displayed on the left side of the window. You’ll see the effects of these

changes in later figures.

If you want to filter the help information so that only information related

to Visual Basic is displayed, select the Visual Basic or Visual Basic and

Related option for the Help Filter setting. You can also change the filter

as you use the Help feature.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 16

By default, help information is displayed as part of the Visual Studio IDE.

To display it separately from the IDE, select the External Help option for

the Show Help setting.

To display something other than the Start page when you start Visual

Studio, select a different option for the At Startup setting. The other

options let you load and display the last solution you worked on, display

the dialog box for opening an existing project or for starting a new

project, or display an empty environment.

1.9 Solutions and Projects in Visual Basic

Before you work with Visual Basic projects, you need to understand the

distinction between a solution and a project. As figure 1.7 explains, a project

is a container that holds Visual Basic source files and other files needed to

create an assembly that can be run by the .NET CLR. A project can contain

several source files, but all of the source files in a project are compiled

together to create a single assembly.

A solution is a container that holds one or more projects. A solution often

contains just a single project. In that case, there’s not much distinction

between a solution and a project.

However, a solution can contain more than one project. Multi-project

solutions are most useful for large applications developed by teams of

programmers. With a multi-project solution, programmers can work

independently on the projects that make up the solution. In fact, the projects

don’t even have to be written in the same language. For example, a solution

can contain two projects, one written in Visual Basic, the other in C#.

How to open or close an existing project

To open a project, click the Open Project button on the Get Started page or

use the File – Open - Project command. Either way, the Open Project dialog

box shown in figure 1.7 is displayed. From this dialog box, you can locate

and open your Visual Basic projects.

You can also open a project you’ve recently worked on directly from the Get

Started page, which was shown in figure 1.5. And you can open recently

used projects by choosing the project you want to open from the Recent

Projects submenu of the File menu.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 17

At this point, you might be confused about whether you should

open projects or solutions. Both are shown in the Open Project dialog

box. In figure 1.7, Financial Calculations.sln is a solution and

FinancialCalculations.vbproj is a Visual Basic project.

In most cases, it doesn’t matter whether you open the solution or the

project. Each way, both the solution and the project files will be opened. If

you open the project, Visual Studio automatically opens the solution that

contains it. And if you open the solution, Visual Studio automatically opens

all of the solution’s projects.

In contrast, you can’t close a project. Instead, you have to close the solution

that contains it. To do that, you use the Close Solution command in the File

menu.

The Open Project dialog box

Figure 1.7: Opening and closing an existing project

Project and solution concepts

Every project has a project file that keeps track of the files that make up

the project and records various settings for the project. Visual Basic

project files have the extension .vbproj. In this figure, the highlighted file

(FinancialCalculations.vbproj) is a project file.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 18

Likewise, every solution has a solution file that keeps track of the

projects that make up the solution. The solution file’s extension is .sln. In

this figure, you can see a solution file named FinancialCalculations.sln

just above the highlighted project file.

When you open a project, Visual Studio automatically opens the solution

that contains the project. And when you open a solution, Visual Studio

automatically opens the projects contained in the solution. So in most

cases, it doesn’t matter whether you open the project or the solution.

Either way, both are opened.

1.10 Working with the IDE

When you open an existing Visual Basic project, you’ll see a screen like the

one in figure 1.8. Here, one or more tabbed windows are displayed in the

main part of the IDE. In this example, the first tab is for the Start page, and

the second tab is for a form named frmInvestment.vb, which is displayed in

the Form Designer window (or just Form Designer). You use this window to

develop the user interface for a form.

Although it isn’t shown in this example, you can also display the code for a

form in the Code Editor window (or just Code Editor). The Code Editor lets

you develop the Visual Basic code for an application. In the next figure, you

can see what this window looks like.

This figure also illustrates some of the other windows that you use as you

develop Visual Basic applications. To add controls to a form, for example,

you use the Toolbox. And to set the properties of a form or control, you use

the Properties window. You’ll learn more about using these windows in the

next chapter. In addition, you can use the Solution Explorer window (or just

Solution Explorer) to manage the files that make up a solution.

This figure also points out two of the toolbars that are available in the IDE.

Like other Windows programs, you can use these toolbars to perform a

variety of operations, and the toolbars change depending on what you’re

doing. Of course, you can also perform any operation by using the menus at

the top of the IDE. And you can perform some operations using the context-

sensitive shortcut menu that’s displayed when you right-click anywhere in

the IDE.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 19

Figure 1.8: Working with the IDE

Description

The main part of the Visual Studio IDE contains one or more tabbed

windows. To develop a form, you use the Form Designer window. And to

develop code, you use the Code Editor window. The Code Editor isn’t

visible in this figure, but is described in figure 1.9.

To add controls and other items to a form, you use the Toolbox. The

Toolbox contains a variety of items organized into categories such as

Data, Components, Windows Forms, and so on. The items you’ll use

most are the controls in the Windows Forms category.

To change the way a form or control looks or operates, you use the

Properties window. This window displays the properties of the item that’s

selected in the Form Designer window.

You use the Solution Explorer window to manage project files. You’ll

learn more about the Solution Explorer in figure 1.10.

At the top of the Visual Studio window are several toolbars. The

Standard toolbar includes standard Windows toolbar buttons such as

Open, Save, Cut, Copy, and Paste. On the right side of the Standard

Visual Basic Unit 1

Sikkim Manipal University Page No.: 20

toolbar, you’ll find several buttons that summon other windows in the

IDE. As you work with Visual Studio, you’ll find that additional toolbars

are occasionally displayed, depending on the function you’re performing.

1.11 The Code Editor Window

The Code Editor window, shown in figure 1.9, lets you create and edit Visual

Basic source code. After you have designed the user interface for your

project by placing controls on the form, you’ll turn to the Code Editor to

develop the Visual Basic statements that make the controls functional. The

easiest way to call up the Code Editor is to double-click a control. Then, you

can begin typing the Visual Basic statements that will be executed when the

user performs the most common action on that control. If you double-click

on a button, for example, you can enter the statements that will be executed

when the user clicks on that button.

The Code Editor works much like other text editors you’ve worked with.

However, the Code Editor has a number of special features that simplify the

task of editing Visual Basic code. For example, color is used to distinguish

Visual Basic keywords from variables, comments, and other language

elements. And many types of coding errors are automatically highlighted as

you type so you can correct them. You’ll learn more about working with the

Code Editor in the next chapter.

Note that the Code Editor and the Form Designer provide two different ways

to work with the same Visual Basic source file. The Code Editor lets you

work directly with the Visual Basic statements that make up your application.

The Form Designer presents a visual representation of the forms and

controls that are implemented by that code.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 21

A project with a Code Editor window displayed

Figure 1.9: Using the Code Editor

Description

The Code Editor window is where you create and edit the Visual Basic

code that your application requires. The Code Editor works much like

any other text editor you have used, so you shouldn’t have much trouble

learning how to use it.

You can display the Code Editor by double-clicking the form or one of

the controls in the Form Designer window. Or, you can click the View

Code button in the Solution Explorer.

Once you’ve opened the Code Editor, you can return to the Form

Designer by clicking the (Design) tab at the top of the Code Editor or the

View Designer button in the Solution Explorer (to the right of the View

Code button). You can also move among these windows by pressing

Ctrl+Tab or Shift+Ctrl+Tab.

It’s important to realize that the Form Designer and the Code Editor do

not represent two different files. Instead, they provide you with two views

of the same Visual Basic source file. The Form Designer gives you a

visual representation of the form that is implemented by your Visual

Basic code. The Code Editor lets you edit the code for the form.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 22

1.12 The Solution Explorer

Figure 1.10 shows the Solution Explorer, which you use to manage the

projects that make up a solution and the files that make up each project. As

you can see, the files in the Solution Explorer are displayed in a tree view

with the files that make up a project subordinate to the project container and

the project container subordinate to the solution container. If a container has

a plus sign next to it, you can click on the plus sign to display its contents.

Conversely, you can hide the contents of a container by clicking on the

minus sign next to it.

You can also use the buttons at the top of the Solution Explorer to work with

the files in a project. To display the code for a form, for example, you can

highlight the form file and then click on the View Code button. And to display

the user interface for a form, you can highlight the form file and then click on

the View Designer button. For a code file, only the View Code button is

available since a code file doesn’t contain a user interface.

To identify the files that make up a project, you can look at the icon that’s

displayed to the left of the file name. The icon for a form file, for example, is

a form, and the icon for a code file is a document and the letters VB. As you

can see, this project consists of three form files and two code files.

Note, however, that all of the files have the file extension vb regardless of

their contents. Because of that, I recommend that you give your files names

that identify their contents. For example, we add the prefix frm to the names

of our form files. That way, it’s easy to identify the form files when you work

with them outside of the Solution Explorer.

The last four files shown in this figure are custom files that we developed for

this project. In contrast, the first file (AssmblyInfo) was added automatically

when this project was created. This file receives information whenever the

project is compiled into an assembly.

This project also includes a folder named References. This folder contains

references to the assemblies that contain the namespaces that are available

to the project. Remember that the namespaces contain the classes that the

application requires. In this case, all of the assemblies were added to the

project automatically when this project was created.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 23

This should give you some idea of how complicated the file structure for a

single project can be. For this relatively simple application, three form files

and one code file were created by the developer. And five namespaces and

an assembly file were added to the project automatically.

Although you can’t see it here, each Visual Basic program you develop also

has access to the Microsoft.VisualBasic namespace. Among other things,

this namespace includes the classes that provide the Visual Basic functions

you can use in your applications. You’ll learn about many of these functions

throughout this book.

The Solution Explorer

Figure 1.10: Using Solution Explorer

Description

You use the Solution Explorer to manage and display the files and

projects in a solution. The Solution Explorer lists all of the projects for

the current solution, as well as all of the files that make up each project.

Plus (+) and minus (-) signs in the Solution Explorer indicate groups of

files. You can click on these signs to expand and collapse the groups.

You can perform most of the functions you need using the buttons at the

top of the Solution Explorer window. The buttons you’ll use most are the

View Code and View Designer buttons, which open the Code Editor and

Form Designer windows, and the View Properties button, which opens

the Properties window.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 24

Project files

Visual Basic source files are stored with the file extension .vb. Each form

you create for a project will have its own form file. You can also create

code files that contain Visual Basic code but do not define a form. The

Solution Explorer uses different icons to distinguish between form files

and code files.

The AssemblyInfo.vb file is created automatically when the project is

created. It contains information about the assembly that’s created when

you compile the project.

The References folder contains references to the assemblies for the

namespaces that the application can use. These namespaces contain

the classes that the project requires. In most cases, all the assemblies

that you need are included when the project is created.

In addition to the assemblies in the References folder, every Visual

Basic application you develop has access to the Microsoft.VisualBasic

assembly.

1.13 Working with Windows in the IDE In figure 1.11, the Toolbox isn’t visible. Instead, it’s hidden at the left side of

the window. Then, when you need the Toolbox, you can move the mouse

pointer over its button to display it. This is just one of the ways that you can

adjust the windows in the IDE so it’s easier to use. This figure also presents

many of the other techniques that you can use.

By default, the Toolbox is displayed as a docked window at the left side of

the application window. To hide it as shown in this figure, you can click on

its Auto Hide button. The Auto Hide button looks like a pushpin, as

illustrated by the button near the upper right corner of the Properties

window. When a docked window is hidden, it appears as a tab at the edge

of the application window.

You can also undock a docked window so it floats in the middle of the IDE.

To do that, you drag it by its title bar away from the edge of the IDE or

double-click on its title bar. In this figure, for example, you can see that the

Solution Explorer window that was docked at the right side of the IDE is now

floating in the middle of the IDE. In addition, the Class View window, which

Visual Basic Unit 1

Sikkim Manipal University Page No.: 25

was grouped with the Solution Explorer window as a tabbed window, has

been separated from the Solution Explorer window. Although we don’t

recommend this arrangement of windows, it should give you a good idea of

the many ways you can arrange them.

As you review the information in this figure, notice that you can’t hide,

separate, or undock the windows in the main area of the IDE. For the most

part, you’ll just move between these windows by clicking on their tabs or by

using one of the other techniques.

If you experiment with these techniques for a few minutes, you’ll see that

they’re easy to master. Then, as you get more comfortable with Visual

Basic, you can adjust the windows so they work best for you.

The IDE with two floating windows and a hidden window

Figure 1.11: Working with the Windows in the IDE

Rearranging Windows

To close a window, click on its Close button. To redisplay it, click on its

button in the Standard toolbar (if one is available) or select it from the

View menu.

To undock a docked window so it floats on the screen, drag it by its title

bar away from the edge of the application window or double-click on its

title bar. To dock a floating window, drag it by its title bar to the edge of

Visual Basic Unit 1

Sikkim Manipal University Page No.: 26

the application window or double-click on its title bar to return it to its

default location.

To hide a docked window, click on its Auto Hide button. Then, the

window is displayed as a tab at the edge of the screen, and you can

display it by placing the mouse pointer over the tab. To change it back,

display it and then click on the Auto Hide button again.

To size a window, place the mouse pointer over an edge or a corner of

the window, and then drag it.

If two or more windows are grouped into tabbed windows, you can

display any window in the group by clicking on its tab. If you dock,

undock, hide, or unhide a tabbed window, all the windows in the group

are docked, undocked, hidden, or unhidden.

To reset the windows to their default arrangement, you can use the

Environment/General settings of the Tools, Options command.

Self Assessment Questions

7. IDE stands for _____.

8. The _____ page lets you customize the IDE so it works the way you

want it to.

9. Visual Basic project files have the extension _____.

1.14 Summary

To develop a Visual Basic .NET application, you use a product called

Visual Studio .NET (pronounced “Visual Studio dot net”).

A Windows Forms application is a typical Windows application that runs

on the user’s PC.

The .NET Framework Class Library consists of segments of pre-written

code called classes that provide many of the functions that you need for

developing .NET applications.

You use the Visual Basic compiler, which is built into Visual Studio, to

compile your Visual Basic source code into Microsoft Intermediate

Language (or MSIL).

The My Profile page lets you select one of several profiles that configure

the Visual Studio environment.

Visual Basic Unit 1

Sikkim Manipal University Page No.: 27

1.15 Terminal Questions

1. Describe the importance and usage of .net framework in Visual Studio.

2. Describe the process of compiling and running a Visual Basic

application

3. Describe the following:

Code Editor Window

Solution Explorer

1.16 Answers

Self Assessment Questions

1. .NET Framework

2. Visual Studio .NET

3. Windows Forms

4. Source files

5. .NET Framework Class Library, Classes

6. Project

7. Integrated Development Environment

8. My Profile

9. .vbproj

Terminal Questions

1. The .NET Framework (pronounced “dot net framework”) defines the

environment that you use to execute Visual Basic .NET applications and

the services you can use within those applications. One of the main

goals of this framework is to make it easier to develop applications that

run over the Internet. However, this framework can also be used to

develop traditional business applications that run on the Windows

desktop. (Refer section 1.2)

2. You use the Visual Basic compiler, which is built into Visual Studio, to

compile your Visual Basic source code into Microsoft Intermediate

Language (or MSIL). For short, this can be referred to as Intermediate

Language (or IL). (Refer section 1.5)

3. The Code Editor window lets you create and edit Visual Basic source

code. After you have designed the user interface for your project by

placing controls on the form, you’ll turn to the Code Editor to develop the

Visual Basic Unit 1

Sikkim Manipal University Page No.: 28

Visual Basic statements that make the controls functional. The easiest

way to call up the Code Editor is to double-click a control. Then, you can

begin typing the Visual Basic statements that will be executed when the

user performs the most common action on that control. If you double-

click on a button, for example, you can enter the statements that will be

executed when the user clicks on that button. (Refer section 1.11)

The Solution Explorer is used to manage the projects that make up a

solution and the files that make up each project. As you can see, the

files in the Solution Explorer are displayed in a tree view with the files

that make up a project subordinate to the project container and the

project container subordinate to the solution container. If a container has

a plus sign next to it, you can click on the plus sign to display its

contents. Conversely, you can hide the contents of a container by

clicking on the minus sign next to it. (Refer section 1.12)

Visual Basic Unit 2

Sikkim Manipal University Page No.: 29

Unit 2 Basic Concepts and Language

Fundamentals Structure:

2.1 Introduction

Objectives

2.2 First Application

2.3 Namespaces in VB.Net

2.4 A More Interactive Hello World Application

2.5 Basic Data Types and Their Mapping to the CTS

(Common Type System)

2.6 Variables

2.7 VB.Net Option Strict and Option Explicit Settings

2.8 Operators in VB.Net

2.9 Constant or Symbols

2.10 Summary

2.11 Terminal Questions

2.12 Answers

2.1 Introduction

This unit is an introduction to the Language fundamentals of Visual

Basic.Net. It explains a sample application along with various components

involved in it. It describes the concept of namespaces in VB.Net. It also

describes the concept of developing Interactive windows based applications.

It explains the variables, data types, constants and Symbols in Visual

basic.Net environment.

Objectives:

After studying this unit, you will be able to:

Introduce the basic concepts of Visual basic.net and its language

features

Demonstrate simple and interactive applications

Describe namespaces in Visual Basic.Net

Describe variables, data types in Visual Basic. Net

Visual Basic Unit 2

Sikkim Manipal University Page No.: 30

2.2 First Application

Start Microsoft Visual Studio.Net and from the menu select File > New >

Project. A "New Project" dialog will now be displayed. Select "Visual Basic

Project" from "Project Type" and select "Console Application" from

"Templates". Type "MyHelloWorldApplication" (without "") in the "Name" text

box below, then click OK.

This will show you the initial default code for your Hello World application.

Change the name of module from Module 1 to "MyHelloWorldApplication"

and type Console.WriteLine("Hello World") inside the Sub Main() functions'

body like whats shown below:

Visual Basic Unit 2

Sikkim Manipal University Page No.: 31

Module MyHelloWorldApplication

Sub Main()

Console.WriteLine("Hello World")

End Sub

End Module

To compile and execute your application, select "Start" from the "Debug"

menu or to run the application without Debug press Ctrl+F5. A new console

window containing the words “Hello World” will now be displayed. Press any

key to terminate the program and close the console window.

Modify the code as below that includes some more VB.NET features:

Imports System

Namespace MyHelloWorldApplication

Module MyHelloWorldModule

Sub Main()

Console.WriteLine("Hello World")

End Sub

End Module

End Namespace

The first line of the above program (Imports System) usually appears in all

VB.Net programs. It gives us access to the core functionality of

programming. The second line (Namespace MyHelloWorldApplication) will

be discussed.

2.3 Namespaces in VB.Net

A namespace is simply a logical collection of related classes in VB.Net. The

application related classes (like those related with database activity for

example) can be bundled in a named collection and hence it is called as a

namespace (e.g., DataActivity).

VB.Net does not allow two classes with the same name to be used in a

program. The sole purpose of using namespaces is to prevent the name

conflict, which may happen if working with a large number of classes. It is

the same case in the Framework Class Library (FCL). For example, it is

highly possible that the Connection Class in DataActivity conflicts with the

Connection Class of InternetActivity. To avoid this, these classes are made

Visual Basic Unit 2

Sikkim Manipal University Page No.: 32

part of their respective namespace. The fully qualified name of these

classes will be DataActivity.Connection and InternetActivity.Connection,

hence resolving any ambiguity for the compiler.

In the second line of the code, there is a declaration classes (enclosed in

Namespace...End Namespace block) which are part of the

MyHelloWorldApplication namespace.

Namespace MyHelloWorldApplication

...

End Namespace

The VB.Net namespaces have no physical mapping. The namespace may

contain modules, classes, interfaces, events, exceptions, delegates and

even other namespaces which are known as "Internal namespace". These

internal namespaces can be defined like this:

Namespace Parent

Namespace Child

...

End Namespace

End Namespace

The Imports Keyword

The first line of the above program is Imports System. The "Imports"

keyword in the code sample above enables us to use classes in the

"System" namespace. For example, It is possible to access the Console

class from the Main(). One point to remember here is that "Imports" allows

access to classes in the referenced namespace only and not in its

internal/child namespaces. Hence it might be needed to write Imports

System.Collections in order to access the classes defined in Collection

namespace which is a sub/internal namespace of the System namespace.

The Module Keyword

A VB.Net program may contain one or more modules. The Main() sub-

procedure usually resides in one of these modules. Modules in VB.Net are a

combination of general data (fields) and general functions (methods) that

are accessible to any code that can access the namespace of a module. All

the members (fields, methods, properties) defined inside a module are

shared by default.

Visual Basic Unit 2

Sikkim Manipal University Page No.: 33

Modules in VB.Net are defined using the Module statement, followed by the

name of the module. The end of a module is marked with the End Module

statement.

Module MyHelloWorldModule

...

End Module

The Main() Sub-Procedure

In the next line, the Main() sub-procedure of our program is defined:

Sub Main()

...

End Sub

This is the standard layout of a Main sub-procedure within a VB.Net module.

The Main() sub-procedure is the entry point of a program,that is, a VB.Net

program starts its execution from the first line in the Main sub-procedure and

exists with the termination of the Main sub-procedure. We can also define

the Main method inside a class as in the example given below.

Imports System

Namespace MyHelloWorldApplication

Class MyHelloWorldClass

Public Shared Sub Main()

Console.WriteLine("Hello World")

End Sub

End Class

End Namespace

The main sub-procedure is designated as "Shared" as it can be called by

the Common Language Runtime (CLR) without creating any objects from

our MyHelloWorldClass (this is the definition of Shared methods, fields and

properties). The sub-procedure is also declared as "Public" so that classes

outside its namespace and assembly may call this method. Main is the

(standard) name of this method. More evidence of this shall be shown later.

One interesting point is that it is legitimate to have multiple Main() methods

Visual Basic Unit 2

Sikkim Manipal University Page No.: 34

in VB.Net program. However, you have to explicitly identify which Main

method is the entry point for the program.

Printing on the Console

The next line of code prints "Hello World" on the Console screen:

Console.WriteLine("Hello World")

In the code, WriteLine() is called. It is a "Shared" method of the Console

class that is defined in the System namespace. This method takes a string

(enclosed in double quotes) as its parameter and prints it on the Console

window.

VB.Net, like other Object Oriented languages, uses the dot (.) operator to

access the member variables (fields) and methods of a class. Also,

parentheses () are used to identify methods in the code. String literals are

enclosed in double quotation marks ("). Lastly, it must be noted that VB.Net

is a case-insensitive language; hence Console and conSole are the same

words (identifiers) in VB.Net.

Comments

Comments are created by programmers who wish to explain the code.

Comments are ignored by the compiler and are not included in the

executable code. VB.Net uses similar syntax for comments as used in VB

and assembly language. The text following a single quotation mark (' any

comment) is a line comment. The ending is the end of the line.

„This is the main method

Public Shared Sub Main()

Console.WriteLine("Hello World") ' It will print Hello World

End Sub

Important points to remember

VB.Net executable program resides in a class or module.

The entry point to a program is the Shared sub-procedure Main()

VB.Net is not a case sensitive language so SMU and Smu mean the

same thing.

Horizontal whitespaces (tabs and spaces) are ignored by the compiler

between the code. Hence, the following is also a valid declaration of the

Main() method (although not recommended):

Visual Basic Unit 2

Sikkim Manipal University Page No.: 35

Public Shared Sub Main ()

Console.WriteLine (“Hello World”)

End Sub

VB.Net programs need not be saved with the same file name as that of

the class or module containing the Main() method.

There can be multiple Main() methods in a program, but it has to be

specified which one is the entry point.

The boundaries of a namespace, class, module and method are defined

by their respective statements and closed with an End statement.

A namespace is only a logical collection of classes with no physical

mapping on disk.

The "Imports" keyword is used to inform the compiler where to look for

the definition of the classes (namespaces) that is to be used.

Comments are ignored by the VB.Net compiler and are used only to

enhance the readability and understandability of the program for

developers only.

Enclosing your classes or modules in a namespace is optional. It is

possible to write a program where any classes or modules are not

enclosed in a namespace

It is not mandatory that the Main method of a program does not take any

argument. It may take arguments, such as:

Public Sub Main(ByVal CmdArgs() As String)

Console.WriteLine("Hello World")

End Sub

Self Assessment Questions

1. A namespace is simply a logical collection of related _____ in VB.Net.

2. The sole purpose of using _____ is to prevent the name conflict, which

may happen if working with a large number of classes.

3. _____ are ignored by the compiler and are not included in the

executable code.

2.4 A More Interactive Hello World Application

Up to this point we have seen a very static Hello World application that

greets the whole world when it is executed. Let us now make a more

Visual Basic Unit 2

Sikkim Manipal University Page No.: 36

interactive hello world that greets its current user. This program will ask the

user's name and will greet them using their name, like 'Hello Ram', when the

user named „Ram‟ runs it. Consider the following code:

Module MyHelloWorldModule

Sub Main()

Console.Write("Please, write your good name: ") 'line 1

Dim name As String = Console.ReadLine() 'line 2

Console.WriteLine("Hello {0}, Good Luck in VB.Net", name) 'line 3

End Sub

End Module

In the first line of Main, there is another method, Write(), which is a part of

the Console class. This is similar to the WriteLine() method discussed in the

previous program, but the cursor does not move to a new line after printing

the string on the console.

In the second line, there is a declared String variable named "name". Then,

a line of input is taken from the user through the ReadLine() method of the

Console class. The result is stored in the "name" variable. The variables are

placeholders (in memory) for storing data temporarily during the execution

of the program. Variables can hold different types of data depending on their

data-type, for example an integer variable can store an integer (number with

no decimal places), while a string variable can store a string (a series) of

characters. The ReadLine() method of the Console class (contrary to

WriteLine()) reads a line of input typed at the Console Window. It returns

this input as a string, in which the "name" variable is stored.

The third line prints the name given by the user at second line along with a

greeting text. Once again, the WriteLine() method of the Console Class is

used. The substitution parameter {0} is used to specify the position in the

line of text where the data from the variable "name" should be written after

the WriteLine() method is called.

Console.WriteLine("Hello {0}, Good Luck in VB.Net", name);

When the compiler finds a substitution parameter {n} it replaces it with the

(n+1) variables following the string in double quotation marks separated by

comma. Hence, when the compiler finds {0}, it replaces it with (0+1), that is,

Visual Basic Unit 2

Sikkim Manipal University Page No.: 37

1st variable "name" following the double quotes separated by comma. At

run-time, the CLR will read it as:

Console.WriteLine("Hello Ram, Good Luck in VB.Net");

if the value of the variable "name" is "Ram" at run-time.

Alternatively, it can also be written as

Console.WriteLine("Hello " + name + ", Good Luck in VB.Net");

without the substitution parameter altogether. Here we concatenate (add)

the strings together to form a message. (The first approach is similar to C's

printf() function while the second is similar to Java's System.out.println()

method)

When we compile and run this program the output will be as follows:

"Please, write your good name: Ram Hello Ram, Good Luck in VB.Net"

2.5 Basic Data Types and Their Mapping to the CTS (Common

Type System)

There are two kinds of data types in VB.Net

1. Value type (implicit data types, Structure and Enumeration)

2. Reference Type (objects, delegates)

Value types are passed to methods by passing an exact copy while

Reference types are passed to methods by passing only their reference

(handle). Implicit data types are defined in the language core by the

language vendor, while explicit data types are types that are made by using

or composing implicit data types.

As seen in the first unit, implicit data types in .net compliant languages are

mapped to types in Common Type System (CTS) and CLS (Common

Language Specification). Hence, each implicit data type in VB.Net has its

corresponding .Net type. The implicit data types in VB.Net are:

Visual Basic Unit 2

Sikkim Manipal University Page No.: 38

VB.Net type Corresponding

.Net type

Size in

bytes Description

Boolean Boolean 1 Contains either True or False

Char Char 2

Contains any single Unicode

character enclosed in double

quotation marks followed by a

c, for example "x"c

Integral types

Byte Byte 1 May contain integers from

0-255

Short Int16 2 Ranges from -32,768 to 32,767

Integer(defau

lt) Int32 4

Ranges from -2,147,483,648 to

2,147,483,647

Long Int64 8

Ranges from -

9,223,372,036,854,775,808 to

9,223,372,036,854,775,807.

Floating point types

Single Single 4

Ranges from ±1.5 × 10-45 to

±3.4 × 1038 with 7 digits

precision. Requires the suffix 'f'

or 'F'

Double(defau

lt) Double 8

Ranges from ±5.0 × 10-324 to

±1.7 × 10308 with 15-16 digits

precision.

Decimal Decimal 12

Ranges from 1.0 × 10-28 to

7.9 × 1028 with 28-29 digits

precision. Requires the suffix

'm' or 'M'

Implicit data types are represented in language using 'keywords'; so each of

above is a keyword in VB.Net (Keyword are the words defined by the

language and can not be used as identifiers). It is worth-noting that string is

also an implicit data type in VB.Net, so String is a keyword in VB.Net. Last

point about implicit data types is that they are value types and thus stored at

the stack, while user defined types or referenced types are stored at heap.

Stack is a data structure that store items in last in first out (LIFO) fashion. It

Visual Basic Unit 2

Sikkim Manipal University Page No.: 39

is an area of memory supported by the processor and its size is determined

at the compile time. Heap is the total memory available at run time.

Reference types are allocated at heap dynamically (during the execution of

program). Garbage collector searches for non-referenced data in heap

during the execution of program and returns that space to Operating

System.

2.6 Variables

During the execution of program, data is temporarily stored in memory. A

variable is the name given to a memory location holding particular type of

data. So, each variable has associated with it a data type and value. In

VB.Net, a variable is declared as:

Dim <variable> as <data type>

Example:

Dim i As Integer

The above line will reserve an area of 4 bytes in memory to store integer

type values, which will be referred in the rest of program by identifier 'i'. You

can initialize the variable as you declare it (on the fly) and can also

declare/initialize multiple variables of same type in a single statement.

Examples:

Dim isReady As Boolean = True

Dim percentage = 87.88, average = 43.9 As Single

Dim digit As Char = "7"c

Self Assessment Questions

4. _____ can hold different types of data depending on their data-type.

5. _____ types are passed to methods by passing an exact copy while

_____ types are passed to methods by passing only their reference.

6. During the execution of program, data is temporarily stored in _____.

2.7 VB.Net Option Strict and Option Explicit Settings

There are two 'bad' features in VB.Net, which are inherent from earlier

versions (VB5 and VB6):

You can declare a variable without specifying its type. VB.Net, in this

case, assumes the type of the variable as System.Object class.

Visual Basic Unit 2

Sikkim Manipal University Page No.: 40

You can convert values (or objects) to incompatible types, for example

String to Integer.

The use of these two features results in quite a number of bugs and makes

the overall design of application bad, complex and difficult to follow. With

incompatible type conversion, the program does compile without any error

but throws a runtime error (exception). But these two features can be turned

off by using the Option Explicit and Option Strict statements.

Option Explicit Statement

Option Explicit, when turned on, does not allow the use of any variable

without proper declaration. There are two methods to apply the Option

Explicit Statement.

To apply the Option Explicit settings to the complete project in Visual

Studio.Net, right click the project name in the solution explorer and

select Properties. It will open the Property Pages window. Now in the

Common Properties tree at left, select Build, it will show the following

window:

From here, you can turn the Option Explicit (as well as Option Strict) on or

off.

To apply the Option Explicit settings to the current file, use the Option

Explicit statement before any statement as, Option Explicit On.

Visual Basic Unit 2

Sikkim Manipal University Page No.: 41

When Option Explicit is on, it will cause the compile time error to write

myName = "Ram" ' compile time error with Option Explicit On

Rather, it has to be written as,

Dim myName As String = "Ram"

Option Strict Statement

When the Option Strict statement is turned on, incompatible type conversion

are not allowed. Option Strict can be turned on or off in the similar fashion

as Option Explicit. You can either use Option Strict Statement as Option

Strict On or you can set it from the project properties. When Option Strict is

On, the following program will cause a compile time error

Sub Main()

Dim strNum As String = "1"

Dim intNum As Integer = strNum

Console.WriteLine(intNum)

End Sub

But if the Option Strict is turned off, the above program will actually compile

and run without error to print 1 on the Console.

It is important to remember that Option Strict also does not allow using un-

declared types and hence there is no use turning the Option Explicit on if

you are already using Option Strict. It is strongly advised to turn on Option

Explicit and Option Strict. Throughout the book, it is assumed that the

Option Strict is turned On.

2.8 Operators in VB.Net

Arithmetic Operators

Several common arithmetic operators are allowed in VB.Net given in the

following table:

Arithmetic Operator Meaning

+ Add

- Subtract

* Multiply

/ Divide

Mod Remainder or modulo

Visual Basic Unit 2

Sikkim Manipal University Page No.: 42

The program below uses these operators

Imports System

Module ArithmeticOperators

' The program shows the use of arithmetic operators

' + - * / Mod

Sub Main()

' result of addition, subtraction, multiplication and modulus operator

Dim sum, difference, product, modulo As Integer

sum = 0

difference = 0

product = 0

modulo = 0

Dim quotient As Double = 0 ' result of division

Dim num1 As Integer = 10 ' operand variables

Dim num2 As Integer = 2

sum = num1 + num2

difference = num1 - num2

product = num1 * num2

quotient = num1 / num2

modulo = 3 Mod num2 ' remainder of 3/2

Console.WriteLine("num1 = {0}, num2 = {1}", num1, num2)

Console.WriteLine()

Console.WriteLine("Sum of {0} and {1} is {2}", num1, num2, sum)

Console.WriteLine("Difference of {0} and {1} is {2}", num1, num2,

difference)

Console.WriteLine("Product of {0} and {1} is {2}", num1, num2,

product)

Console.WriteLine("Quotient of {0} and {1} is {2}", num1, num2,

quotient)

Console.WriteLine()

Console.WriteLine("Remainder when 3 is divided by {0} is {1}",

num2, modulo)

End Sub

End Module

Visual Basic Unit 2

Sikkim Manipal University Page No.: 43

Assignment Operators

Assignment operators are used to assign values to variables. Common

assignment operators in VB.Net are:

Assignment Operator Meaning

= Simple assignment

+= Additive assignment

-= Subtractive assignment

*= Multiplicative assignment

/= Division assignment

The Equal operator is used to assign a value to a variable or a reference.

For example, the instruction,

Dim isPaid As Boolean = false

assigns the value 'False' to the isPaid variable of Boolean type. The Left and

right hand side of the equal or any other assignment operator must be

compatible otherwise the compiler will complain of a syntax error.

Sometimes casting is used for type conversion, e.g., to convert and store

values in a variable of type Double to a variable of type Integer. We need to

apply integer cast using VB.Net's CType() built-in method.

Dim doubleValue As Double = 4.67

Dim intValue As Integer = CType(doubleValue, Integer)' intValue

would be equal to 4

The method CType() is used for compatible type conversions. It takes two

arguments; the first being the source variable to convert to, while the second

argument is the target type of conversion. Hence, the above call to the

method CType() will convert the value in the variable 'doubleValue' of type

Double to a variable of type Integer and will return the converted Integer

type value that will be stored in the Integer variable 'intValue'.

Of course, with narrow casting (from bigger type to smaller type) there is

always a danger of some loss of precision; as in the case above, we only

got 4 of the original 4.67. Sometimes, the casting may result in a runtime

error.

Visual Basic Unit 2

Sikkim Manipal University Page No.: 44

Dim intValue As Integer = 32800

Dim shortValue As Short = CType(intValue, Short)

When the second of these lines is run an error will be given, stating that

"Arithmetic operation resulted in an overflow." Why is it so? Variables of

type Short can only take a maximum value of 32767. The cast above cannot

assign 32800 to a shortValue. This is detected at runtime and an error is

given.

If you try to do an invalid cast of incompatible types like below

Dim strValue As String = "Ram"

Dim intValue As Integer = CType(strValue, Integer)

Then again it will get compiled but will crash the program at runtime.

Relational Operators

Relational operators are used for comparison purposes in conditional

statements. The common relational operators in VB.Net are:

Relational Operator Meaning

= Equality check

<> Un-equality check

> Greater than

< Less than

<= Less than or equal to

>= Greater than or equal to

Relational operators always result in a Boolean statement; either True or

False. For example if we have two variables

Dim num1 = 5, num2 = 6 As Integer

then,

num1 = num2 will result in false

num1 <> num2 will result in true

num1 > num2 will result in false

num1 < num2 will result in true

num1 <= num2 will result in true

num1 >= num2 will result in false

Visual Basic Unit 2

Sikkim Manipal University Page No.: 45

Only compatible data types can be compared. It is invalid to compare a

Boolean with an Integer, if

Dim i = 1 As Integer

Dim b = True As Boolean

then it is a syntax error to compare i and b for equality (i=b)

Logical and Bitwise Operators

These operators are used for logical and bitwise calculations. The common

logical and bitwise operators in VB.NET are:

Logical and Bitwise Operators Meaning

AND bitwise AND

OR bitwise OR

XOR bitwise XOR

NOT bitwise NOT

ANDALSO (Logical or short circuit AND)

OrElse

(Logical or short circuit OR)

The operators And, Or and Xor are rarely used in usual programming

practice. The Not operator is used to negate a Boolean or bitwise

expression like:

Dim b = False As Boolean

Dim bb As Boolean = Not b ' bb would be true

Logical Operators And, Or, AndAlso and OrElse are also used to combine

comparisons like

Dim i=6, j=12 As Integer

Dim firstVar As Boolean = i>3 And j < 10 ' firstVar would be false

Dim secondVar As Boolean = i>3 Or j < 10 ' secondVar would be true.

In the first comparison case: i>3 And j<10 will result in true only if both the

conditions i>3 and j<10 result in true. While in the second comparison: i>3

Or j<10 will result in true if any of the conditions i>3 and j<10 result in true.

You can of course use the combination of And, Or, AndAlso and OrElse in a

single statement like:

bool firstVar = (i>3 And j<10) OrElse (i<7 And j>10) 'firstVar would be

true

Visual Basic Unit 2

Sikkim Manipal University Page No.: 46

In the above statement, conditional expressions are grouped to avoid any

ambiguity.

You can also use And and Or operators in place of AndAlso and OrElse

respectively; but for combining conditional expressions, AndAlso and OrElse

are more efficient as they use "short circuit evaluation", i.e., if in (i>3

AndAlso j<10) expression, i>3 evaluates to false, it would not check the

second expression j<10 and will return false (as in AND, if one of the

participant operand is false, the whole operation will result in false). Hence,

one should be very careful to use assignment expressions with AndAlso and

OrElse operators. The And and Or operators don't do short circuit evaluation

and do execute all the comparisons before returning the result.

Operator Precedence

When several operations occur in an expression, each part is evaluated and

resolved in a predetermined order called operator precedence.

Precedence Rules

o When expressions contain operators from more than one category,

they are evaluated according to the following rules:

o The arithmetic and concatenation operators have the order of

precedence described in the following section, and all have greater

precedence than the comparison, logical, and bitwise operators.

o All comparison operators have equal precedence, and all have

greater precedence than the logical and bitwise operators, but lower

precedence than the arithmetic and concatenation operators.

o The logical and bitwise operators have the order of precedence

described in the following section, and all have lower precedence

than the arithmetic, concatenation, and comparison operators.

o Operators with equal precedence are evaluated left to right in the

order in which they appear in the expression.

Precedence Order

Operators are evaluated in the following order of precedence:

Arithmetic and Concatenation Operators

Exponentiation (^)

Unary identity and negation (+, –)

Multiplication and floating-point division (*, /)

Visual Basic Unit 2

Sikkim Manipal University Page No.: 47

Integer division (\)

Modulus arithmetic (Mod)

Addition and subtraction (+, –), string concatenation (+)

String concatenation (&)

Arithmetic bit shift (<<, >>)

Comparison Operators

All comparison operators (=, <>, <, <=, >, >=, Is, IsNot, Like, TypeOf...Is)

Logical and Bitwise Operators

Negation (Not)

Conjunction (And, AndAlso)

Inclusive disjunction (Or, OrElse)

Exclusive disjunction (Xor)

Comments

The = operator is only the equality comparison operator, not the assignment

operator.

The string concatenation operator (&) is not an arithmetic operator, but in

precedence it is grouped with the arithmetic operators.

The Is and IsNot operators are object reference comparison operators.

They do not compare the values of two objects; they check only to

determine whether two object variables refer to the same object instance.

Associativity

When operators of equal precedence appear together in an expression, for

example multiplication and division, the compiler evaluates each operation

as it encounters it from left to right. The following example illustrates this.

Dim n1 As Integer = 96 / 8 / 4

Dim n2 As Integer = (96 / 8) / 4

Dim n3 As Integer = 96 / (8 / 4)

The first expression evaluates the division 96 / 8 (which results in 12) and

then the division 12 / 4, which results in three. Because the compiler

evaluates the operations for n1 from left to right, the evaluation is the same

when that order is explicitly indicated for n2. Both n1 and n2 have a result of

three. By contrast, n3 has a result of 48, because the parentheses force the

compiler to evaluate 8 / 4 first.

Visual Basic Unit 2

Sikkim Manipal University Page No.: 48

Because of this behavior, operators are said to be left associative in Visual

Basic.

Overriding Precedence and Associativity

You can use parentheses to force some parts of an expression to be

evaluated before others. This can override both the order of precedence and

the left associativity. Visual Basic always performs operations that are

enclosed in parentheses before those outside. However, within

parentheses, it maintains ordinary precedence and associativity, unless you

use parentheses within the parentheses. The following example illustrates

this.

Dim a, b, c, d, e, f, g As Double

a = 8.0

b = 3.0

c = 4.0

d = 2.0

e = 1.0

f = a – b + c / d * e

'The preceding line sets f to 7.0. Because of natural operator precedence

and „associativity, it is exactly equivalent to the following line.

f = (a – b) + ((c / d) * e)

'The following line overrides the natural operator precedence and left

associativity.

g = (a – (b + c)) / (d * e)

' The preceding line sets g to 0.5.

2.9 Constant or Symbols

Constants values once defined cannot be changed in the program.

Constants are declared using Const keyword, like:

Dim Const PI As Double = 3.142

Constants must be initialized as they are declared.

Dim Const MARKS As Integer

It is a notation convention to use capital letters while naming constants.

Visual Basic Unit 2

Sikkim Manipal University Page No.: 49

Self Assessment Questions

7. _____, when turned on, does not allow the use of any variable without

proper declaration.

8. _____ operators are used to assign values to variables.

9. You can use _____ to force some parts of an expression to be

evaluated before others.

2.10 Summary

A namespace is simply a logical collection of related classes in VB.Net.

VB.Net does not allow two classes with the same name to be used in a

program. The sole purpose of using namespaces is to prevent the name

conflict, which may happen if working with a large number of classes.

Value types are passed to methods by passing an exact copy while

Reference types are passed to methods by passing only their reference

(handle).

A variable is the name given to a memory location holding particular type

of data.

You can use parentheses to force some parts of an expression to be

evaluated before others.

Constants values once defined cannot be changed in the program.

2.11 Terminal Questions

1. What do you mean by namespaces? Explain.

2. Explain various basic data types and variables in Visual Basic.

3. Describe various kinds of operators in Visual Basic .NET.

2.12 Answers

1. A namespace is simply a logical collection of related classes in VB.Net.

The application related classes (like those related with database activity

for example) can be bundled in a named collection and hence it is called

as a namespace (e.g., DataActivity). (Refer Section 2.3)

2. There are two kinds of data types in VB.Net.

Value type (implicit data types, Structure and Enumeration)

Reference Type (objects, delegates) (Refer Sections 2.5 & 2.6)

3. Visual Basic .NET contains various kinds of operators such as arithmetic

operators, relational operators, logical operators etc. (Refer Section 2.8)

Visual Basic Unit 3

Sikkim Manipal University Page No.: 50

Unit 3 Flow Control Statements

Structure:

3.1 Introduction

Objectives

3.2 If…Then…Else Statement

3.3 Select…Case Statement

3.4 Loops in VB.Net

3.5 Arrays in VB.Net

3.6 Summary

3.7 Terminal Questions

3.8 Answers

3.1 Introduction

This unit introduces the reader to flow control statements in Visual basic.Net

like If…Then…Else. It demonstrates the concepts of Arrays and Loops in

VB.Net.

Objectives:

After studying this unit, you should be able to:

explain the usage of control statements

describe various flow control statements

describe the applications of Loops and Arrays in Visual Basic.Net.

3.2 If…Then… Else statement

Condition checking has always been the most basic and important construct

in any language. VB.Net provides conditional statements in the form of the

If...Then...Else statement. The structure of this statement is:

If Boolean expression Then

Statement or block of statement

Else

Statement or block of statement

End If

Visual Basic Unit 3

Sikkim Manipal University Page No.: 51

The Else clause above is optional. The typical example is

If i=100 Then

Console.WriteLine("You Reached Hundred")

End If

In the above example, the console message will be printed only if the

expression i=5 evaluates to True. If action is needed in the case when the

condition does not evaluate to true you can use the Else clause.

If i=100 Then

Console.WriteLine("You Reached Hundred")

Else

Console.WriteLine("Still you are not reached Hundred”)

End If

Only the first message will be printed in the case of i being 100. In any other

case (when i is not 100), the second message will be printed. You can also

use a block of statements (more than one statement) under any If and Else.

If i=100 Then

j = i*5

Console.WriteLine("Reached Hundred")

Else

j = i/5

Console.WriteLine("Still not Reached Hundred")

End If

If... Then or If... Then... Else may be written in the same line. For examples,

1. If i=100 Then Console.WriteLine("Reached Hundred")

2. If i=100 Then j = i*5 Else j = i/5

As you might have picked from the above two statements, when an If...

Then and If...Then...Else are used on the same line, we do not need to write

an End If. The reason is quite simple; End is used to mark the end of a block

in VB.Net. With these two statements, we do not create or use any blocks of

statements.

It is always recommended to use If...Then and If...Then...Else statements in

block format with End If. It increases the readability and prevents many bugs

that otherwise can be produced in the code.

Visual Basic Unit 3

Sikkim Manipal University Page No.: 52

You can also have an If after an Else for further conditioning

If i>5 Then ' line 1

If i=6 Then ' line 2

Console.WriteLine("Ok, 6 is also closer to 5")

Else ' line 4

Console.WriteLine("Oops! i is greater than 5 but not 6")

End If

Console.WriteLine("Thanks God, i finally becomes greater than 5")

Else ' line 8

Console.WriteLine("Missed...When will i become 5 or closed to 5?")

End If

ElseIf i=6 is executed only if the first condition i=5 is false. An Else at line 5

will be executed only if the second condition i=6 (line 3) executes and fails

(that is both the first and second condition fails). The point being is that Else

at line 5 is related to the If on line 3.

As If...Then...Else is also an statement, you can use it under other

If...Then...Else statements, like:

If i>5 Then ' line 1

If i=6 Then ' line 2

Console.WriteLine("Ok, 6 is also closer to 5")

Else ' line 4

Console.WriteLine("Oops! i is greater than 5 but not 6")

End If

Console.WriteLine("Thanks God, i finally becomes greater than 5")

Else ' line 8

Console.WriteLine("Missed...When will i become 5 or closed to 5?")

End If

The Else on line 4 is clearly related to the If...Then on line 2 while the Else

on line 8 belongs to the If on line 1. Finally, do note (VB6 and C/C++

programmers especially) that the If statement expects only Boolean

expression and not an Integer value. It is indeed an error to write as

Dim flag As Integer = 0

If flag Then

' do something...

End If

Visual Basic Unit 3

Sikkim Manipal University Page No.: 53

Instead, it can be written as either

Dim flag As Integer = 0

If flag = 1 Then ' note ==

' do something…

End If

or,

Dim flag As Boolean = False

If flag Then ' Boolean expression

' do something...

End If

3.3 Select…Case statement

If you need to perform a series of specific checks, Select...Case is present

in VB.Net and is just the ticket for this. The general structure of

Select...Case statement is as follows:

Select <any implicit data type expression> Case expression statements ' some other case blocks ... Case Else statements End Select

It takes much less time to use the Select...Case than using several

If...Then...ElseIf statements. The following example illustrates the usage of

Select…Case statement.

Imports System

' To execute the program write "SwitchCaseExample 2" or any other

number at

„ command line, if the name of .exe file is "SwitchCaseExample.exe"

Module ArithmeticOperators

' Demonstrates the use of switch...case statement along with

' the use of command line argument

Sub Main(ByVal userInput() As String)

' convert the string input to integer

„Will through run-time exception if there is no input

„at run-time or input is not castable to integer

Visual Basic Unit 3

Sikkim Manipal University Page No.: 54

Dim input As Integer = Integer.Parse(userInput(0))

Select Case input ' what is input?

Case 1 ' if it is 1

Console.WriteLine("You typed 1 (one) as first command line

argument")

Case 2 ' if it is 2

Console.WriteLine("You typed 2 (two) as first command line

argument")

Case 3 To 5 ' if it is 3

Console.WriteLine("You typed number from 3 (three) to

five (five) as first command line argument")

Case Else ' if it is not of the above

Console.WriteLine("You typed other than 1, 2, 3, 4 and 5")

End Select

End Sub

End Module

An integer must be supplied for the command line argument. Firstly, compile

the program (at command line or in Visual Studio.Net). Suppose we made

an exe with name "SelectCaseExample.exe". Now, run it at the command

line as given below:

C:\> SelectCaseExample 2

You typed 2 (two) as command line argument

or,

C:> SelectCaseExample 4

You typed number from 3 (three) to five (five) as first command line

argument

or,

C:> SelectCaseExample 7

You typed other than 1, 2, 3, 4 and 5

If you did not enter any command line argument or give a non-integer

argument, the program will raise an exception.

Unhandled Exception: System.IndexOutOfRangeException: Index was

outside the bounds of the array.

Visual Basic Unit 3

Sikkim Manipal University Page No.: 55

At SelectCaseExample.ArithmeticOperators.Main(String[] userInput) in

C:\Documents and Settings\Ramr.First\My Documents\Visual Studio

Projects\VBDotNe tSchoolLesson3\Module1.vb:line 14

Let us come to the internal workings. We converted the first command line

argument (userInput(0)) into an Integer variable input. For conversion, we

used static Parse() method of the Integer data type. This method takes a

String and returns an equivalent integer or raises an exception if the

conversion can‟t be completed. Next we checked the value of input variable

using switch the statement.

Select Case input

...

End Select

Later on the basis of the input values, we took specific actions under the

respective case statements. Case 1 ' if it is 1 Console.WriteLine("You typed

1 (one) as the first command line argument")

We can also specify a range in the Case Expression to match

Case 3 To 5 ' if it is 3

Console.WriteLine("You typed number from 3 (three)

to five (five) as first command line argument")

If all the specific checks fail (input is neither 1,2,3,4 or 5), the statements

under “Case Else” will execute.

Case Else ' if it is not of the above

Console.WriteLine("You typed other than 1, 2, 3, 4 and 5")

There are some important points to remember when using switch…case

statement in VB.Net

You can use any implicit data type in the Select statement.

You can use multiple statements under a single case statement as

follows

Case "Pakistan"

continent = "Asia"

Console.WriteLine("Pakistan is an Asian Country")

Case Else

continent = "Un-recognized"

Console.WriteLine("Un-recognized country discovered")

Visual Basic Unit 3

Sikkim Manipal University Page No.: 56

Statements under Case Else will only be executed if and only if all Case

checks fail.

You can't have more than one Case Else block in a single Select

statement.

Self Assessment Questions

1. VB.Net provides conditional statements in the form of _____ statement.

2. If you need to perform a series of specific checks, then _____ statement

can be used.

3. Statements under Case Else will only be executed if and only if all Case

checks _____.

3.4 Loops in VB.Net

Loops are used for iteration purposes, that is, performing a task multiple

times (usually until a termination condition is met)

(i) For…Next Loop

The most common type of loop in VB.Net is the For...Next loop. The basic

structure of the For...Next loop is exactly the same as in VB6 and is given

below:

For variable = startingValue To lastValue

statement or block of statements

Next

Let us see a For...Next loop that will write integers from 1 to 10 on the

console.

Dim i As Integer

For i = 1 to 10

Console.WriteLine("In the loop, value of i is " & i)

Next

At the start, an integer variable i is initialized with the value of 1, then the

statements under the For are executed until the value of i does not equal 10.

Each time i is incremented by 1.

The important points about For loop are:

You can use an Exit For statement in a For...Next loop or any other loop

to change the normal execution flow.

Visual Basic Unit 3

Sikkim Manipal University Page No.: 57

An Exit For statement terminates the loop and transfers the execution

point outside the for loop as below:

For i=1 to 10

If i>5 Then

Exit For

End If

Console.WriteLine("In the loop, value of i is {0}.", i)

Next

The loop will terminate once the value of i gets greater than 5. If some

statements are present after Exit For, it should be enclosed under some

conditions. Otherwise the lines following the break point will not execute.

For i = 1 To 10

Exit For

Console.WriteLine()

Next

You can define the increment/decrement (change) in each iteration of a

For...Next Loop using the Step statement. The code below will increment by

2 in the value of i in each cycle of the loop.

For i = 1 To 10 Step 2

Console.WriteLine("Value of i is {0}", i)

Next

The following is the output on the Console,

Value of i is 1

Value of i is 3

Value of i is 5

Value of i is 7

Value of i is 9

Press any key to continue

Note that the increment starts after the first iteration. You can also specify

the negative increment (that is, decrement) in a Step. The following code will

output Integers from 10 to 1.

Value of i is 10

Value of i is 9

Visual Basic Unit 3

Sikkim Manipal University Page No.: 58

Value of i is 8

Value of i is 7

Value of i is 6

Value of i is 5

Value of i is 4

Value of i is 3

Value of i is 2

Value of i is 1

Press any key to continue

(ii) Do While… Loop

The general structure of the Do While...Loop is

Do While Boolean expression

Statement or block of statements

Loop

The statements under Do While will run continuously as long as the Boolean

expression evaluates to true. The similar code for printing integers 1 to 10

on Console using the Do While...Loop is

Dim i As Integer =1

Do While i<=10

Console.WriteLine("In the loop, value of i is " & i)

i = i + 1

Loop

(iii) Do… Loop While

A Do...Loop While is similar to a Do While...Loop, except that it does not

check the condition before entering the first iteration (execution of code

inside the body of loop). The general form of Do...Loop While is:

Do

statement or block of statements

Loop While Boolean expression

The statements under the Do will be executed first and then the Boolean

condition is checked. The loop will continue until the condition remains true.

The code which prints integers 1 to 10 on console using Do...Loop While is

Visual Basic Unit 3

Sikkim Manipal University Page No.: 59

Dim i As Integer = 1

Do

Console.WriteLine("In the loop, value of i is " & i)

i = i + 1

Loop While i<=10

The important point is that the statements in a Do...Loop While execute at

least once.

(iv) Do… Loop Until

A Do...Loop Until is similar to the Do...Loop While, except that it continues to

execute the containing statements until the condition against the Until part

evaluates to True or the condition against the Until remains False. The

general form of the Do...Loop Until is as follows:

Do

statement or block of statements

Loop Until Boolean expression

The statements under the Do will execute first and then the condition is

checked. The loop will continue until the condition remains false. The

following code will print integers from 1 to 10 on console using the Do...Loop

Until.

Dim i As Integer = 1

Do

Console.WriteLine("In the loop, value of i is " & i)

i = i + 1

Loop Until i=10

Again the statements in Do...Loop Until execute at least once.

(v) The For Each Loop

There is another type of loop that is very simple and useful to iterate through

arrays and other collections. This is a For Each loop. The basic structure of

the For Each loop is

For Each <identifier> in <array or collection>

<statements or block of statements>

End For

Visual Basic Unit 3

Sikkim Manipal University Page No.: 60

The following example illustrates the working of For Each loop.

' demonstrates the use of arrays in VB.Net

Public Sub Main()

' declaring and initializing an array of type integer

Dim myIntegers() As Integer = New Integer() {3, 7, 2, 14, 65}

' iterating through the array and printing each element

Dim i As Integer

For Each i in myIntegers

Console.WriteLine(i)

Next

End Sub

We declared the variable 'i' to hold individual values of the array 'myIntegers'

in each iteration. It is necessary to specify the type of variable 'i' same as

the type of elements in the collection (Integer in our case).

Important points to be noted are:

Variables are used to hold individual elements of an array in each iteration

(i in the above example) are read-only. You can't change the elements of an

array through it, you can only read it. This means For Each only allows you

to iterate through the array or collection and not to change the contents of it.

If you wish to perform some work on array elements such as to change the

individual elements, you should use the For...Next loop.

For Each can be used to iterate through arrays or collections. By collection,

we mean any class, struct or interface that implements an IEnumerable

interface. (Just go through this point and come back to it once we complete

the lesson describing classes and interfaces).

The String class is also a collection of characters (implements IEnumerable

interface and returns the Char value in the Current property). The following

code example demonstrates this and prints all the characters of a string.

Public Sub Main()

Dim name As String = "Faraz Rasheed"

Dim ch As Char

For Each ch in name

Console.WriteLine(ch)

End For

End Sub

This will print each character of the name variable on a separate line.

Visual Basic Unit 3

Sikkim Manipal University Page No.: 61

3.5 Arrays in VB.Net

Declaration

An Array is a collection of values of similar data type. Technically, VB.Net

arrays are of reference type. Each array in VB.Net is an object and is

inherited from the System.Array class. Arrays are declared as follows:

Dim <identifier>(<size of array>) As <data type>

Let us define an array of Integer type to hold 10 integers.

Dim myIntegers(9) As Integer

The above will create an array of 10 integers from the index of 0 to 9. The

size of an array is fixed and must be defined before use. You can also use

variables to define the size of array like so:

Dim size As Integer = 10

Dim myIntegers(10-1) As Integer

You can optionally perform declaration and initialization in separate steps

like below:

Dim myIntegers() As Integer

myIntegers = New Integer() {1, 2, 3, 4, 5}

Here we initialized the array myIntegers using the values it holds. Note, we

must enclose the values in curly brackets and separate the individual values

with commas. This will create an array size of 5, whose successive values

will be 1, 2, 3, 4, 5.

It is important to note that when an array declaration and initialization are

performed separately, you must provide values for each element.

Accessing the values stored in array

To access the values in an Array, we use the indexing operator (Integer

index) by passing an Integer to indicate which particular index value we wish

to access. It's important to note that index values in VB.Net starts from 0.

So, if an array contains 5 elements, first element would be at index 0,

second at index 1 and last (fifth) at index 4. The following code

demonstrates how to access the 3rd element of an array.

Dim myIntArray() As Integer

myIntArray = New Integer() {5, 10, 15, 20}

Dim j As Integer = myIntArray(2)

Visual Basic Unit 3

Sikkim Manipal University Page No.: 62

The following example illustrates the usage of an integral array.

' demonstrates the use of arrays in VB.Net

Public Sub Main()

' declaring and initializing an array of type integer

Dim myIntegers() As Integer = New Integer() {3, 7, 2, 14, 65}

' iterating through the array and printing each element

Dim i As Integer

For i = 0 to 4

Console.WriteLine(myIntegers(i))

Next

End Sub

Here we used the For...Next loop to iterate through an array and use the

Console.WriteLine() method to print each individual element of the array.

Note how the indexing operator () is used.

The above program is quite simple and efficient, but we have to hard-code

the size of the array in the For...Next loop. As we mentioned earlier, arrays

in VB.Net are reference type and are a sub-class of the System.Array Class.

This class has a lot of useful properties and methods that can be applied to

any instance of an array. Properties are very much like a combination of

getter and setter methods in common Object Oriented languages.

Properties are context sensitive; meaning the compiler can un-ambiguously

identify whether it should call a getter or a setter in certain contexts. We will

discuss properties in detail in the coming chapters. System.Array has a very

useful read only property “Length” that can be used to find the length or the

size of an array programmatically. Using the Length property, the For...Next

loop from the previous code example can be written as follows:

For i = 0 to myIntegers.Length - 1

Console.WriteLine(myIntegers(i))

Next

This type of loop is very flexible and can be applied to an array of any size

and of any data-type.

Visual Basic Unit 3

Sikkim Manipal University Page No.: 63

We can also understand the common description of the Main() Sub

procedure. Main is also declared as

Public Main(ByVal args As String())

The command line arguments that we pass when executing our program are

available in our programs through an array of String type, which is identified

by args string array.

Self Assessment Questions

4. The most common type of loop in VB.Net is the _____ loop.

5. The statements under Do…While will run continuously as long as the

Boolean expression evaluates to _____.

6. An _____ is a collection of values of similar data type.

3.6 Summary

Condition checking has always been the most basic and important

construct in any language. VB.Net provides conditional statements in the

form of the If...Then...Else statement.

If you need to perform a series of specific checks, Select...Case is

present in VB.Net and is just the ticket for this.

Loops are used for iteration purposes, that is, performing a task multiple

times (usually until a termination condition is met).

3.7 Terminal Questions

1. Write a program to find and display the greatest of three numbers. The

input should be taken through a form based application and the greatest

number should be displayed in a textbox on the form.

2. Write a program to print the day of the week taking the input of numbers

1 to 7 as input using Select… Case statement.

3. Write a program to sort and display an array of integers in ascending

order using the concept of array in VB.Net.

3.8 Answers

1. Use If…Then…Else statement. (Refer Section 3.2)

2. Use Select…Case statement. (Refer Section 3.3)

3. Use arrays. (Refer Section 3.5)

Visual Basic Unit 4

Sikkim Manipal University Page No.: 64

Unit 4 Form Based Applications

Structure:

4.1 Introduction

Objectives

4.2 Creating a New Project

4.3 Forms Design For a Windows Application

4.4 Classes and Objects

4.5 Event Driven Applications

4.6 Working with Label, Text Box, and Button Controls

4.7 Working with Combo Box and List Box Controls

4.8 Working with Check Box and Radio Button Controls

4.9 Working with Group Box and Panel Controls

4.10 Working with Tab Controls

4.11 Developing a Multi-form Application

4.12 Working with Form Objects

4.13 Single-document and Multiple-document Interfaces

4.14 Summary

4.15 Terminal Questions

4.16 Answers

4.1 Introduction

Designing a form is the basis of any graphical user interface based

application. This unit makes the reader understand the concepts of

designing window based form applications using Visual Basic as the

Language. It makes the user to design any application using the available

controls in Visual Basic. It starts with the step of creating a new project to

the stage of creating single and multi-document interfaces.

Objectives:

After studying this unit, you should be able to:

explain the basics of creating window based applications

describe the usage of various controls available in Visual Basic

apply the GUI designing concepts

create single and multi-document based interfaces

test the applications developed

Visual Basic Unit 4

Sikkim Manipal University Page No.: 65

4.2 Creating a New Project

When you create a new Visual Basic project, you use the New Project

dialog box to set the basic options for the project, such as the project’s

name and the location at which the project is saved. In addition, you can use

the Options dialog box to set some options that affect how Visual Studio

handles projects and solutions. You’ll learn about these dialog boxes in the

topics that follow. The project template that you select determines the initial

files, assembly references, code, and property settings that are added to the

project.

(i) Using the New Project dialog box

To create a new project and set the basic options for that project, you use

the New Project dialog box shown in figure 4.1. This dialog box lets you

select the type of project you want to create by choosing one of several

templates.

When you create a new project, Visual Studio also creates a new solution to

hold the project. By default, the solution is given the same name as the

project and is stored in the same folder. If that’s not what you want, you can

click on the More button in the New Project dialog box. This displays

additional options that let you create a solution folder above the project

folder and provide a separate name for the solution.

Figure 4.1: The New Project dialog box

Visual Basic Unit 4

Sikkim Manipal University Page No.: 66

(ii) Options Dialog Box To make it easier for you to create new projects, you can set default project

and solution options by using the Options dialog box shown in figure 4.2.

You can display this dialog box by using the Tools, Options command. To

get to the Projects and Solutions options, click the Environment folder if it

isn’t already open, then click Projects and Solutions.

The Visual Studio projects location option establishes the default location for

new projects. To set this option, you can type a path directly into the text

box, or you can click Browse to display a dialog box that lets you navigate to

the folder you want to use. Note that you can always override the default

project location by specifying a different location in the New Project dialog

box when you create a new project.

The next two options in this category let you determine if the Output and

Task List windows are displayed automatically. Then, the last group of

options determines whether or not Visual Studio saves changes to the files

when you build and run a project.

As you can see in this figure, you can set a variety of options in addition to

the ones described here. You’ll learn about some of these options later in

this book. However, I suggest that you spend a few minutes exploring the

Options dialog box now so you know what options are available. You’ll have

a chance to do that in the first exercise for this chapter.

Figure 4.2: How to use the Options dialog box

Visual Basic Unit 4

Sikkim Manipal University Page No.: 67

4.3 Forms Design For a Windows Application

When you create a new project, the project begins with a single, blank form.

You can then add controls to the form and set the properties of the form and

controls so they look and work the way you want them to. That’s what you’ll

learn to do in the topics that follow.

Example: Design of Invoice Total form

Before I show you how to add controls to a form and set the properties of

the form and controls, I want to describe the Invoice Total form that I’ll use

as an example throughout this chapter. This form is presented in figure 4.3.

As you can see, the form consists of a eight controls: a text box, five labels,

and two buttons.

“The Invoice Total form lets the user enter an order total into the text box,

and then calculates the discount amount and invoice total for that order

when the user clicks on the Calculate button. The discount amount and

invoice total are displayed in label controls. For this simple application, the

discount amount is always calculated as 20% of the order total.

After the discount amount and invoice total are calculated for an order, the

user can enter a different order total and click on the Calculate button again

to display the discount and invoice total for that order amount. This cycle

continues until the user clicks on the Close button in the upper right corner

of the form or clicks on the Exit button. Then, the form is closed and the

application ends.”

Note that this application also provides keystroke options for users who

prefer using the keyboard to the mouse. In particular, the user can activate

the Calculate button by pressing the Enter key and the Exit button by

pressing the Esc key. The user can also activate the Calculate button by

pressing Alt+C and the Exit button by pressing Alt+X. When the user

presses the Alt key, the letters that activate the keys are underlined so the

user can tell which ones to press.

Visual Basic Unit 4

Sikkim Manipal University Page No.: 68

Figure 4.3: Design of Invoice Total form

Description

The Invoice Total form calculates a discount amount and invoice total based

on the order total entered by the user.

The user enters the order total into a text box, and the discount amount and

invoice total are displayed in label controls. Label controls are also used to

identify the amounts that are displayed on the form.

After entering an order total, the user can click on the Calculate button to

calculate the discount amount and the invoice total. Alternatively, the user

can press the Enter key to perform the calculation. For this version of the

Invoice Total application, the discount is always calculated as 20% of the

order total.

To close the form and end the application, the user can click on the Close

button in the upper right corner of the form or on the Exit button.

Alternatively, the user can press the Esc key to exit from the form.

The user can press Alt+C to perform the calculation or Alt+X to exit from the

form. When the user presses the Alt key, the C in the Calculate button will

be underlined and the x in the Exit button will be underlined.

Adding controls to a form

Figure 4.4 shows how you can use the Toolbox to add controls to a form.

The easiest way to do that is to click on the control in the Toolbox, then click

the form at the location where you want to add the control. You can then

resize the control by dragging one of the control’s adjustment handles, and

you can move the control by dragging the control to a new location on the

form.

Visual Basic Unit 4

Sikkim Manipal University Page No.: 69

If you prefer, you can place and size the control in a single operation by

clicking the control in the Toolbox, then clicking and dragging in the form. In

this figure, for example, a button is being added to the form.

A third method for adding controls is to simply double-click the control you

want to add in the Toolbox. This places the control in the upper left corner of

the form. You can then move and resize the control.

A fourth way to add a control is to drag the control from the Toolbox to the

form. The control is placed wherever you drop it. You can then resize the

control.

You can work with several controls at once. For example, let’s say that you

have four text box controls on your form and you want to make them all the

same size with the same alignment. To do that, first select all four controls

by holding down the Shift key as you click on them or by using the mouse

pointer to drag around the controls. Then, use the commands in the Format

menu or the buttons in the Layout toolbar to move, size, and align the first

three controls relative to the fourth control (the primary control). To format

the controls relative to a control other than the last one you selected, click

on that control to make it the primary control. (The primary control will have

different color handles so you can identify it.)

Although these techniques may be hard to visualize as you read about

them, you’ll find that they’re relatively easy to use. All you need is a little

practice, which you’ll get in the first exercise for this chapter.

Figure 4.4: How to add controls to a form

Visual Basic Unit 4

Sikkim Manipal University Page No.: 70

Setting properties

After you have placed controls on a form, you need to set each control’s

properties so the controls will look and work the way you want them to when

the form is displayed. In addition, you need to set some of the properties for

the form itself.

To set the properties of a form or control, you work in the Properties window

as shown in figure 4.5. To display the properties for a specific control, click

on it in the Form Designer window to select the control. To display the

properties of the form, click the form’s title bar or any blank area of the form.

In the Properties window, you can select a property by clicking it. When you

do, a brief description of that property is given at the bottom of the

Properties window. To change a property setting, you change the entry to

the right of the property name by typing a new value or choosing a new

value from a drop-down list.

Figure 4.5: Setting properties

Description

The Properties window displays the properties for the object that’s

currently selected in the Form Designer window. To display the

properties for another object, click on that object or select the object

from the drop-down list at the top of the Properties window.

Visual Basic Unit 4

Sikkim Manipal University Page No.: 71

To change a property, enter a value into the text box or select a value

from its drop-down list if it has one. If a button with an ellipsis (…)

appears at the right side of a property’s text box, you can click on the

ellipsis to display a dialog box that lets you set options for the property.

To change the properties for two or more controls at the same time,

select the controls. Then, the common properties of the controls are

displayed in the Properties window.

When you click on a property in the Properties window, a brief

explanation of the property appears in a pane at the bottom of the

window. For more information, press F1 to display the help information

for the property.

You can use the first two buttons at the top of the Properties window to

sort the properties by category or alphabetically.

You can use the plus and minus signs displayed to the left of some of

the properties and categories in the Properties window to expand and

collapse the list of properties.

Note: If a description isn’t displayed when you click on a property in the

Properties window, right-click on the window and select Description from the

shortcut menu.

The tab order is the order in which the controls on a form receive the focus

when the user presses the Tab key. The tab order should usually be set so

the focus moves left-to-right and top-to-bottom, beginning at the top left of

the form and ending at the bottom right. However, in some cases you’ll want

to deviate from that order. For example, if you have controls arranged in

columns, you may want the tab order to move down each column.

The tab order is initially set based on the order in which you add controls to

the form. So if you add the controls in the right order, you won’t need to alter

the tab order. But if you do need to change the tab order, you can do so by

adjusting the TabIndex property settings. The TabIndex property is simply a

number that represents the control’s position in the tab order, beginning with

zero. So, the first control in the tab order has a TabIndex of 0, the second

control’s TabIndex is 1, and so on.

Access keys are shortcut keys that let the user move directly to a control.

You set a control’s access key by using the Text property. Just precede the

letter in the Text property value that you want to use as an access key with

Visual Basic Unit 4

Sikkim Manipal University Page No.: 72

an ampersand (&). Then, the user can activate the control by pressing Alt

plus the access key.

Note that if you assign an access key to a control that can’t receive the

focus, such as a label control, pressing the access key causes the focus to

move to the next control in the tab order. As a result, you can use an access

key with a label control to create a shortcut for a text box control.

Finally, you should usually set the AcceptButton and CancelButton form

properties. These properties specify the buttons that are activated when the

user presses the Enter and Esc keys. That can make it easier for a user to

work with a form. If, for example, the AcceptButton property of the Invoice

Total form in figure 4.5 is set to the Calculate button, the user can simply

press the Enter key after entering an order total instead of having to use the

mouse to click on the Calculate button.

Property settings for the Invoice Total form Table 4.1 shows the property settings for the Invoice Total form.

Since the form is designed so it’s the right size for the controls it contains,

you can set the FormBorderStyle property to FixedSingle. Then, the user

won’t be able to change the size of the form by dragging the edge of the

form. In addition, you can set the MaximizeBox and MinimizeBox properties

to False so these boxes aren’t displayed on the form and the user can’t

minimize or maximize the form.

Table 4.1: The property settings for the Invoice Total form

The property settings for the form

Default name Property Setting

Form1 FormBorderStyle FixedSingle

MaximizeBox False

MinimizeBox False

StartPosition CenterScreen

Text Calculate invoice total

AcceptButton btnCalculate

CancelButton btnExit

Visual Basic Unit 4

Sikkim Manipal University Page No.: 73

The property settings for the controls

Default name Property Setting

Label1 Text Order total:

TextAlign MiddleRight

TabIndex 0

Label2 Text Discount:

TextAlign MiddleRight

TabIndex 0

Label3 Text Invoice total:

TextAlign MiddleRight

TabIndex 0

TextBox1 Name txtOrderTotal

Text (empty)

TabIndex 1

Label4 Name lblDiscountAmount

Text (empty)

TextAlign MiddleLeft

TabIndex 0

BorderStyle Fixed3D

Label5 Name lblInvoiceTotal

Text (empty)

TextAlign MiddleLeft

TabIndex 0

BorderStyle Fixed3D

Button1 Name btnCalculate

Text &Calculate

TabIndex 2

Button2 Name btnExit

Text E&xit

TabIndex 3

Note: Because label controls can’t receive the focus, the TabIndex

properties for these controls don’t matter. What matters is that the text box

and the two buttons have TabIndex properties with sequence numbers that

move the focus from the text box, to the Calculate button, to the Exit button,

and back to the text box.

Visual Basic Unit 4

Sikkim Manipal University Page No.: 74

Self Assessment Questions

1. When you create a new project, Visual Studio also creates a new _____

to hold the project.

2. Designing a _____ is the basis of any graphical user interface based

application.

3. Just precede the letter in the Text property value that you want to use as

an access key with an _____ symbol.

4.4 Classes and Objects

An object is a self-contained unit that combines code and data. Two

examples of objects you have already worked with are forms and form

controls. A class is the code that defines the characteristics of an object.

You can think of a class as a template for an object. An object is an instance

of a class, and the process of creating an object from a class is called

instantiation. More than one object instance can be created from a single

class. For example, a form can have several button objects, all instantiated

from the same Button class. Each is a separate object, but all share the

characteristics of the Button class. A class can be based on an existing

class. In that case, the existing class is referred to as the base class, and

the new class inherits the characteristics of the base class.

Properties, Methods, and Events

An object’s interface consists of a clearly defined set of properties,

methods, and events. The properties, methods, and events can be

referred to as members of the object.

Properties are the data associated with an object.

Methods are the operations that an object can perform.

Events are signals by which an object can notify other objects that

something noteworthy has occurred.

If you instantiate two or more instances of the same class, all of the

objects have the same properties, methods, and events. However, the

values assigned to the properties can vary from one instance to another.

Objects and Forms

When you use the IDE to design a form, the IDE automatically

generates Visual Basic code that creates a new class based on the

Form class. Then, when you run the project, a form object is instantiated

from the new class.

Visual Basic Unit 4

Sikkim Manipal University Page No.: 75

When you add a control to a form, the IDE automatically generates

Visual Basic code in the Form class that instantiates a control object

from the appropriate class and sets the control’s properties to the values

you have set for the control.

4.5 Event Driven Applications

Visual Basic applications are event-driven, i.e., they work by responding to

the events that occur on objects. To respond to an event, you code an event

procedure (or event handler) as shown in Figure 4.7.

The user may click on an Exit button on the form. Then, the application

responds by executing the event procedure for that object and event. In this

case, the event procedure consists of a single statement that uses the Close

method to close the form. The Private Sub and End Sub statements are

generated by Visual Studio to mark the beginning and the end of the

procedure.

Although the Click and DblClick events are started by user actions, that’s

not always the case. For instance, the GotFocus and LostFocus events can

occur when the user moves the focus to or from a control, but they can also

occur when the Visual Basic code moves the focus to or from a control.

Similarly, the Load event of a form can occur when an application first starts.

And the Closed event occurs after the Close method is executed for a form.

In addition to the events shown here, most objects have many more events

that the application can respond to. For example, events occur when the

user positions the mouse over an object or when the user presses or

releases a key. However, you don’t typically respond to those events.

Event: The user clicks on the Exit button

Visual Basic Unit 4

Sikkim Manipal University Page No.: 76

Figure 4.7: How an application responds to events

Response: The procedure for the Click event of the Exit button is executed

Private Sub btnExit_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) _

Handles btnExit.Click

Me.Close()

End Sub

Common control events

Event Occurs when…

Click …the user clicks on the control.

DblClick …the user double-clicks on the control.

GotFocus …the focus is moved to the control.

LostFocus …the focus is moved from the control.

Common Form Events

Event Occurs when…

Load …the form is loaded into memory.

Activated …the form becomes the active form.

Closing …the form is closing.

Closed …the form is closed.

Visual Basic Unit 4

Sikkim Manipal University Page No.: 77

The code for the Invoice Total form

Figure 4.8 presents the code for the Invoice Total form. The first thing to

notice is that the code starts with a Class statement and ends with an End

Class statement. These statements are added automatically when you

create a form, and they’re your first clue that when you create a form you’re

actually creating a new class that defines the form. In this case, the class is

named Form1, which is the default name for the first form that’s added to a

Windows application.

Visual Basic also adds an Inherits statement after the Class statement. In

this case, the Inherits statement says that the new form is based on the

Form class in the System.Windows.Forms namespace of the .NET Class

Library.

The rest of the code for this form consists of two event procedures. The first

one responds to the Click event of the Calculate button; the second one

responds to the Click event of the Exit button. I’ll describe this code briefly

here so you have a general idea of how it works, but if you’re new to

programming you may not understand the code completely until after you

read the next chapter.

The event procedure for the Click event of the Calculate button calculates

the discount amount and the invoice total based on the order total entered

by the user and then displays those values in the appropriate label controls.

To do that, this procedure starts by defining the variables it will use in its

calculations. In this case, three variables are defined, each of which can

hold a decimal value.

In the next group of statements, the value in the Text property of the Order

Total text box, which is the value entered by the user, is assigned to the

variable named dOrderTotal. Because the discount for this version of the

program is always 20%, the discount amount is calculated by multiplying the

order total by .2, and the resulting value is assigned to the variable named

dDiscountAmount. Then, the invoice total is calculated by subtracting the

discount amount from the order total, and the result is assigned to the

variable named dInvoiceTotal.

The next two statements assign the values of the last two variables to the

Text properties of the label controls, which displays the values on the form.

Then, the last statement before the End Sub statement executes the Focus

Visual Basic Unit 4

Sikkim Manipal University Page No.: 78

method of the Order Total text box, which moves the focus to that control.

Otherwise, the focus would remain on the Calculate button that’s used to

start this event procedure.

The other procedure that’s required by this application is for the Click event

of the Exit button. It contains just one statement that performs the Close

event of the form. So when the user clicks on this button, the form is closed,

which ends the application.

Note that all of the shaded code in this figure is generated by Visual Basic

when you start the project and start the event procedures. Beyond that,

Visual Basic generates other code that is hidden in the Code Editor window

under the label “Windows Form Designer generated code”. When the

application is run, this is the code that implements the form and controls that

you designed in the Form Designer. For now, you can just accept the fact

that this generated code should work the way you want it to. By the time you

finish this book, though, you’ll understand what this code does.

Public Class Form1 Inherits System.Windows.Forms.Form

Private Sub btnCalculate_Click (ByVal Sender As System.Object,_

ByVal e as System.EventArgs) Handles btnCalculate.Click

Dim dOrderTotal As Decimal

Dim dDiscountAmount As Decimal

Dim dInvoiceTotal As Decimal

dOrderTotal = txtOrderTotal.Text

dDiscountAmount = dOrderTotal * .2

dInvoiceTotal = dOrderTotal – dDiscountAmount

lblDiscountAmount.Text = dDiscountAmount

lblInvoiceTotal.Text = dInvoiceTotal

txtOrderTotal.Focus()

End Sub

Private Sub btnExit_Click (ByVal Sender As System.Object,_

ByVal e as System.EventArgs) Handles btnExit.Click

Me.Close()

End Sub

End Class

Figure 4.8: The code for the Invoice Total form

Visual Basic Unit 4

Sikkim Manipal University Page No.: 79

Description

The code for the Invoice Total form includes two event procedures. The

first one is executed when the user clicks the Calculate button. This

procedure calculates the discount amount and invoice total based on the

order total entered by the user.

The second event procedure is executed when the user clicks the Exit

button. This procedure closes the form, which ends the application.

When you use the IDE to create a form, you’re actually creating a new

class based on the Form class. That’s why the code for a Windows form

starts with a Class statement and ends with an End Class statement.

That’s also why the Class statement is followed by an Inherits statement

that identifies the Form class. All three of these statements are

generated for you, and you don’t need to change them.

Note: All of the shaded statements in the code are generated for you.

4.6 Working with Label, Text Box, and Button Controls

Since the Invoice Total and Future Value programs that were presented in

previous chapters used label, text box, and button controls, you should

already be familiar with the basic operations of these controls. However, you

may want to know about some of the other properties that affect how they

function. The properties you’re most likely to use are presented in Table 4.2.

As you know, the main purpose of a label control is to display information.

So you almost always set its Text property to the text you want to display

when you design the form. If the text will change as the program executes,

though, you can set this property in the code for the form.

You can include an ampersand (&) in the Text property to indicate the

character that can be used to access the control using the keyboard. Note,

however, that since a label can’t receive the focus, the focus moves to the

next control in the tab order that can receive the focus. In the form shown at

the top of this figure, for example, the access key for the Invoice number

label is the letter I. So if the user holds down the Alt key and presses the

letter I, the focus will move to the text box to the right of the label, which is

what you want.

In some cases, you may want to include an ampersand in the text that’s

displayed in the label. To do that, you have to set the UseMnemonic

Visual Basic Unit 4

Sikkim Manipal University Page No.: 80

property of the label to False. Then, an ampersand you include in the Text

property is treated as a text character.

Several of the text box properties in this figure are used to create multi-line

text boxes like the one shown in the form at the top of this figure. To create

a text box like this, you set the Multiline property to True. Then, you can set

the AcceptsReturn, AcceptsTab, Scrollbars, and WordWrap properties so

the control works the way you want it to. These properties, as well as the

other text box properties shown in this figure, should be self-explanatory, so

I won’t describe them in more detail. If you need more information about any

of these properties, though, you can refer to the online help documentation.

The last property shown in this figure is the Text property of the button

control. Like the label control, you can include one ampersand in this

property to define an access key for it. Unlike the label control, if you want to

include an ampersand in the text, you can type two ampersands in a row. If,

for example, you want to create a Save & Exit button, you can type “Save

&& Exit” as the Text property.

A form with access keys and a multi-line text box

Figure 4.9: How to work with label, text box, and button controls

Visual Basic Unit 4

Sikkim Manipal University Page No.: 81

Table 4.2: Control Properties

Label Control Properties:

Property Example Description

Text &Invoice number:

The text for the label. If an ampersand (&) is included, the next letter is treated as an access key. Then, the user can press Alt plus this letter to move the focus to the control that follows the label in the tab order. (The label itself can’t receive the focus.)

UseMnemonic True Determines whether an ampersand (&) in the Text property of the control identifies an access key (True) or a text character (False).

Text box control properties:

Property Example Description

AcceptsReturn False Determines whether return characters can be entered into a text box whose Multiline property is set to True.

AcceptsTab False Determines whether tab characters can be entered into a text box whose Multiline property is set to True.

CharacterCasing Normal Determines whether characters entered into the text box should be left as entered or converted to upper or lowercase.

HideSelection False Determines if the text in the text box is hidden when the control loses focus.

MaxLength 10 The maximum number of characters that can be entered into the text box. The default is 32767.

Multiline False Determines whether the text in the text box can occupy more than one line.

PasswordChar * The character that’s displayed in place of each character entered into the text box. Used to provide security for entering passwords.

ReadOnly False Determines whether the user can change the text in the text box.

Scrollbars None Determines what scrollbars are displayed in a multi-line text box.

WordWrap True Determines whether the lines in a multi-line text box are wrapped automatically when the end of each line is reached.

Visual Basic Unit 4

Sikkim Manipal University Page No.: 82

Button control property

Property Example Description

Text E&xit The text that will appear on the control. If an ampersand is included, the letter that follows can be used as an access key.

Self Assessment Questions

4. An _____ is a self-contained unit that combines code and data.

5. An object is an _____ of a class, and the process of creating an object

from a class is called _____.

6. Visual Basic applications are _____, i.e., they work by responding to the

events that occur on objects.

4.7 Working with combo box and list box controls

Figure 4.10 shows you how to work with combo boxes and list boxes. In the

form at the top of this figure, a combo box lets the user select a number that

represents the life of an asset and a list box displays the depreciation

amount for each year of the asset’s life. To use this form, the user enters the

initial cost of the asset and the final value of the asset (which is often zero)

in the text boxes. Then, the user selects the life of the asset from the drop-

down list of the combo box or enters the number of years into that box. Last,

the user clicks on the Calculate button to display the year and depreciation

amounts in the list box.

This figure also lists some of the properties and methods you’re likely to use

as you work with combo boxes and list boxes. To get the index value of the

item that the user selects, for example, you can use the SelectedIndex

property. And to get the value of the selected item, you can use the

SelectedItem property. You’ll see coding examples that use these properties

in the next figure (figure 4.11).

One property that applies only to a combo box is the DropDownStyle

property. This property determines how the combo box functions. The

default is DropDown, which means that the user can either click on the drop-

down arrow at the right side of the combo box to display the drop-down list

and select an item, or he can enter a value directly into the text box portion

Visual Basic Unit 4

Sikkim Manipal University Page No.: 83

of the combo box. Note that the value the user enters doesn’t necessarily

have to be a value that appears in the list.

If you want to restrict user entries to just the values in the list, you can set

the DropDownStyle property to DropDownList. Then, the user can only

select a value from the list or enter a value that appears in the list.

The third option for the DropDownStyle property is Simple. Like the

DropDown setting, this setting lets the user enter any value into the text box

portion of the control. However, instead of having to click on an arrow to

display the list, the list is always visible.

When you work with the items in a list box or combo box, you should realize

that you’re actually working with the items in a collection. To refer to this

collection, you use the Items property of the control. Then, you can use the

properties and methods that the .NET Framework provides for working with

collection objects to work with the items in the collection. The most common

properties and methods are summarized in this figure.

The most common event for working with combo boxes and list boxes is the

SelectedIndexChanged event. This event occurs when the value of the

SelectedIndex property changes, which is when the user selects a different

item from the list. For a combo box, you can also use the TextChanged

event to detect when the user enters a value into the text box portion of the

control. Keep in mind, though, that this event will occur each time a single

character is added, changed, or deleted.

Figure 4.10: How to work with combo box and list box controls

Visual Basic Unit 4

Sikkim Manipal University Page No.: 84

Common properties of list box and combo box controls

Property Description

SelectedIndex The index value of the selected item. Items are numbered from 0. If no item is selected, this property has a value of –1.

SelectedItem The contents of the selected item.

Text The contents of the text box portion of a combo box control.

Sorted If set to True, the items in the list are sorted alphabetically.

Items Provides access to the collection of items in a list box or combo box list.

DropDownStyle Determines whether the text box portion of a combo box control is editable and whether the list portion is always displayed or is displayed when the drop-down arrow is clicked.

Common properties and methods of the Items collection

Property Description

Count The number of items in the list.

Method Description

Add Adds an item to a list box or combo box list.

Insert Inserts an item into a list box or combo box list at the specified location.

Remove Removes an item from a list box or combo box list.

Clear Removes all items from a list box or combo box list.

Description

To work with the items in a list box or combo box list, you use the Items

collection of the control that you access through the Items property of

the control. To refer to any item in the collection, you use an index value.

If a list box contains more items than can be displayed at one time, a

vertical scroll bar is automatically added.

When the user selects a different item from a list, the

SelectedIndexChanged event occurs. When the user enters a value into

the text box portion of a combo box, the TextChanged event occurs.

Figure 4.11 presents some code examples for working with combo boxes

and list boxes. The first example uses a For…Next loop to load the numbers

Visual Basic Unit 4

Sikkim Manipal University Page No.: 85

1 through 40 into a combo box list named cboLife. This is the combo box

from the Calculate Depreciation form you saw in the previous figure that lets

the user specify the life of an asset. Each time through the loop, the Add

method is used to add the number to the Items collection of the combo box.

In this case, the code is in the Load event procedure for the Form, so the

combo box is loaded when the form is loaded. After that, the user can select

a value from the combo box and other procedures can use that value. You

can see, for example, that the Text property of cboLife is used as the third

argument for the SYD function in the second coding example in this figure.

The second example shows how you can load the list box in figure 4.10

when the Click event of the Calculate button occurs. This example begins by

invoking the Clear method to clear all items from the list box. Then, a

For…Next loop uses the SYD function to add the lines to the list box.

The SYD function is one of the financial functions that come with Visual

Basic. It calculates each year’s depreciation using a method know as the

Sum of the Years’ Digits. If you’re not familiar with depreciation, keep in

mind that you don’t have to understand how it works. Just think of it as a

function that requires four arguments and returns a yearly depreciation

value that is added to a list box. The point of this code is to illustrate the use

of the Add method.

Even then, this code may look confusing, but it’s easy to understand if you

break it down. For each year in the asset’s life (iIndex), the Add method is

used to add a string to the Items collection of the list box. This string starts

with the year followed by a colon and some spaces

lstDepreciation.Items.Add ("Year " & iIndex & ": " &

followed by the value derived from the SYD function

SYD(txtInitialCost.Text, txtFinalValue.Text, cboLife.Text, iIndex)

after the FormatCurrency function is used to format the result.

When you use the Add method of the Items collection to add an item to a

list, the item is added at the end of the list. If you want to add the item in

another location, you can use the Insert method as illustrated by the third

example in this figure. When you use this method, you indicate the index

where you want the item inserted along with the value of the item to be

inserted. Keep in mind if you use this method that the index values of a

Visual Basic Unit 4

Sikkim Manipal University Page No.: 86

collection are zero-based. So the index of the first item is 0, the index of the

second item is 1, and so on.

The fourth example in this figure shows how to use the Remove method to

remove an item from a list by specifying its index value. The fifth example

shows how to use the SelectedItem property to get the value of the selected

item. And the last example shows how you can initialize a combo box so

that no value is selected. To do that, you set the SelectedIndex property of

the control to –1, which is not a valid index value.

Code that loads the combo box in figure 4.10

Private Sub Form1_Load(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles MyBase.Load

Dim iIndex As Integer

For iIndex = 1 To 40

cboLife.Items.Add(iIndex)

Next iIndex

End Sub

Code that clears and loads the list box in figure 8-3

Private Sub btnCalculate_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles btnCalculate.Click

Dim iIndex As Integer

lstDepreciation.Items.Clear()

For iIndex = 1 To cboLife.Text

lstDepreciation.Items.Add("Year " & iIndex & ": " _

& FormatCurrency(SYD(txtInitialCost.Text, _

txtFinalValue.Text, cboLife.Text, iIndex)))

Next iIndex

End Sub

A statement that inserts an item into a combo box list:

cboNames.Items.Insert(iIndex, txtName.Text)

A statement that removes an item from a list

cboNames.Items.Remove(iIndex)

A statement that refers to the selected item in a combo box

sSelectedName = cboNames.SelectedItem

A statement that initializes a combo box so that no item is selected

cboNames.SelectedIndex = -1

Figure 4.11 Code for working with combo box and list box controls

Visual Basic Unit 4

Sikkim Manipal University Page No.: 87

About the depreciation functions:

The SYD function that’s used in the second example is one of the

financial functions that comes with Visual Basic. It calculates the yearly

depreciation for an item by using the Sum of the Years’ Digits method of

depreciation.

The four arguments that the SYD function requires are the initial cost of

the item, the final value of the item, the lifetime of the item in years, and

the year that the item value should be calculated for. This function

returns the depreciation for one year.

Another function that can be used to calculate depreciation is the SLN

function. It calculates straight line depreciation using just the first three

arguments that are used for the SYD function (initial cost, final value,

and lifetime of the item).

To find out more about the depreciation functions or other financial

functions, use the Index tab of the help feature and type in “financial

calculations.”

4.8 Working with Check Box and Radio Button Controls

Figure 4.12 shows you how to work with check boxes and radio buttons.

The main difference between these two types of controls is that radio

buttons in a group are mutually exclusive and check boxes operate

independently. In other words, if the user selects a radio button in a group,

all of the other buttons are automatically turned off. In contrast, when the

user selects a check box, it has no effect on the other check boxes on the

form, even if they appear as a group.

To group radio buttons, you can place them in either a group box control or

a panel control. You’ll learn about these controls in a minute. For now, just

realize that if radio buttons aren’t placed within one of these controls, all of

the radio buttons on the form function as a group.

The property you’re most likely to use when working with radio buttons and

check boxes is the Checked property. This property can have a value of

either True or False to indicate if the control is checked. You can see how

this property is used in the two examples in this figure.

Visual Basic Unit 4

Sikkim Manipal University Page No.: 88

In the first example, the Checked property of the Future Value radio button

is tested in an If statement. If the value of this property is True, a procedure

named CalculateFutureValue is executed. But if the value of this property is

False, it indicates that the Monthly Investment radio button is selected. In

that case, a procedure named CalculateMonthlyInvestment is executed.

The second example is similar. In this case, though, the Checked property

of a check box is tested. If the value of this property is True, the FV function

is executed using the DueDate.EndOfPeriod constant for the fifth argument.

Otherwise, the DueDate.BegOfPeriod constant is used.

The event you’re most likely to work with when you use radio buttons or

check boxes is the CheckedChanged event. This event occurs when you

check or uncheck one of these controls. You’ll see how you can use this

event in one of the applications presented later in this chapter.

4.9 Working with group box and panel controls

Figure 4.12 also illustrates how to use GroupBox and Panel controls. Here,

you can see that the two radio buttons have been placed inside a group box

so it’s clear that they function as a group. The name of the group, which is

displayed in the upper left corner of the group box, is specified by setting the

Text property of the control. In contrast, the panel control doesn’t have a

Text property. Because of that, it’s more common to use this control to form

visual rather than functional groups.

Regardless of which control you use, you should know that if you move one

of these controls in the Form Designer window, all of the controls it contains

are moved with it. In fact, it’s common to use a panel control just to group

controls that can be moved together. Then, if you don’t want the panel to

appear when the form is displayed, you can set its BorderStyle property to

None.

Visual Basic Unit 4

Sikkim Manipal University Page No.: 89

A form with two radio buttons, a group box, a panel, and a check box

Figure 4.12: Working with radio button, check box, group box,

and panel controls

Code that uses the radio buttons

If rdoFutureValue.Checked Then

CalculateFutureValue()

Else

CalculateMonthlyInvestment()

End If

Code that uses the check box

If chkDueAtEnd.Checked Then

txtFutureValue.Text = _

FormatNumber(FV(txtInterestRate.Text / 12 / 100, _

txtYears.Text * 12, -txtMonthlyInvestment.Text, , _

DueDate.EndOfPeriod))

Else

txtFutureValue.Text = _

FormatNumber(FV(txtInterestRate.Text / 12 / 100, _

txtYears.Text * 12, -txtMonthlyInvestment.Text, , _

DueDate.BegOfPeriod))

End If

Description

To determine whether a radio button or check box is checked, you test

its Checked property. This property can be set to either True or False.

Visual Basic Unit 4

Sikkim Manipal University Page No.: 90

When you check or uncheck a radio button or check box, the

CheckedChanged event occurs.

You can use either a group box or a panel control to group controls. The

main difference between the two is that a group box includes a Text

property that contains the caption for the control, but a panel control

does not.

Group boxes are typically used to group controls like radio buttons that

function as a group. Panel controls are typically used to visually group

controls on a form.

If you move a group box or a panel control, all of the controls it contains

move with it.

Self Assessment Questions

7. One property that applies only to a combo box is the _____ property.

8. If you want to restrict user entries to just the values in the list, you can

set the DropDownStyle property to _____.

9. To determine whether a radio button or check box is checked, you test

its _____ property.

4.10 Working with tab controls

This control lets you group other controls on the form into pages. Figure

4.13 presents the basic skills for working with tab controls.

As you can see, the form in this figure contains a tab control with two pages,

also called tabs. The first tab provides controls that let you calculate an

investment, and the second tab provides controls that let you calculate

depreciation. The tab control makes it easy to combine related forms like

this into a single form.

The event you’ll use most often with a tab control is the

SelectedIndexChanged event. This event occurs when the SelectedIndex

property of the control changes, which typically happens as a result of a

user clicking on another tab. The event procedure shown in this figure, for

example, moves the focus to the appropriate control on a tab when that tab

becomes the current tab. Notice that this procedure uses the SelectedIndex

property to determine which tab is current.

Visual Basic Unit 4

Sikkim Manipal University Page No.: 91

A form that uses a tab control with two tabs

Figure 4.13: Working with tab controls

Code that uses the SelectedIndexChanged event of the tab control

Private Sub tabCalculations_SelectedIndexChanged _

(ByVal sender As System.Object, ByVal e As System.EventArgs) _

Handles tabCalculations.SelectedIndexChanged

If tabCalculations.SelectedIndex = 0 Then

If rdoFutureValue.Checked = True Then

txtMonthlyInvestment.Focus()

Else

txtInterestRate.Focus()

End If

Else

txtInitialCost.Focus()

End If

End Sub

Description

After you add a tab control to a form, you can add tabs to it by clicking

on the Add Tab link at the bottom of the Properties window or by

selecting the Add Tab command from the shortcut menu for the control.

By default, the tabs are displayed along the top of the tab control. To

display them along the left, right, or bottom of the control, change the

Alignment property accordingly.

Visual Basic Unit 4

Sikkim Manipal University Page No.: 92

By default, the tabs you add are displayed in a single row. To create

multiple rows of tabs, set the Multiline property to True.

To remove a tab, select it and then click on the Remove Tab link in the

Properties window or select the Remove Tab command from the

shortcut menu for the control.

Each tab in a tab control contains a page where you add the controls for

the tab. You use the Text property of a page to set the text that’s

displayed in its associated tab.

The SelectedIndexChanged event occurs when you move to another

tab. You can use the SelectedIndex property of the tab control to

determine which tab was selected.

4.11 Developing a multi-form application

In the last chapter, you saw forms for calculating an investment and for

calculating depreciation. Each of these forms was stored in a separate

project and operated independently of one another. Another way to

implement related forms like these, though, is to include them both in the

same project. To do that, you need to learn the skills presented in this

chapter.

Basic skills and concepts for developing multi-form applications

Few applications consist of a single form like the ones you’ve seen so far in

this book. Because of that, you need to know how to work with two or more

forms in the same project. You’ll learn the basic skills and concepts for

doing that in the topics that follow.

Adding a form to a project

When you start a new project, it consists of a single blank form. Then, to

add another form to the project, you use the Add New Item dialog box

shown in figure 4.14. From this dialog box, you select the Windows Form

template and then enter the name of the new form. When you click on the

Open button, the new form is created with the name you specify. If you look

at the code that’s generated for this form, you’ll see that the class is also

given this name (without the file extension, of course).

You can also add an existing form to a project using the Add Existing Item

dialog box. This can be useful if you want to use the same form in two

different projects or if you want to create a form that’s similar to an existing

Visual Basic Unit 4

Sikkim Manipal University Page No.: 93

form. Note that when you add an existing form from another project, that

form is copied into the new project. That way, you don’t have to worry about

changing the original form inadvertently. If you did the exercises for the last

chapter, you already saw how this works.

The Add New Item dialog box

Figure 4.14: How to add a form to a project

How to add a new form

Display the Add New Item dialog box by selecting the Project Add

Windows Form command. Or, select the Add Windows Form command

from the shortcut menu that’s displayed when you right-click on the

project in the Solution Explorer.

To add a new form, select the Windows Form template from the Add

New Item dialog box, enter a name for the form, and click on the Open

button.

How to add an existing form

Display the Add Existing Item dialog box by selecting the Project Add

Existing Item command. Or, select the Add Existing Item command from

the shortcut menu for the project.

To add an existing form, select the VB file for the form from the Add

Existing Item dialog box and then click on the Open button.

Note: The Class statement that’s generated for the new form will reflect the

name you specify in the Add New Item dialog box. Because of that, you may

Visual Basic Unit 4

Sikkim Manipal University Page No.: 94

want to change the class statement for the default form to an appropriate

name for consistency.

4.12 Working with form objects

To work with a form using Visual Basic code, you use the techniques shown

in Figure 4.15. To start, you declare an object variable for the form. Then,

you create an instance of the form class and assign a reference to that

instance to the object variable. As with other object variables and classes,

you can do that using a single declaration statement with the New keyword

as shown in the first statement in this figure. Alternatively, you can declare

the variable without the New keyword and then use this keyword in an

assignment statement to create an instance of the class and assign it to the

object variable.

After you create an instance of a form, you can load and display that form

using the Show method as illustrated in the second statement in this figure.

This method is a member of the Form class that’s defined by the .NET

Framework. Any form you create in Visual Basic inherits the members of the

Form class. So you can use any of these members to work with your forms.

Some of the other methods you’re likely to use are listed in this figure.

The syntax for declaring a form variable

{Dim|Private|Public|Static} variablename As [New] formname

A statement that declares a form variable and creates an instance of the

form

Dim frmCalculateInvestment As New frmCalculateInvestment()

A statement that displays a form

frmCalculateInvestment.Show()

Typical methods for working with form objects

Method Description

Show Loads the form if it isn’t already loaded, and then displays the form by setting its Visible property to True.

Hide Hides the form by setting its Visible property to False.

BringToFront Displays the form on top of any other forms that are currently displayed.

SendToBack Displays the form behind any other forms that are currently displayed.

Figure 4.15: Working with form objects

Visual Basic Unit 4

Sikkim Manipal University Page No.: 95

Description

When an application starts by displaying a form, Visual Basic

automatically creates an instance of that form. To display another form

from that form or from a class or module, you have to first declare an

object variable and create an instance of the form.

You declare an object variable that will hold a reference to a form just as

you do any other object variable. If you include the New keyword on the

declaration, an instance of the form class you name is created and

assigned to the form variable. Otherwise, you can code an assignment

statement with the New keyword to do that.

After you declare an object variable and assign a form object to it, you

can use that variable to work with the properties and methods of the

form.

Changing the startup object for a project

By default, the form that’s created when you start a project is the form that

will be displayed when you run the application. If that’s not what you want,

you can change the Startup object property of the project as shown in figure

4.16. To change the startup object to another form, for example, you just

select the form name from the drop-down list. And to change the startup

object to the Main procedure in a module, you select the Sub Main option.

The Property Pages dialog box

Figure 4.16: How to change the startup object for a project

Operation

To display the Property Pages dialog box for a project, select the

Project Properties command, or select the Properties command

from the shortcut menu for the project.

Visual Basic Unit 4

Sikkim Manipal University Page No.: 96

To change the form that’s displayed when the project starts, select the

General group in the Common Properties folder. Then, select the form

that you want from the Startup object combo box.

To run the Main procedure in a module when the project starts, select

the Sub Main option from the Startup object combo box.

4.13 Single-document and multiple-document interfaces

Figure 4.17 shows two versions of the Financial Calculations application that

will be used as examples in this chapter. These applications let the user

calculate an investment or depreciation using forms like the ones you saw in

the last chapter. In addition, each application includes a third form that

provides a way for the user to access the other forms.

The first version of this application uses a single-document interface, or SDI.

In an SDI application, each form runs in its own application window, and this

window is usually shown in the Windows taskbar. Then, you can click on the

buttons in the taskbar to switch between the open forms. When you use this

interface, each form can have its own menus and toolbars. In addition, a

main form called a startup form typically provides access to the other forms

of the application. In this figure, for example, the startup form includes

buttons that the user can click on to display the other forms.

The second version of this application uses a multiple-document interface,

or MDI. In an MDI application, a container form called a parent form

contains one or more child forms. Then, the menus and toolbars on the

parent form contain the commands that let you open and view forms, and

you can use its Window menu to switch between the open forms. When you

close the parent form of an MDI application, all of the child forms are closed

and the application ends.

The main advantage of a multiple-document interface is that the parent form

manages multiple instances of child forms for you. In contrast, if you create

multiple instances of a form in an SDI application, you have to manage them

yourself. As you can imagine, that can get unwieldy.

The parent form in the MDI application in this figure also includes a status

bar. A bar like this can be set up to display a number of information items.

Although you can add a status bar to any form in either an SDI or MDI

Visual Basic Unit 4

Sikkim Manipal University Page No.: 97

application, it makes the most sense to use one on the parent form in an

MDI application.

Incidentally, you can also develop an explorer-style interface with Visual

Basic .NET. In this type of interface, a single window is split into two panes

just as it is in the Windows Explorer. Then, you can use the left pane to

navigate between different parts of the application, and you can use the

right pane to work with the application. This type of interface, however, isn’t

presented in this book.

Single-document interface (SDI)

Multiple-document interface (MDI)

Figure 4.17: Single-document and multiple-document interfaces

Visual Basic Unit 4

Sikkim Manipal University Page No.: 98

Self Assessment Questions

10. The event you’ll use most often with a tab control is the _____ event.

11. Any form you create in Visual Basic inherits the members of the _____

class.

12. In _____ type of interface, a single window is split into two panes just as

it is in the Windows Explorer.

4.14 Summary

When you create a new Visual Basic project, you use the New Project

dialog box to set the basic options for the project, such as the project’s

name and the location at which the project is saved.

When you create a new project, the project begins with a single, blank

form. You can then add controls to the form and set the properties of the

form and controls so they look and work the way you want them to.

An object is a self-contained unit that combines code and data.

A class is the code that defines the characteristics of an object.

An object is an instance of a class, and the process of creating an object

from a class is called instantiation.

Visual Basic applications are event-driven, i.e., they work by responding

to the events that occur on objects.

4.15 Terminal Questions

1. Design a form based applications using labels, text boxes, and buttons

to perform basic arithmetic operations on integers.

2. Develop a form based interface to demonstrate the usage of combo box

and list box controls.

3. With the help of suitable example, describe the development of single-

document and multi-document interface.

4.16 Answers

Self Assessment Questions

1. Solution

2. Form

3. Ampersand (&)

4. Object

5. Instance, Instantiation

Visual Basic Unit 4

Sikkim Manipal University Page No.: 99

6. Event driven

7. DropDownStyle

8. DropDownList

9. Checked

10. SelectedIndexChanged

11. Form

12. Explorer Style Interface

Terminal Questions

1. Refer Section 4.6

2. Refer Section 4.7

3. Refer Section 4.13

Visual Basic Unit 5

Sikkim Manipal University Page No.: 100

Unit 5 Exception Handling in VB.NET

Structure:

5.1 Introduction

Objectives

5.2 A Brief Review of Error Handling in VB6

5.3 Exceptions in .NET

5.4 Structured-Exception-Handling Keywords

5.5 Throwing a New Exception

5.6 The Exit Try Statement

5.7 Using Exception Properties

5.8 Source and StackTrace

5.9 GetBaseException

5.10 HelpLink

5.11 Summary

5.12 Terminal Questions

5.13 Answers

5.1 Introduction

All professional-grade programs need to handle unexpected conditions. In

programming languages before Microsoft .NET, this was often called error

handling. Unexpected conditions generated error codes, which were trapped

by programming logic that took appropriate action.

The common language runtime in .NET does not generate error codes.

When an unexpected condition occurs, the CLR creates a special object

called an exception. This object contains properties and methods that

describe the unexpected condition in detail and communicate various items

of useful information about what went wrong.

Because .NET deals with exceptions instead of errors, the term ―error

handling‖ is seldom used in the .NET world. Instead, the term ―exception

handling‖ is preferred. This term refers to the techniques used in .NET to

detect exceptions and take appropriate action.

This chapter covers how exception handling works in Visual Basic 2005.

There are many improvements over pre-.NET versions of Visual Basic. This

chapter discusses the common language runtime (CLR) exception handler

Visual Basic Unit 5

Sikkim Manipal University Page No.: 101

in detail and the programming methods that are most efficient in catching

errors. Specifically, this chapter covers the following:

A brief review of error handling in Visual Basic 6 (VB6)

The general principles behind exception handling

The Try...Catch...Finally structure, the Exit Try statement, and nested

Try structures

The exception object’s methods and properties

Capabilities in Visual Studio .NET to work with exceptions

Error and trace logging and how you can use these methods to obtain

feedback on how your program is working

This chapter begins with a quick review of error handling in previous

versions of Visual Basic to use as a reference point. Then you will learn new

ways to handle exceptions in .NET.

Objectives:

Error handling is the most important feature of any programming language.

After studying this unit, you should be able to:

describe and discuss the importance of error handling mechanism in

Visual Basic

discuss various exceptions in VB.Net

discuss exception handling keywords

explain the keywords try, catch, throw and finally

explain the properties of exceptions.

5.2 A Brief Review of Error Handling in VB6

For compatibility, Visual Basic 2005 and other .NET versions of Visual Basic

still support the old-style syntax for error handling that was used in Visual

Basic 6 and earlier versions. That means you can still use the syntax

presented in this review. However, it is strongly recommended that you

avoid using this old-style syntax in favor of the exception handling features

that are native to .NET. Using the new Try...Catch syntax (presented after

this review) will give you more flexibility and better code structure.

The old-style syntax in VB6 was handed down from DOS versions of

BASIC. The On Error construct was created in an era when line labels and

Visual Basic Unit 5

Sikkim Manipal University Page No.: 102

GoTo statements were commonly used. Such error handling is difficult to

use and has limited functionality compared to more modern alternatives.

In VB6, a typical routine with error handling code looks like this:

Private Function OpenFile(sFileName As String) As Boolean

On Error GoTo ErrHandler:

Open sFileName For Random As #1

OpenFile = True

Exit Sub

ErrHandler:

Select Case Err.Number

Case 53 ' File not found

MessageBox.Show "File not found"

Case Else

MessageBox.Show "Other error"

End Select

OpenFile = False

End Function

The top of the routine points to a section of code called an error handler,

which is usually placed at the bottom of the routine. The error handler takes

control as soon as an error is detected in the routine, and it checks the error

number to determine what action to take. The error number is available as a

property of the Err object, which is a globally available object that holds error

information in VB6.

There are several other error handling syntax options not included in the

preceding error-handling code. If the error handler can take care of the error

without breaking execution, then it can resume execution with the line of

code that generated the error ( Resume), the one after that ( Resume Next),

or at a particular location ( Resume {LineLabel}).

There’s a much better way to manage errors in VB 2005, called structured

exception handling. The rest of this chapter discusses this new way to work

with code errors, and uses the term structured exception handling

throughout, except for the small sections that discuss compatibility with

older error-handling techniques.

Visual Basic Unit 5

Sikkim Manipal University Page No.: 103

5.3 Exceptions in .NET

.NET implements a systemwide, comprehensive approach to exception

handling. As noted in the chapter introduction, instead of an error number,

there is an exception object. This object contains information relevant to the

error, exposed as properties of the object. Later you’ll see a summary of the

properties and the information they expose in a table.

Such an object is an instance of a class that derives from a class named

System.Exception. As shown later, a variety of subclasses of

System.Exception are used for different circumstances.

Important Properties and Methods of an Exception

The Exception class has properties that contain useful information about the

exception, as shown in the following table:

Property Description

HelpLink A string indicating the link to help for this exception

InnerException Returns the exception object reference to an inner (nested) exception

Message A string that contains a description of the error, suitable for displaying to users

Source A string containing the name of an object that generated the error

StackTrace A read-only property that holds the stack trace as a text string. The stack trace is a list of the pending method calls at the point at which the exception was detected. That is, if MethodA called MethodB, and an exception occurred in MethodB, the stack trace would contain both MethodA and MethodB.

TargetSite A read-only string property that holds the method that threw the exception

The two most important methods of the Exception class are as follows:

Method Description

GetBaseException Returns the first exception in the chain

ToString Returns the error string, which might include as much information as the error message, the inner exceptions, and the stack trace, depending on the error

Visual Basic Unit 5

Sikkim Manipal University Page No.: 104

How Exceptions Differ from the Err Object in VB6

Because an exception contains all of the information needed about an error,

structured exception handling does not use error numbers and the Err

object. The exception object contains all the relevant information about the

error.

However, whereas there is only one global Err object in VB6, there are

many types of exception objects in VB 2005. For example, if a divide by

zero is done in code, then an OverflowException is generated. There are

several dozen types of exception classes in VB 2005, and in addition to

using the ones that are available in the .NET Framework, you can inherit

from a class called ApplicationException and then create your own

exception classes.

In .NET, all exceptions inherit from System.Exception. Special-purpose

exception classes can be found in many namespaces. The following table

lists four representative examples of the classes that extend Exception:

Namespace Class Description

System InvalidOperationException Generated when a call to an object method is inappropriate because of the object’s state

System OutOfMemoryException Results when there is not enough memory to carry out an operation

System.XML XmlException Often caused by an attempt to read invalid XML

System.Data DataException Represents errors in ADO.NET components

It is common for an exception class to reside in a namespace with the

classes that typically generate the exception. For example, the

DataException class is in System.Data, with the ADO.NET components that

often generate a DataException instance.

Visual Basic Unit 5

Sikkim Manipal University Page No.: 105

Having many types of exceptions in VB 2005 enables different types of

conditions to be trapped with different exception handlers. This is a major

advance over VB6.

Self Assessment Questions

1. When an unexpected condition occurs, the CLR creates a special object

called an _____.

2. There’s a much better way to manage errors in VB 2005, called _____.

3. In .NET, all exceptions inherit from _____.

5.4 Structured-Exception-Handling Keywords

Structured exception handling depends on several new keywords in VB

2005:

Try – Begins a section of code in which an exception might be

generated from a code error. This section of code is often called a Try

block. In some respects, this would be the equivalent of an On Error

statement in VB6. However, unlike an On Error statement, a Try

statement does not indicate where a trapped exception should be

routed. Instead, the exception is automatically routed to a Catch

statement (discussed next).

Catch – Begins an exception handler for a type of exception. One or

more Catch code blocks follow a Try block, with each Catch block

catching a different type of exception. When an exception is

encountered in the Try block, the first Catch block that matches that type

of exception receives control. A Catch statement is analogous to the line

label used in a VB6 On Error statement, but the ability to route different

types of exceptions to different Catch statements is a radical

improvement over VB6.

Finally – Contains code that runs when the Try block finishes normally,

or when a Catch block receives control and then finishes. That is, the

code in the Finally block always runs, regardless of whether an

exception was detected. Typically, the Finally block is used to close or

dispose of any resources, such as database connections, that might

have been left unresolved by the code that had a problem. There is no

equivalent of a Finally in VB6.

Visual Basic Unit 5

Sikkim Manipal University Page No.: 106

Throw – Generates an exception. This is similar to Err.Raise in VB6. It’s

usually done in a Catch block when the exception should be kicked back

to a calling routine or in a routine that has itself detected an error such

as a bad argument passed in.

The Try, Catch, and Finally Keywords

Here is an example showing some typical simple structured exception

handling code in VB 2005. In this case, the most likely source of an error is

the items argument. If it has a value of zero, then this would lead to dividing

by zero, which would generate an exception.

First, create a Windows Application in Visual Basic 2005 and place a button

on the default Form1 created in the project. In the button’s click event, place

the following two lines of code:

Dim sngAvg As Single

sngAvg = GetAverage(0, 100)

Then put the following function in the form’s code:

Private Function GetAverage(iItems As Integer, iTotal As Integer) as

Single

' Code that might throw an exception is wrapped in a Try block

Try

Dim sngAverage As Single

' This will cause an exception to be thrown if iItems = 0

sngAverage = CSng(iTotal \ iItems)

' This only executes if the line above generated no error

MessageBox.Show("Calculation successful")

Return sngAverage

Catch excGeneric As Exception

' If the calculation failed, you get here

MessageBox.Show("Calculation unsuccessful - exception caught")

Return 0

End Try

End Function

This code traps all the exceptions with a single generic exception type, and

you don’t have any Finally logic. Run the program and press the button. You

Visual Basic Unit 5

Sikkim Manipal University Page No.: 107

will be able to follow the sequence better if you place a breakpoint at the top

of the GetAverage function and step through the lines.

Here is a more complex example that traps the divide-by-zero exception

explicitly. This second version of the GetAverage function (notice that the

name is GetAverage2) also includes a Finally block:

Private Function GetAverage2(iItems As Integer, iTotal As Integer) as

Single

' Code that might throw an exception is wrapped in a Try block

Try

Dim sngAverage As Single

' This will cause an exception to be thrown.

sngAverage = CSng(iTotal \ iItems)

' This only executes if the line above generated no error.

MessageBox.Show("Calculation successful")

Return sngAverage

Catch excDivideByZero As DivideByZeroException

' You'll get here with an DivideByZeroException in the Try block

MessageBox.Show("Calculation generated DivideByZero

Exception")

Return 0

Catch excGeneric As Exception

' You'll get here when any exception is thrown and not caught in

' a previous Catch block.

MessageBox.Show("Calculation failed - generic exception caught")

Return 0

Finally

' Code in the Finally block will always run.

MessageBox.Show("You always get here, with or without an

error")

End Try

End Function

This code contains two Catch blocks for different types of exceptions. If an

exception is generated, then .NET will go down the Catch blocks looking for

a matching exception type. That means the Catch blocks should be

arranged with specific types first and more generic types after.

Visual Basic Unit 5

Sikkim Manipal University Page No.: 108

Place the code for GetAverage2 in the form, and place another button on

Form1. In the Click event for the second button, place the following code:

Dim sngAvg As Single

sngAvg = GetAverage2(0, 100)

Run the program again and press the second button. As before, it’s easier

to follow if you set a breakpoint early in the code and then step through the

code line by line.

The Throw Keyword

Sometimes a Catch block is unable to handle an error. Some exceptions are

so unexpected that they should be ―sent back up the line‖ to the calling

code, so that the problem can be promoted to code that can decide what to

do with it. A Throw statement is used for that purpose.

A Throw statement, like an Err.Raise, ends execution of the exception

handler – that is, no more code in the Catch block after the Throw statement

is executed. However, Throw does not prevent code in the Finally block

from running. That code still runs before the exception is kicked back to the

calling routine.

You can see the Throw statement in action by changing the earlier code for

GetAverage2 to look like this:

Private Function GetAverage3(iItems As Integer, iTotal as Integer) as

Single

' Code that might throw an exception is wrapped in a Try block

Try

Dim sngAverage As Single

' This will cause an exception to be thrown.

sngAverage = CSng(iTotal \ iItems)

' This only executes if the line above generated no error.

MessageBox.Show("Calculation successful")

Return sngAverage

Catch excDivideByZero As DivideByZeroException

' You'll get here with an DivideByZeroException in the Try block.

MessageBox.Show("Calculation generated DivideByZero

Exception")

Visual Basic Unit 5

Sikkim Manipal University Page No.: 109

Throw excDivideByZero

MessageBox.Show("More logic after the throw − never executed")

Catch excGeneric As Exception

' You'll get here when any exception is thrown and not caught in

' a previous Catch block.

MessageBox.Show("Calculation failed - generic exception caught")

Throw excGeneric

Finally

' Code in the Finally block will always run, even if

' an exception was thrown in a Catch block.

MessageBox.Show("You always get here, with or without an

error")

End Try

End Function

Here is some code to call GetAverage3. You can place this code in

another button’s click event to test it out:

Try

Dim sngAvg As Single

sngAvg = GetAverage3(0, 100)

Catch exc As Exception

MessageBox.Show("Back in the click event after an error")

finally

MessageBox.Show("Finally block in click event")

End Try

5.5 Throwing a New Exception

Throw can also be used with exceptions that are created on-the-fly. For

example, you might want your earlier function to generate an

ArgumentException, since you can consider a value of items of zero to be

an invalid value for that argument.

In such a case, a new exception must be instantiated. The constructor

allows you to place your own custom message into the exception. To show

how this is done, let’s change the aforementioned example to throw your

own exception instead of the one caught in the Catch block:

Visual Basic Unit 5

Sikkim Manipal University Page No.: 110

Private Function GetAverage4(iItems As Integer, iTotal as Integer) as

Single

If iItems = 0 Then

Dim excOurOwnException As New _

ArgumentException("Number of items cannot be zero")

Throw excOurOwnException

End If

' Code that might throw an exception is wrapped in a Try block.

Try

Dim sngAverage As Single

' This will cause an exception to be thrown.

sngAverage = CSng(iTotal \ iItems)

' This only executes if the line above generated no error.

MessageBox.Show("Calculation successful")

Return sngAverage

Catch excDivideByZero As DivideByZeroException

' You'll get here with an DivideByZeroException in the Try block.

MessageBox.Show("Calculation generated DivideByZero

Exception")

Throw excDivideByZero

MessageBox.Show("More logic after the thrown - never executed")

Catch excGeneric As Exception

' You'll get here when any exception is thrown and not caught in

' a previous Catch block.

MessageBox.Show("Calculation failed - generic exception caught")

Throw excGeneric

Finally

' Code in the Finally block will always run, even if

' an exception was thrown in a Catch block.

MessageBox.Show("You always get here, with or without an

error")

End Try

End Function

Visual Basic Unit 5

Sikkim Manipal University Page No.: 111

This code can be called from a button with similar code for calling

GetAverage3. Just change the name of the function called to GetAverage4.

This technique is particularly well suited to dealing with problems detected in

property procedures. Property Set procedures often do checking to ensure

that the property is about to be assigned a valid value. If not, throwing a new

ArgumentException (instead of assigning the property value) is a good way

to inform the calling code about the problem.

5.6 The Exit Try Statement

The Exit Try statement will, under a given circumstance, break out of the Try

or Catch block and continue at the Finally block. In the following example,

you are going to exit a Catch block if the value of iItems is 0, because you

know that your error was caused by that problem:

Private Function GetAverage5(iItems As Integer, iTotal as Integer) As

Single

' Code that might throw an exception is wrapped in a Try block.

Try

Dim sngAverage As Single

' This will cause an exception to be thrown.

sngAverage = CSng(iTotal \ iItems)

' This only executes if the line above generated no error.

MessageBox.Show("Calculation successful")

Return sngAverage

Catch excDivideByZero As DivideByZeroException

' You'll get here with an DivideByZeroException in the Try block.

If iItems = 0 Then

Return 0

Exit Try

Else

MessageBox.Show("Error not caused by iItems")

End If

Throw excDivideByZero

MessageBox.Show("More logic after the thrown - never executed")

Catch excGeneric As Exception

Visual Basic Unit 5

Sikkim Manipal University Page No.: 112

' You'll get here when any exception is thrown and not caught in

' a previous Catch block.

MessageBox.Show("Calculation failed - generic exception caught")

Throw excGeneric

Finally

' Code in the Finally block will always run, even if

' an exception was thrown in a Catch block.

MessageBox.Show("You always get here, with or without an

error")

End Try

End Sub

In your first Catch block, you have inserted an If block so that you can

exit the block given a certain condition (in this case, if the overflow

exception was caused by the value of intY being 0). The Exit Try goes

immediately to the Finally block and completes the processing there:

If iItems = 0 Then

Return 0

Exit Try

Else

MessageBox.Show("Error not caused by iItems")

End If

Now, if the overflow exception is caused by something other than division by

zero, then you’ll get a message box displaying Error not caused by iItems.

Nested Try Structures

In some cases, particular lines in a Try block may need special exception

processing. Moreover, errors can occur within the Catch portion of the Try

structures and cause further exceptions to be thrown. For both of these

scenarios, nested Try structures are available. You can alter the example

under the section ―The Throw Keyword‖ to demonstrate the following code:

Private Function GetAverage6(iItems As Integer, iTotal as Integer) As

Single

' Code that might throw an exception is wrapped in a Try block.

Try

Dim sngAverage As Single

Visual Basic Unit 5

Sikkim Manipal University Page No.: 113

' Do something for performance testing....

Try

LogEvent("GetAverage")

Catch exc As Exception

MessageBox.Show("Logging function unavailable")

End Try

' This will cause an exception to be thrown.

sngAverage = CSng(iTotal \ iItems)

' This only executes if the line above generated no error.

MessageBox.Show("Calculation successful")

Return sngAverage

Catch excDivideByZero As DivideByZeroException

' You'll get here with an DivideByZeroException in the Try block.

MessageBox.Show("Error not divide by 0")

Throw excDivideByZero

MessageBox.Show("More logic after the thrown - never executed")

Catch excGeneric As Exception

' You'll get here when any exception is thrown and not caught in

' a previous Catch block.

MessageBox.Show("Calculation failed - generic exception caught")

Throw excGeneric

Finally

' Code in the Finally block will always run, even if

' an exception was thrown in a Catch block.

MessageBox.Show("You always get here, with or without an

error")

End Try

End Function

In the preceding example, you are assuming that a function exists to log an

event. This function would typically be in a common library, and might log

the event in various ways. You will look at logging exceptions in detail later

in the chapter, but a simple LogEvent function might look like this:

Visual Basic Unit 5

Sikkim Manipal University Page No.: 114

Public Function LogEvent(ByVal sEvent As String)

FileOpen(1, "logfile.txt", OpenMode.Append)

Print(1, DateTime.Now & "-" & sEvent & vbCrLf)

FileClose(1)

End Function

In this case, you don’t want a problem logging an event, such as a ―disk full‖

error, to crash the routine. The code for the GetAverage function triggers a

message box to indicate trouble with the logging function.

A Catch block can be empty. In that case, it has a similar effect as On Error

Resume Next in VB6. The exception is ignored. However, execution does

not pick up with the line after the line that generated the error, but instead

picks up with either the Finally block or the line after the End Try if no Finally

block exists.

Self Assessment Questions

4. A block of exception handling statements begin with _____ keyword.

5. _____ keyword is used to handle unexpected errors without executing

further statements in the Catch block.

6. _____ keyword is used to denote the final block in exception handling.

5.7 Using Exception Properties

The previous examples have displayed hard-coded messages into message

boxes, and this is obviously not a good technique for production

applications. Instead, a message box or log entry describing an exception

should provide as much information as possible concerning the problem. To

do this, various properties of the exception can be used.

The most brutal way to get information about an exception is to use the

ToString method of the exception. Suppose that you modify the earlier

example of GetAverage2 to change the displayed information about the

exception like this:

Private Function GetAverage2(ByVal iItems As Integer, ByVal iTotal As

Integer) _

As Single

' Code that might throw an exception is wrapped in a Try block.

Try

Visual Basic Unit 5

Sikkim Manipal University Page No.: 115

Dim sngAverage As Single

' This will cause an exception to be thrown.

sngAverage = CSng(iTotal \ iItems)

' This only executes if the line above generated no error.

MessageBox.Show("Calculation successful")

Return sngAverage

Catch excDivideByZero As DivideByZeroException

' You'll get here with an DivideByZeroException in the Try block.

MessageBox.Show(excDivideByZero.ToString)

Throw excDivideByZero

MessageBox.Show("More logic after the thrown - never executed")

Catch excGeneric As Exception

' You'll get here when any exception is thrown and not caught in

' a previous Catch block.

MessageBox.Show("Calculation failed - generic exception caught")

Throw excGeneric

Finally

' Code in the Finally block will always run, even if

' an exception was thrown in a Catch block.

MessageBox.Show("You always get here, with or without an

error")

End Try

End Function

When the function is accessed with iItems = 0, a message box similar to the

one in Figure 5.1 will be displayed.

Figure 5.1: Output with iItems = 0

The Message Property

The message in the dialog shown in Figure 5.1 is helpful to a developer

because it contains a lot of information, but it’s not something you would

Visual Basic Unit 5

Sikkim Manipal University Page No.: 116

typically want users to see. Instead, a user normally needs to see a short

description of the problem, and that is supplied by the Message property.

If the previous code is changed so that the Message property is used

instead of ToString, then the message box will provide something like what

is shown in Figure 5.2.

Figure 5.2: Output using ToString method

The InnerException and TargetSite Properties

The InnerException property is used to store an exception trail. This comes

in handy when multiple exceptions occur. It’s quite common for an exception

to occur that sets up circumstances whereby further exceptions are raised.

As exceptions occur in a sequence, you can choose to stack your

exceptions for later reference by use of the InnerException property of your

Exception object. As each exception joins the stack, the previous Exception

object becomes the inner exception in the stack.

For simplicity, you’ll start a new code sample, with just a subroutine that

generates its own exception. You’ll include code to add a reference to an

InnerException object to the exception you are generating with the Throw

method.

This example also includes a message box to show what’s stored in the

exception’s TargetSite property. As shown in the results, TargetSite will

contain the name of the routine generating the exception — in this case,

HandlerExample. Here’s the code:

Visual Basic Unit 5

Sikkim Manipal University Page No.: 117

Sub HandlerExample()

Dim intX As Integer

Dim intY As Integer

Dim intZ As Integer

intY = 0

intX = 5

' First Required Error Statement.

Try

' Cause a "Divide by Zero"

intZ = CType((intX \ intY), Integer)

' Catch the error.

Catch objA As System.DivideByZeroException

Try

Throw (New Exception("0 as divisor", objA))

Catch objB As Exception

Dim sError As String

sError = "My Message: " & objB.Message & vbCrLf & vbCrLf

sError &= "Inner Exception Message: " & _

objB.InnerException.Message & vbCrLf & vbCrLf

sError &= "Method Error Occurred: " & objB.TargetSite.Name

MessageBox.Show(sError)

End Try

Catch

Messagebox.Show("Caught any other errors")

Finally

Messagebox.Show(Str(intZ))

End Try

End Sub

As before, you catch the divide-by-zero error in the first Catch block, and the

exception is stored in objA so that you can reference its properties later.

You throw a new exception with a more general message (―0 as divisor‖)

that is easier to interpret, and you build up your stack by appending objA as

the InnerException object using an overloaded constructor for the Exception

object:

Visual Basic Unit 5

Sikkim Manipal University Page No.: 118

Throw (New Exception("0 as divisor", objA))

You catch your newly thrown exception in another Catch statement. Note

how it does not catch a specific type of error:

Catch objB As Exception

Then you construct an error message for the new exception and display it in

a message box:

Dim sError As String

sError = "My Message: " & objB.Message & vbCrLf & vbCrLf

sError &= "Inner Exception Message: " & _

objB.InnerException.Message & vbCrLf & vbCrLf

sError &= "Method Error Occurred: " & objB.TargetSite.Name

MessageBox.Show(sError)

The message box that is produced is shown in Figure 5.3.

Figure 5.3: Message output

First your own message is included, based on the new exception thrown by

your own code. Then the InnerException gets the next exception in the

stack, which is the divide-by-zero exception, and its message is included.

Finally, the TargetSite property gives you the name of the method that threw

the exception. TargetSite is particularly helpful in logs or error reports from

users that are used by developers to track down unexpected problems.

After this message box, the Finally clause displays another message box

that just displays the current value of intZ, which is zero because the divide

failed. This second box also occurs in other examples that follow.

5.8 Source and StackTrace

The Source and StackTrace properties provide the user with information

regarding where the error occurred. This supplemental information can be

Visual Basic Unit 5

Sikkim Manipal University Page No.: 119

invaluable for the user to pass on to the troubleshooter in order to help

resolve errors more quickly. The following example uses these two

properties and shows the feedback when the error occurs:

Sub HandlerExample2()

Dim intX As Integer

Dim intY As Integer

Dim intZ As Integer

intY = 0

intX = 5

' First Required Error Statement.

Try

' Cause a "Divide by Zero"

intZ = CType((intX \ intY), Integer)

' Catch the error.

Catch objA As System.DivideByZeroException

objA.Source = "HandlerExample2"

Messagebox.Show("Error Occurred at :" & _

objA.Source & objA.StackTrace)

Finally

Messagebox.Show(Str(intZ))

End Try

End Sub

The output from the Messagebox statement is very detailed, providing the

entire path and line number where the error occurred, as shown in

Figure 5.4.

Figure 5.4: Output of the above code

Visual Basic Unit 5

Sikkim Manipal University Page No.: 120

Notice that this information is also included in the ToString method

examined earlier (refer to Figure 5.1).

5.9 GetBaseException

The GetBaseException method comes in very handy when you are deep in

a set of thrown exceptions. This method returns the originating exception,

which makes debugging easier and helps keep the troubleshooting process

on track by sorting through information that can be misleading:

Sub HandlerExample3()

Dim intX As Integer

Dim intY As Integer

Dim intZ As Integer

intY = 0

intX = 5

' First Required Error Statement.

Try

' Cause a "Divide by Zero"

intZ = CType((intX \ intY), Integer)

' Catch the error.

Catch objA As System.DivideByZeroException

Try

Throw (New Exception("0 as divisor", objA))

Catch objB As Exception

Try

Throw (New Exception("New error", objB))

Catch objC As Exception

Messagebox.Show(objC.GetBaseException.Message)

End Try

End Try

Finally

Messagebox.Show(Str(intZ))

End Try

End Sub

Visual Basic Unit 5

Sikkim Manipal University Page No.: 121

The InnerException property provides the information that the

GetBaseException method needs, so as your example executes the Throw

statements, it sets up the InnerException property. The purpose of the

GetBaseException method is to provide the properties of the initial

exception in the chain that was produced. Hence,

objC.GetBaseException.Message returns the Message property of the

original OverflowException message even though you’ve thrown multiple

errors since the original error occurred:

Messagebox.Show(objC.GetBaseException.Message)

To put it another way, the code traverses back to the exception caught as

objA and displays the same message as the objA.Message property would,

as shown in Figure 5.5.

Figure 5.5: Message output

5.10 HelpLink

The HelpLink property gets or sets the help link for a specific Exception

object. It can be set to any string value, but is typically set to a URL. If you

create your own exception in code, you might want to set HelpLink to some

URL describing the error in more detail. Then the code that catches the

exception can go to that link. You could create and throw your own custom

application exception with code like the following:

Dim exc As New ApplicationException("A short description of the

problem")

exc.HelpLink = "http://mysite.com/somehtmlfile.htm"

Throw exc

When trapping an exception, the HelpLink can be used to launch a viewer

so the user can see the details about the problem. The following example

shows this in action, using the built-in Explorer in Windows:

Visual Basic Unit 5

Sikkim Manipal University Page No.: 122

Sub HandlerExample4()

Try

Dim exc As New ApplicationException("A short description of the

problem")

exc.HelpLink = "http://mysite.com/somehtmlfile.htm"

Throw exc

' Catch the error.

Catch objA As System.Exception

Shell("explorer.exe " & objA.HelpLink)

End Try

End Sub

This results in launching Internet Explorer to show the page specified by the

URL. Most exceptions thrown by the CLR or the .NET Framework’s classes

have a blank HelpLink property. You should only count on using HelpLink if

you have previously set it to a URL (or some other type of link information)

yourself.

Self Assessment Questions

7. The most brutal way to get information about an exception is to use the

_____ method of the exception.

8. The _____ property is used to store an exception trail.

9. The _____ property gets or sets the help link for a specific Exception

object.

5.11 Summary

.NET implements a systemwide, comprehensive approach to exception

handling.

The Exception class has properties that contain useful information about

the exception.

Try, Catch, Throw, and Finally keywords are used to denote exception

blocks.

The GetBaseException method comes in very handy when you are deep

in a set of thrown exceptions.

The HelpLink property gets or sets the help link for a specific Exception

object. It can be set to any string value, but is typically set to a URL.

Visual Basic Unit 5

Sikkim Manipal University Page No.: 123

5.12 Terminal Questions

1. Describe the concept of Exceptions in .Net environment

2. Describe the structured Exception handling keywords

3. Describe the concept of Source and Stacktrace

5.13 Answers

Self Assessment Questions

1. Exception

2. Structured Exception Handling

3. System.Exception

4. Try

5. Throw

6. Finally

7. ToString

8. InnerException

9. HelpLink

Terminal Questions

1. .NET implements a systemwide, comprehensive approach to exception

handling. As noted in the chapter introduction, instead of an error

number, there is an exception object. This object contains information

relevant to the error, exposed as properties of the object. (Refer Section

5.3)

2. Try, Catch, Throw and Finally keywords are used to handle exceptions.

(Refer Section 5.4)

3. The Source and StackTrace properties provide the user with information

regarding where the error occurred. This supplemental information can

be invaluable for the user to pass on to the troubleshooter in order to

help resolve errors more quickly. (Refer Section 5.8)

Visual Basic Unit 6

Sikkim Manipal University Page No.: 124

Unit 6 Data Access in VB.NET

Structure:

6.1 Introduction

Objectives

6.2 Visual Studio .NET and the Data Form Wizard

6.3 Setting a Connection String

6.4 Opening the Connection

6.5 The Data Adapter

6.6 Structured Query Language

6.7 Filling the DataSet

6.8 Summary

6.9 Terminal Questions

6.10 Answers

6.1 Introduction

This unit introduces the user to data access techniques used in VB.NET. It

works with Visual Studio 2005 and higher versions. The user is expected to

be familiar with the knowledge of databases and concepts of RDBMS as a

pre-requisite to this unit.

Objectives:

After studying this unit, you should be able to:

explain the usage of Visual Studio.Net in data access

describe the Data Form Wizard of Visual Basic.Net

describe the objects of ADO classes.

6.2 Visual Studio .NET and the Data Form Wizard

VB.Net allows you many ways to connect to a database or a data source.

The technology used to interact with a database or data source is called

ADO.NET. The ADO parts stands for Active Data Objects which, admittedly,

doesn’t explain much. But just like System was a Base Class (leader of a

hierarchy, if you like), so is ADO. Forming the foundation of the ADO Base

Class are five other major objects:

Connection

Command

DataReader

Visual Basic Unit 6

Sikkim Manipal University Page No.: 125

DataSet

DataAdapter

We’ll see just what these objects are, and how to use them, as we go along.

But we can make a start on the ADO.NET trail by creating a simple Address

Book project. All we’ll do is see how to use ADO to open up the database

you downloaded, and scroll through each entry.

What we’re going to be doing is to use a Wizard to create a program that

reads the database and allows us to scroll through it. The wizard will create

a Form for us, and allow us to add buttons to the form so that the data can

be edited, updated, and deleted.

We are going to design the form shown in figure 6.1.

Figure 6.1: Example Form

The Connection Object

The Connection Object is what you need if you want to connect to a

database. There are a number of different connection objects, and the one

you use depends largely on the type of database you're connecting to.

Because we're connecting to an Access database, we'll need something

called the OLE DB connection object.

OLE stands for Object Linking and Embedding, and it’s basically a lot of

objects (COM objects) bundled together that allow you to connect to data

Visual Basic Unit 6

Sikkim Manipal University Page No.: 126

sources in general, and not just databases. You can use it, for example, to

connect to text files, SQL Server, email, and a whole lot more.

There are a number of different OLE DB objects (called data providers), but

the one we'll use is called "Jet". Others are SQL Server and Oracle.

So place a button on your form. Change the Name property to btnLoad.

Double click your button to open up the code window. Add the following line:

Dim con As New OleDb.OleDbConnection

If you have the free Visual Basic 2005 Express Edition, you may see a

wiggly line appear under the line of code. This is because you first need to

add a reference to the Data Objects. Here's how to do this:

Click Project from the menu bar

Then click Add Reference

From the dialogue box, select the .NET tab. Scroll down and select the

System.Data item

Click OK.

At the very top of your code window, before Public Class Form 1, type the

following:

Imports System.Data

This will then allow you to work with the various objects in the Database

section. Your coding window will look as shown in figure 6.2:

Figure 6.2: The Code Window

Whichever version you have, though, the variable con will now hold the

Connection Object. Notice that there is a full stop after the OleDB part.

You'll then get a pop up box from where you can select OleDbConnection.

This is the object that you use to connect to an Access database.

Visual Basic Unit 6

Sikkim Manipal University Page No.: 127

6.3 Setting a Connection String

There are Properties and Methods associated with the Connection Object,

of course. We want to start with the ConnectionString property. This can

take many parameters. Fortunately, we only need a few of these.

We need to pass two things to our new Connection Object: the technology

we want to use to do the connecting to our database; and where the

database is. (If your database was password and user name protected, you

would add these two parameters as well. Ours isn't, so we only need the

two.)

The technology is called the Provider; and you use "Data Source" to

specify where your database is. This should be entered on the same line,

and not two as it is below. So add this to your code:

con.ConnectionString = "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data

Source = C:\AddressBook.mdb"

Notice the two parts, separated by a semi-colon:

1st Part: PROVIDER=Microsoft.Jet.OLEDB.4.0

2nd Part: Data Source = C:\AddressBook.mdb

The first part specifies which provider technology we want to use to do the

connecting (JET). The second part, typed after a semi-colon, points to

where the database is. In the above code, the database is on the C drive, in

the root folder. The name of the Access file we want to connect to is called

AddressBook.mdb. (Note that "Data Source" is two words, and not one.)

But your coding window should now look like this:

Private Sub btnLoad_Click(ByVal Sender as Object,_

ByVal e as System.EventArgs) _

Handles btnLoad.Click

Dim con as new OleDb.OleDbConnection

Con.ConnectionString = “Provider = Microsoft.Jet.OLEDB.4.0;

DataSource = C:\AddressBook.mdb”

This assumes that you have copied the AddressBook database over to the

root folder of your C Drive. If you've copied it to another folder, change the

"Data Source" part to match. For example, if you copied it to a folder called

"databases" you'd put this:

Visual Basic Unit 6

Sikkim Manipal University Page No.: 128

Data Source = C:\databases\AddressBook.mdb

In our code , though, ConnectionString is a property of the con variable.

The con variable holds our Connection Object. We're passing the

Connection String the name of a data provider, and a path to the database.

Self Assessment Questions

1. The technology used to interact with a database or data source is called

_____.

2. ADO stands for _____.

3. The _____ object is required to connect to a database.

6.4 Opening the Connection

Now that we have a ConnectionString, we can go ahead and open the

database. This is quite easy - just use the Open method of the Connection

Object:

con.Open( )

Once open, the connection has to be closed again. This time, just use the

Close method:

con.Close( )

Add the following four lines to your code:

con.Open()

MsgBox("A Connection to the Database is now open")

con.Close()

MsgBox("The Connection to the Database is now Closed")

Test out your new code by running your program. Click your button and the

two message boxes should display. If they don't, make sure your Data

Source path is correct. If it isn't, you might see the error message shown in

figure 6.3.

Visual Basic Unit 6

Sikkim Manipal University Page No.: 129

Figure 6.3: Error Message

The error message is a bit on the vague and mysterious side. But what its

saying is that it can't find the path to the database, so it can't Open the

connection. The line con.Open in your code will then be highlighted in

green. You need to specify the correct path to your database. When you do,

you'll see the message boxes from our code, and not the big one above.

Now that we've opened a connection to the database, we need to read the

information from it. This is where the DataSet and the DataAdapter come in.

In the previous section, you learned how to set up a Connection Object. This

was so that you could open a connection to the database itself. But that's

not the end of it. The data from the database needs to be stored

somewhere, so that we can manipulate it.

ADO.NET uses something called a DataSet to hold all of your information

from the database (you can also use a DataTable, if all you want to do is

read information, and not have people write to your database.). But the

DataSet (and Data Table) will hold a copy of the information from the

database.

The DataSet is not something you can draw on your form, like a Button or a

Textbox. The DataSet is something that is hidden from you, and just stored

in memory. Imagine a grid with rows and columns. Each imaginary row of

the DataSet represents a Row of information in your Access database. And

each imaginary column represents a Column of information in your Access

database (called a Field in Access).

This, then, is a DataSet. But what's a Data Adapter?

The Connection Object and the DataSet can't see each other. They need a

go-between so that they can communicate. This go-between is called a

Visual Basic Unit 6

Sikkim Manipal University Page No.: 130

Data Adapter. The Data Adapter contacts your Connection Object, and then

executes a query that you set up. The results of that query are then stored

in the DataSet.

The Data Adapter and DataSet are objects. You set them up like this:

Dim ds As New DataSet

Dim da As OleDb.OleDbDataAdapter

da = New OleDb.OleDbDataAdapter(sql, con)

The code needs a little explaining, though. First, the Data Adapter.

6.5 The Data Adapter

The Data Adapter is a property of the OLEDB object, hence the full stop

between the two:

OleDb.OleDbDataAdapter

We're passing this object to the variable called da. This variable will then

hold a reference to the Data Adapter.

While the second line in the code above sets up a reference to the Data

Adapter, the third line creates a new Data Adapter object. You need to put

two things in the round brackets of the Object declaration: Your SQL string

(which we'll get to shortly), and your connection object. Our Connection

Object is stored in the variable which we've called con. (Like all variable you

can call it practically anything you like. We've gone for something short and

memorable.) You then pass the New Data Adapter to your variable (da for

us): da = New OleDb.OleDbDataAdapter(sql, con)

We need something else, though. The sql in between the round brackets is

the name of a variable. We haven't yet set this up. We'll have a look at SQL

in a moment. But bear in mind what the Data Adapter is doing: Acting as a

go-between for the Connection Object and the Data Set

6.6 Structured Query Language

SQL (pronounced SeeKwel), is short for Structured Query Language, and is

a way to query and write to databases (not just Access). The basics are

quite easy to learn. If you want to grab all of the records from a table in a

database, you use the SELECT word. Like this:

SELECT * FROM Table_Name

Visual Basic Unit 6

Sikkim Manipal University Page No.: 131

SQL is not case sensitive, so the above line could be written:

Select * from Table_Name

But your SQL statements are easier to read if you type the keywords in

uppercase letters. The keywords in the lines above are SELECT and

FROM. The asterisk means "All Records". Table_Name is the name of a

table in your database. So the whole line reads:

"SELECT all the records FROM the table called Table_Name"

You don't need to select all (*) the records from your database. You can just

select the columns that you need. The name of the table in our database is

tblContacts. If we wanted to select just the first name and surname

columns from this table, we can specify that in our SQL String:

SELECT tblContacts.FirstName, tblContacts.Surname FROM

tblContacts

When this SQL statement is executed, only the FirstName and Surname

columns from the database will be returned.

There are a lot more SQL commands, but for our purposes this is enough.

Because we want to SELECT all (*) the records from the table called

tblContacts, we pass this string to the string variable we have called sql:

sql = "SELECT * FROM tblContacts"

So add the following code to your database project:

Dim ds As New DataSet

Dim da As OleDb.OleDbDataAdapter

Dim sql As String

sql = "SELECT * FROM tblContacts"

da = New OleDb.OleDbDataAdapter(sql, con)

(If you're using the free 2005 Express edition, you might see DataSet with a

wiggly line under it. This is because you need to set a reference to

something called System.Xml.dll. To do that, click Project > Add

Reference from the menu bar. The on the NET tab of the dialogue box that

appears, scroll down and click on System.Xml.dll. Then click OK.)

Now that the Data Adapter has selected all of the records from the table in

our database, we need somewhere to put those records - in the DataSet.

Visual Basic Unit 6

Sikkim Manipal University Page No.: 132

6.7 Filling the DataSet

The Data Adapter can Fill a DataSet with records from a Table. You only

need a single line of code to do this:

da.Fill(ds, "AddressBook")

As soon as you type the name of your Data Adapter (da for us), you'll get a

pop up box of properties and methods. Select Fill from the list, then type a

pair of round brackets. In between the round brackets, you need two things:

the Name of your DataSet (ds, in our case), and an identifying name. This

identifying name can be anything you like. But it is just used to identify this

particular Data Adapter Fill. We could have called it "Bacon Sandwich", if we

wanted:

da.Fill(ds, "Bacon Sandwich ")

The code above still works. But it's better to stick to something a little more

descriptive than "Bacon Sandwich"!

Add the new line after the creation of the Data Adapter:

da = New OleDb.OleDbDataAdapter(sql, con)

da.Fill(ds, "AddressBook")

And that's it. The DataSet (ds) will now be filled with the records we

selected from the table called tblContact. There's only one slight problem –

nobody can see the data yet! We'll tackle that in the next part.

In the previous section, we saw what Data Adapters and DataSets were. We

created a Data Adapter so that it could fill a DataSet with records from our

database. What we want to do now is to display the records on a Form, so

that people can see them. So this:

Add two textboxes to your form

Change the Name properties of your textboxes to txtFirstName and

txtSurname

Go back to your code window

Add the following two lines:

txtFirstName.Text = ds.Tables("AddressBook").Rows(0).Item(1)

txtSurname.Text = ds.Tables("AddressBook").Rows(0).Item(2)

You can add them after the line that closes the connection to the database.

Once the DataSet has been filled, a connection to a database can be

closed.

Visual Basic Unit 6

Sikkim Manipal University Page No.: 133

Before the code is explained, run your program and click the button. You

should see "John Smith" displayed in your two textboxes.

So let's examine the code that assigns the data from the DataSet to the

textboxes. The first line was this:

txtFirstName.Text = ds.Tables("AddressBook").Rows(0).Item(1)

It's rather a long line! But after the equals sign, you type the name of your

DataSet (ds for us). After a full stop, select Tables from the popup list. The

Tables property needs something in between round brackets. Quite

bizarrely, this is NOT the name of your database table! It's that identifier you

used with the Data Adapter Fill. We used the identifier "AddressBook". If

we had used "Bacon Sandwich" then we'd put this:

ds.Tables("Bacon Sandwich")

But we didn't, so our code is:

ds.Tables("AddressBook")

Type a full stop and you'll see another list popping up at you. Select Rows

from the list. In between round brackets, you need a number. This is a Row

number from the DataSet. We want the first row, which is row zero in the

DataSet:

ds.Tables("AddressBook").Rows(0)

Type full stop after Rows(0) and the popup list appears again. To identify a

Column from the DataSet, you use Item. In between round brackets, you

type which column you want:

ds.Tables("AddressBook").Rows(0).Item(1)

In our Access database, column zero is used for an ID field. The FirstName

column is the second column in our Access database. Because the Item

collection is zero based, this is item 1 in the DataSet.

You can also refer to the column name itself for the Item property, rather

than a number. So you can do this:

ds.Tables("AddressBook").Rows(0).Item("FirstName")

ds.Tables("AddressBook").Rows(0).Item("Surname")

Visual Basic Unit 6

Sikkim Manipal University Page No.: 134

If you get the name of the column wrong, then VB throws up an error. But an

image might clear things up. The figure 6.4 below shows the items and rows

in the database.

Figure 6.4: Items and Rows in a Database

The image shows which are the Rows and which are the Items in the

Access database Table. So the Items go down and the Rows go across.

However, we want to be able to scroll through the table. We want to be able

to click a button and see the next record. Or click another button and see

the previous record. You can do this by incrementing the Row number. To

see the next record, we'd want this:

txtFirstName.Text = ds.Tables("AddressBook").Rows(1).Item(1)

txtSurname.Text = ds.Tables("AddressBook").Rows(1).Item(2)

The record after that would then be:

txtFirstName.Text = ds.Tables("AddressBook").Rows(2).Item(1)

txtSurname.Text = ds.Tables("AddressBook").Rows(2).Item(2)

So by incrementing and decrementing the Row number, you can navigate

through the records. Let's see how that's done.

You saw in the previous section that you can navigate through the records

of a database by incrementing or decrementing the Row number of the

DataSet. In this section, we're going to see a more practical example of how

to do that. It's better if you start a new project for this. With a new form open,

do the following:

Add two Textboxes. Change the Name properties to txtFirstName and

txtSurname

Add four Buttons. Change the Name and Text properties to these:

Visual Basic Unit 6

Sikkim Manipal University Page No.: 135

Button Name Button Text

btnNext

btnPrevious

btnFirst

btnLast

Next Record

Previous Record

First Record

Last Record

When you're done, your form should look as shown in figure 6.5:

Figure 6.5: Form Window

Press F7 to see your code window, and add the following code to the

Form1 Declarations area:

Declarations area:

Public class Form1

Dim inc as Integer

Dim MaxRows as Integer

Dim con As New OleDb.OleDbConnection

Dim ds as New DataSet

Dim da as OleDb.OleDbDataAdapter

Dim sql as String

(VB 2005 Express Edition users: don't forget to add the references! Click

Project > Add References. Locate System.Data.dll and System.Xml.dll

on the NET tab. Select these items and click OK. Then add Imports

System.Data at the very top of your code window.) Your code will look like

this:

Visual Basic Unit 6

Sikkim Manipal University Page No.: 136

All we're doing here is setting up the variables we need. There's one for the

Connection Object, one for the DataSet, and one for the Data Adapter.

We've also set up two Integer variables (inc and MaxRows), and a String

variable (sql).

When the Form Loads, we can connect to our database, use the data

Adapter to grab some records from the database, and then put these

records into the DataSet. So in the Form1 Load Event, add the following

code:

You've met all the code before, except for these two lines:

MaxRows = ds.Tables("AddressBook").Rows.Count

inc = -1

In the MaxRows variable, we can store how many rows are in the DataSet.

You get how many rows are in your DataSet with Rows.Count:

MaxRows = ds.Tables("AddressBook").Rows.Count

So the Rows property has a Count Method. This simply counts how many

rows are in the DataSet. We're passing that number to a variable called

Visual Basic Unit 6

Sikkim Manipal University Page No.: 137

MaxRows. You can then test what is in the variable, and see if the inc

counter doesn't go past it. You need to do this because VB throws up an

error message if try to go past the last row in the DataSet. (Previous

versions of VB had some called an EOF and BOF properties. These

checked the End of File and Before End of File. These properties have

now gone.)

To navigate through the records, we're going to use that inc variable. We'll

either add 1 to it, or take 1 away. We'll then use the variable for the Rows in

the DataSet. It's better to do this in a Subroutine of your own. So add this

Sub to your code:

Private Sub NavigateRecords()

txtFirstName.Text = ds.Tables("AddressBook").Rows(inc).Item(1)

txtSurname.Text = ds.Tables("AddressBook").Rows(inc).Item(2)

End Sub

The important part is Rows(inc). This moves us through the Rows in the

DataSet. We're then placing the values into the two Textboxes.

The whole of your code so far should look like this (Express Edition user will

have the Imports System.Data line at the very top):

In the next unit, you'll add the code for the buttons.

Visual Basic Unit 6

Sikkim Manipal University Page No.: 138

Self Assessment Questions

4. The _____ will hold a copy of the information from the database.

5. The _____ contacts your Connection Object, and then executes a query

that you set up.

6. In VB.NET, _____ is used to query and write to databases.

6.8 Summary

VB.Net allows you many ways to connect to a database or a data source.

The technology used to interact with a database or data source is called

ADO.NET.

The Connection Object is required to connect to a database.

We need to pass two things to our new Connection Object: the

technology we want to use to do the connecting to our database; and

where the database is.

ADO.NET uses DataSet to hold all of your information from the database.

SQL short for Structured Query Language, is a way to query and write to

databases.

6.9 Terminal Questions

1. Describe the Data form Wizard in Visual Studio.Net.

2. Describe the concept of setting a connection string with an example.

3. What is a Data Adapter? Explain.

6.10 Answers

Self Assessment Questions

1. ADO.NET

2. Active Data Objects

3. Connection

4. DataSet

5. Data Adapter

6. SQL

Terminal Questions

1. VB.Net allows you many ways to connect to a database or a data source.

The technology used to interact with a database or data source is called

ADO.NET. (Refer Section 6.2)

Visual Basic Unit 6

Sikkim Manipal University Page No.: 139

2. There are Properties and Methods associated with the Connection

Object, of course. The ConnectionString property can take many

parameters. (Refer Section 6.3)

3. The Data Adapter is a property of the OLEDB object, hence it is used as

shown below:

OleDb.OleDbDataAdapter

We're passing this object to the variable called da. This variable will then

hold a reference to the Data Adapter. (Refer Section 6.5)

Visual Basic Unit 7

Sikkim Manipal University Page No.: 140

Unit 7 Working with Records in VB.NET

Structure:

7.1 Introduction

Objectives

7.2 Record Navigation

7.3 Add, Update and Delete Records

7.4 Summary

7.5 Terminal Questions

7.6 Answers

7.1 Introduction

This unit introduces the user to access records in VB.NET. Also you will get

familiar with managing records such as adding new records, updating the

existing records and deleting the unwanted records.

Objectives:

After studying this unit, you should be able to:

describe record navigation in VB.NET

add new records

update the existing records

delete unwanted records

7.2 Record Navigation

(i) Move Back One Record at a Time

To move backwards through the DataSet, we need to decrement the inc

counter. This means is deducting 1 from whatever is currently in inc.

But we also need to check that inc doesn't go past zero, which is the first

record in the DataSet. Here's the code to add to your btnPrevious:

If inc > 0 Then

inc = inc - 1

NavigateRecords()

Else

MsgBox("First Record")

End If

Visual Basic Unit 7

Sikkim Manipal University Page No.: 141

So the If statement first checks that inc is greater than zero. If it is, inc gets

1 deducted from. Then the NavigateRecords() subroutine gets called. If inc

is zero or less, then we display a message.

When you've finished adding the code, test your program out. Click the

Previous button first. The message box should display, even though no

records have been loaded into the textboxes. This is because the variable

inc has a value of -1 when the form first loads. It only gets moved on to zero

when the Next button is clicked. You could amend your IF Statement to this:

If inc > 0 Then

inc = inc - 1

NavigateRecords()

ElseIf inc = -1 Then

MsgBox("No Records Yet")

ElseIf inc = 0 Then

MsgBox("First Record")

End If

This new If Statement now checks to see if inc is equal to minus 1, and

displays a message if it does. It also checks if inc is equal to zero, and

displays the "First Record" message box.

(ii) Moving to the Last Record in the DataSet

To jump to the last record in the DataSet, you only need to know how many

records have been loaded into the DataSet - the MaxRows variable in our

code. You can then set the inc counter to that value, but minus 1. Here's the

code to add to your btnLast:

If inc <> MaxRows - 1 Then

inc = MaxRows - 1

NavigateRecords()

End If

The reason we're saying MaxRows - 1 is that the row count might be 5, say,

but the first record in the DataSet starts at zero. So the total number of

records would be zero to 4. Inside of the If Statement, we're setting the inc

counter to MaxRows - 1, then calling the NavigateRecords() subroutine.

That's all we need to do. So run your program. Click the Last button, and

you should see the last record displayed in your textboxes.

Visual Basic Unit 7

Sikkim Manipal University Page No.: 142

(iii) Moving to the First Record in the DataSet

Moving to the first record is fairly straightforward. We only need to set the

inc counter to zero, if it's not already at that value. Then call the Sub:

If inc <> 0 Then

inc = 0

NavigateRecords()

End If

Add the code to your btnFirst. Run your program and test out all of your

buttons. You should be able to move through the names in the database,

and jump to the first and last records.

As yet, though, we don't have a way to add new records, to update records,

or to delete them. Let's do that next.

7.3 Add, Update and Delete Records

In the last section, you learned how to move through the records in your

DataSet, and how to display the records in Textboxes on your form. In this

lesson, we'll see how to add new records, how to delete them and how to

Update a records.

Before we start the coding for these new buttons, it's important to

understand that the DataSet is disconnected from the database. What this

means is that if you're adding a new record, you're not adding it to the

database: you're adding it to the DataSet! Similarly, if you're updating or

Deleting, you are doing it to the DataSet, and NOT to the database. After

you have made all of your changes, you THEN commit these changes to the

database. You do this by issuing a separate command. But we'll see how it

all works.

You'll need to add a few more buttons to your form - five of them. Change

the Name properties of the new Buttons to the following:

btnAddNew

btnCommit

btnUpdate

btnDelete

btnClear

Visual Basic Unit 7

Sikkim Manipal University Page No.: 143

Change the Text properties of the buttons to "Add New Record ", "Commit

Changes", "Update Record ", "Delete Record", and "Clear/Cancel". Your

form might look something like this:

(i) Updating a Record

To reference a particular column (item) in a row of the DataSet, the code is

this:

ds.Tables("AddressBook").Rows(2).Item(1)

That will return whatever is at Item 1 on Row 2.

As well as returning a value, you can also set a value. You do it like this:

ds.Tables("AddressBook").Rows(2).Item(1) = "Jane"

Now Item 1 Row 2 will contain the text "Jane". This won't, however, affect

the database! The changes will just get made to the DataSet. To illustrate

this, add the following code to your btnUpdate:

ds.Tables("AddressBook").Rows(inc).Item(1) = txtFirstName.Text

ds.Tables("AddressBook").Rows(inc).Item(2) = txtSurname.Text

MsgBox("Data updated")

Run your program, and click the Next Record button to move to the first

record. "John" should be displayed in your first textbox, and "Smith" in the

Visual Basic Unit 7

Sikkim Manipal University Page No.: 144

second textbox. Click inside the textboxes and change "John" to "Joan" and

"Smith" to "Smithy". (Without the quotes). Now click your Update Record

button. Move to the next record by clicking your Next Record button, and

then move back to the first record. You should see that the first record is

now "Joan Smithy".

Close down your program, then run it again. Click the Next Record button

to move to the first record. It will still be "John Smith". The data you updated

has been lost! So here, again, is why:

"Changes are made to the DataSet, and NOT to the Database"

To update the database, you need some extra code. Amend your code to

this (the new lines are in bold, red text):

Dim cb As New OleDb.OleDbCommandBuilder(da)

ds.Tables("AddressBook").Rows(inc).Item(1) = txtFirstName.Text

ds.Tables("AddressBook").Rows(inc).Item(2) = txtSurname.Text

da.Update(ds, "AddressBook")

MsgBox("Data updated")

The first new line is this:

Dim cb As New OleDb.OleDbCommandBuilder(da)

To update the database itself, you need something called a Command

Builder. The Command Builder will build a SQL string for you. In between

round brackets, you type the name of your Data Adapter, da in our case.

The command builder is then stored in a variable, which we have called cb.

The second new line is where the action is:

da.Update(ds, "AddressBook")

The da variable is holding our Data Adapter. One of the methods of the

Data Adapter is Update. In between the round brackets, you need the name

of your DataSet (ds, for us). The "AddressBook" part is optional. It's what

we've called our DataSet, and is here to avoid any confusion.

But the Data Adapter will then contact the database. Because we have a

Command Builder, the Data Adapter can then update your database with

the values from the DataSet.

Without the Command Builder, though, the Data Adapter can't do its job. Try

this. Comment out the Command Builder line (put a single quote before the

Visual Basic Unit 7

Sikkim Manipal University Page No.: 145

"D" of Dim). Run your program again, and then try and update a record.

You'll get this error message:

The error is because you haven't got a command builder – a Valid Update

Command. Delete the comment from your Command Builder line and the

error message goes away. You should now be able to make changes to the

database itself (as long as the Access database isn't Read Only).

Try it out. Run your program, and change one of the records. Click the

Update button. Then close the program down, and load it up again. You

should see your new changes displayed in the textboxes.

(ii) Add a New Record

Adding a new record is slightly more complex. First, you have to add a new

Row to the DataSet, then commit the new Row to the Database.

But the Add New Record button on our form is quite simple. The only thing

it does is to switch off other buttons, and clear the textboxes, ready for a

new entry. Here's the code for your Add New Record button:

btnCommit.Enabled = True

btnAddNew.Enabled = False

btnUpdate.Enabled = False

btnDelete.Enabled = False

txtFirstName.Clear()

txtSurname.Clear()

So three buttons are switched off when the Add New Record button is

clicked, and one is switched on. The button that gets switched on is the

Commit Changes button. The Enabled property of btnCommit gets set to

Visual Basic Unit 7

Sikkim Manipal University Page No.: 146

True. But, for this to work, you need to set it to False when the form loads.

So return to your Form. Click btnCommit to select it. Then locate the

Enabled Property in the Properties box. Set it to False. When the Form

starts up, the button will be switched off.

The Clear/Cancel button can be used to switch it back on again. So add this

code to your btnClear:

btnCommit.Enabled = False

btnAddNew.Enabled = True

btnUpdate.Enabled = True

btnDelete.Enabled = True

inc = 0

NavigateRecords()

We're switching the Commit Changes button off, and the other three back

on. The other two lines just make sure that we display the first record again,

after the Cancel button is clicked. Otherwise the textboxes will all be blank.

To add a new record to the database, we'll use the Commit Changes

button. So double click your btnCommit to access its code. Add the

following:

If inc <> -1 Then

Dim cb As New OleDb.OleDbCommandBuilder(da)

Dim dsNewRow As DataRow

dsNewRow = ds.Tables("AddressBook").NewRow()

dsNewRow.Item("FirstName") = txtFirstName.Text

dsNewRow.Item("Surname") = txtSurname.Text

ds.Tables("AddressBook").Rows.Add(dsNewRow)

da.Update(ds, "AddressBook")

MsgBox("New Record added to the Database")

btnCommit.Enabled = False

btnAddNew.Enabled = True

btnUpdate.Enabled = True

btnDelete.Enabled = True

End If

The code is somewhat longer than usual, but we'll go through it.

Visual Basic Unit 7

Sikkim Manipal University Page No.: 147

The first line is an If Statement. We're just checking that there is a valid

record to add. If there's not, the inc variable will be on minus 1. Inside of the

If Statement, we first set up a Command Builder, as before. The next line

is this:

Dim dsNewRow As DataRow

If you want to add a new row to your DataSet, you need a DataRow object.

This line just sets up a variable called dsNewRow. The type of variable is a

DataRow.

To create the new DataRow object, this line comes next:

dsNewRow = ds.Tables("AddressBook").NewRow()

We're just saying, "Create a New Row object in the AddressBook DataSet,

and store this in the variable called dsNewRow." As you can see,

NewRow() is a method of ds.Tables. Use this method to add rows to your

DataSet.

The actual values we want to store in the rows are coming from the

textboxes. So we have these two lines:

dsNewRow.Item("FirstName") = txtFirstName.Text

dsNewRow.Item("Surname") = txtSurname.Text

The dsNewRow object we created has a Property called Item. This is like

the Item property you used earlier. It represents a column in your DataSet.

We could have said this instead:

dsNewRow.Item(1) = txtFirstName.Text

dsNewRow.Item(2) = txtSurname.Text

The Item property is now using the index number of the DataSet columns,

rather than the names. The result is the same, though: to store new values

in these properties. We're storing the text from the textboxes to our new

Row.

We now only need to call the Method that actually adds the Row to the

DataSet:

ds.Tables("AddressBook").Rows.Add(dsNewRow)

To add the Row, you use the Add method of the Rows property of the

DataSet. In between the round brackets, you need the name of your

DataRow (the variable dsNewRow, in our case).

Visual Basic Unit 7

Sikkim Manipal University Page No.: 148

You should know what the rest of the code does. Here's the next line:

da.Update(ds, "AddressBook")

Again, we're just using the Update method of the Data Adapter, just like last

time. The rest of the code just displays a message box, and resets the

button.

But to add a new Row to a DataSet, here's a recap on what to do:

Create a DataRow variable

Create an Object from this variable by using the NewRow() method of

the DataSet Tables property

Assign values to the Items in the new Row

Use the Add method of the DataSet to add the new row

A little more complicated, but it does work! Try your program out. Click your

Add New Record button. The textboxes should go blank, and three of the

buttons will be switched off. Enter a new First Name and Surname, and then

click the Commit Changes button. You should see the message box telling

you that a new record has been added to the database. To see the new

record, close down your program, and run it again. The new record will be

there.

(iii) Delete a Record from a Database

The code to delete a record is a little easier than last time. Double click your

btnDelete and add the following:

Dim cb As New OleDb.OleDbCommandBuilder(da)

ds.Tables("AddressBook").Rows(inc).Delete()

MaxRows = MaxRows - 1

inc = 0

NavigateRecords()

da.Update(ds, "AddressBook")

You've met most of it before. First we set up a Command Builder. Then we

have this line:

ds.Tables("AddressBook").Rows(inc).Delete()

Just as there is an Add method of the DataSet Rows property, so there is a

Delete method. You don't need anything between the round brackets, this

time. We've specified the Row to delete with:

Rows(inc)

Visual Basic Unit 7

Sikkim Manipal University Page No.: 149

The inc variable is setting which particular Row we're on. When the Delete

method is called, it is this row that will be deleted.

However, it will only be deleted from the DataSet. To delete the row from the

underlying database, we have this again:

da.Update(ds, "AddressBook")

The Command Builder, in conjunction with the Data Adapter, will take care

of the deleting. All you need to is call the Update method of the Data

Adapter.

The MaxRows line in the code just deducts 1 from the variable. This just

ensures that the number of rows in the DataSet matches the number we

have in the MaxRows variable.

We also reset the inc variable to zero, and call the NavigateRecords()

subroutine. This will mean that the first record is displayed, after a record

has been deleted.

Try out your program. Click the Next Record button a few times to move to

a valid record. Then click the Delete Record button. The record will be

deleted from the DataSet AND the database. The record that is then

displayed will be the first one.

There's another problem, though: if you click the Delete Record button

before the Next Record button, you'll get an error message. You can add

an If Statement to check that the inc variable does not equal minus 1.

Another thing you can do is to display a message box asking users if they

really want to delete this record. Here's one in action:

To get this in your own programme, add the following code to the very top of

your Delete button code:

If MessageBox.Show("Do you really want to Delete this

Record?", _

Visual Basic Unit 7

Sikkim Manipal University Page No.: 150

"Delete", MessageBoxButtons.YesNo, _

MessageBoxIcon.Warning) = DialogResult.No Then

MsgBox("Operation Cancelled")

Exit Sub

End If

The first three lines of the code are really one line. The underscore has

been used to spread it out, so as to fit on this page.

But we're using the new message box function:

MessageBox.Show()

In between the round brackets, we specifying the message to display,

followed by a caption for the message box. We then have this:

MessageBoxButtons.YesNo

You won't have to type all that out; you'll be able to select it from a popup

list. But what it does is give you Yes and No buttons on your message box.

After typing a comma, we selected the MessageBoxIcon.Warning icon from

the popup list. But you need to check which button the user clicked. This is

done with this:

= DialogResult.No

Again, you select from a popup list. We want to check if the user clicked the

No button. This will mean a change of mind from the user. A value of No will

then be returned, which is what we're checking for in the If Statement.

The code for the If Statement itself is this:

MsgBox("Operation Cancelled")

Exit Sub

This will display another message for the user. But most importantly, the

subroutine will be exited: we don't want the rest of the Delete code to be

executed, if the user clicked the No button.

And that's it for our introduction to database programming. You not only saw

how to construct a database program using the Wizard, but how to write

code to do this yourself. There is an awful lot more to database

programming, and we've just scratched the surface. But in a beginner's

course, that's all we have time for.

Visual Basic Unit 7

Sikkim Manipal University Page No.: 151

Self Assessment Questions

1. The _____ will build a SQL string for you.

2. If you want to add a new row to your DataSet, you need a _____ object.

7.4 Summary

To move backwards through the DataSet, we need to decrement the inc

counter.

Adding a new record is slightly more complex. First, you have to add a

new Row to the DataSet, then commit the new Row to the Database.

To add a new record to the database, we'll use the Commit Changes

button.

7.5 Terminal Questions

1. Describe the concept of record navigation in VB.NET.

2. Describe the process of adding, updating and deleting records with an

example.

7.6 Answers

Self Assessment Questions

1. Command Builder

2. DataRow

Terminal Questions

1. To move backwards through the DataSet, we need to decrement the inc

counter. This means is deducting 1 from whatever is currently in inc.

(Refer Section 7.2)

2. Refer Section 7.3

Visual Basic Unit 8

Sikkim Manipal University Page No.: 152

Unit 8 Arrays in Visual Basic

Structure:

8.1 Introduction

Objectives

8.2 Declaring Arrays in Visual Basic

Fixed-sized Arrays

Multidimensional Arrays

Static and Dynamic Arrays

Arrays within UDTs

8.3 Arrays and Variants

8.4 Assigning and Returning Arrays

8.5 Inserting and Deleting items using Arrays

8.6 Sorting using Arrays

8.7 Control Arrays

8.8 Jagged Arrays

8.8 Summary

8.9 Terminal Questions

8.10 Answers

8.1 Introduction

In the previous unit, we have seen the usage of built in and user defined

data types. These can be used to store only one data type value in one

variable. In this unit, we are going to see the usage of a single variable to

store n number of values of homogenous data type.

An array is a consecutive group of memory locations that all have the same

name and the same type. To refer to a particular location or element in the

array, we specify the array name and the array element position number.

The Individual elements of an array are identified using an index. Arrays

have upper and lower bounds and the elements have to lie within those

bounds. Each index number in an array is allocated individual memory

space and therefore users must evade declaring arrays of larger size than

required. We can declare an array of any of the basic data types including

variant, user-defined types and object variables. The individual elements of

an array are all of the same data type.

Visual Basic Unit 8

Sikkim Manipal University Page No.: 153

Objectives:

After studying this unit, you should be able to:

declare and use various types of arrays

explain arrays and their variants

describe the process of assigning and returning array variables

illustrate the process of inserting and deleting items from arrays

illustrate the process of sorting using arrays

describe and illustrate control and jagged arrays

8.2 Declaring Arrays in Visual Basic

Arrays occupy space in memory. The programmer specifies the array type

and the number of elements required by the array so that the compiler may

reserve the appropriate amount of memory. Arrays may be declared as

Public (in a code module), module or local. Module arrays are declared in

the general declarations using keyword Dim or Private. Local arrays are

declared in a procedure using Dim or Static. Array must be declared

explicitly with keyword "As".

There are two types of arrays in Visual Basic namely:

Fixed-Size Array: The size of array always remains the same-size doesn't

change during the program execution.

Dynamic Array: The size of the array can be changed at the run time- size

changes during the program execution.

8.2.1 Fixed-Size Arrays

When an upper bound is specified in the declaration, a Fixed-array is

created. The upper limit should always be within the range of long data type.

Declaring a fixed-array

Dim numbers(5) As Integer

In the above illustration, numbers is the name of the array, and the number

6 included in the parentheses is the upper limit of the array. The above

declaration creates an array with 6 elements, with index numbers running

from 0 to 5.

If we want to specify the lower limit, then the parentheses should include

both the lower and upper limit along with the To keyword.

Visual Basic Unit 8

Sikkim Manipal University Page No.: 154

Example

Dim numbers (1 To 6) As Integer

In the above statement, an array of 10 elements is declared but with indexes

running from 1 to 6.

A public array can be declared using the keyword Public instead of Dim as

shown below.

Public numbers(5) As Integer

8.2.2 Multidimensional Arrays

Arrays can have multiple dimensions. A common use of multidimensional

arrays is to represent tables of values consisting of information arranged in

rows and columns. To identify a particular table element, we must specify

two indexes: The first (by convention) identifies the element's row and the

second (by convention) identifies the element's column.

Tables or arrays that require two indexes to identify a particular element are

called two dimensional arrays. Note that multidimensional arrays can have

more than two dimensions. Visual Basic supports at least 60 array

dimensions, but most people will need to use more than two or three

dimensional-arrays.

The following statement declares a two-dimensional array 50 by 50 array

within a procedure.

Dim AvgMarks (50, 50)

It is also possible to define the lower limits for one or both the dimensions as

for fixed size arrays. An example for this is given here.

Dim Marks (101 To 200, 1 To 100)

An example for three dimensional-array with defined lower limits is given

below.

Dim Details(101 To 200, 1 To 100, 1 To 100)

8.2.3 Static and Dynamic arrays

Basically, you can create either static or dynamic arrays. Static arrays must

include a fixed number of items, and this number must be known at compile

time so that the compiler can set aside the necessary amount of memory.

You create a static array using a Dim statement with a constant argument:

Visual Basic Unit 8

Sikkim Manipal University Page No.: 155

' This is a static array.

Dim Names(100) As String

Visual Basic starts indexing the array with 0. Therefore, the preceding array

actually holds 101 items.

Most programs don't use static arrays because programmers rarely know at

compile time how many items you need and also because static arrays can't

be resized during execution. Both these issues are solved by dynamic

arrays. You declare and create dynamic arrays in two distinct steps. In

general, you declare the array to account for its visibility (for example, at the

beginning of a module if you want to make it visible by all the procedures of

the module) using a Dim command with an empty pair of brackets. Then you

create the array when you actually need it, using a ReDim statement:

' An array defined in a BAS module (with Private scope)

Dim Customers() As String

...

Sub Main()

' Here you create the array.

ReDim Customer(1000) As String

End Sub

If you're creating an array that's local to a procedure, you can do everything

with a single ReDim statement:

Sub PrintReport()

' This array is visible only to the procedure.

ReDim Customers(1000) As String

' ...

End Sub

If you don't specify the lower index of an array, Visual Basic assumes it to

be 0, unless an Option Base 1 statement is placed at the beginning of the

module. My suggestion is this: Never use an Option Base statement

because it makes code reuse more difficult. (You can't cut and paste

routines without worrying about the current Option Base.) If you want to

explicitly use a lower index different from 0, use this syntax instead:

ReDim Customers(1 To 1000) As String

Visual Basic Unit 8

Sikkim Manipal University Page No.: 156

Dynamic arrays can be re-created at will, each time with a different number

of items. When you re-create a dynamic array, its contents are reset to 0 (or

to an empty string) and you lose the data it contains. If you want to resize an

array without losing its contents, use the ReDim Preserve command:

ReDim Preserve Customers(2000) As String

When you're resizing an array, you can't change the number of its

dimensions nor the type of the values it contains. Moreover, when you're

using ReDim Preserve on a multidimensional array, you can resize only its

last dimension:

ReDim Cells(1 To 100, 10) As Integer

...

ReDim Preserve Cells(1 To 100, 20) As Integer ' This works.

ReDim Preserve Cells(1 To 200, 20) As Integer ' This doesn't.

Finally, you can destroy an array using the Erase statement. If the array is

dynamic, Visual Basic releases the memory allocated for its elements (and

you can't read or write them any longer); if the array is static, its elements

are set to 0 or to empty strings.

You can use the LBound and UBound functions to retrieve the lower and

upper indices. If the array has two or more dimensions, you need to pass a

second argument to these functions to specify the dimension you need:

Print LBound(Cells, 1) ' Displays 1, lower index of 1st

dimension

Print LBound(Cells) ' Same as above

Print UBound(Cells, 2) ' Displays 20, upper index of 2nd

dimension

' Evaluate total number of elements.

NumEls = (UBound(Cells) _ LBound(Cells) + 1) * _

(UBound(Cells, 2) _ LBound(Cells, 2) + 1)

8.2.4 Arrays within UDTs

UDT structures can include both static and dynamic arrays. Here's a sample

structure that contains both types:

Type MyUDT

StaticArr(100) As Long

Visual Basic Unit 8

Sikkim Manipal University Page No.: 157

DynamicArr() As Long

End Type

...

Dim udt As MyUDT

' You must DIMension the dynamic array before using it.

ReDim udt.DynamicArr(100) As Long

' You don't have to do that with static arrays.

udt.StaticArr(1) = 1234

The memory needed by a static array is allocated within the UDT structure;

for example, the StaticArr array in the preceding code snippet takes exactly

400 bytes. Conversely, a dynamic array in a UDT takes only 4 bytes, which

form a pointer to the memory area where the actual data is stored. Dynamic

arrays are advantageous when each individual UDT variable might host a

different number of array items. As with all dynamic arrays, if you don't

dimension a dynamic array within a UDT before accessing its items, you get

an error 9 – "Subscript out of range."

Self Assessment Questions

1. An ___________ is a consecutive group of memory locations that all

have the same name and same type.

2. _____ arrays are declared in the general declarations using keyword

Dim or Private.

3. Visual Basic supports at least ______ array dimensions.

8.3 Arrays and Variants

Visual Basic lets you store arrays in Variant variables and then access the

array items using the Variant variable as if it were an array:

ReDim Names(100) As String, var As Variant

' Initialize the Names array (omitted).

var = Names() ' Copy the array into the Variant.

Print var(1) ' Access array items through the Variant.

Visual Basic Unit 8

Sikkim Manipal University Page No.: 158

You can even create an array of Variant elements on the fly using the Array

function and store it in a Variant variable:

' Arrays returned by the Array() function are zero-based.

Factorials = Array(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880,

3628800)

Likewise, you can pass an array to a procedure that expects a Variant

parameter and then access the elements of the array through that

parameter:

' A polymorphic function that sums the values in any array

Function ArraySum(arr As Variant) As Variant

Dim i As Long, result As Variant

For i = LBound(arr) To UBound(arr)

result = result + arr(i)

Next

ArraySum = result

End Function

The most interesting feature of the preceding routine is that it works

correctly with any type of numeric one-dimensional array. It even works with

String arrays, but in that case you get the concatenation of all items, not

their sum.

This procedure is extremely powerful and reduces the amount of code you

have to write to deal with different kinds of arrays. But you should be aware

that accessing array items through a Variant parameter noticeably slows

down the execution. If you need the best performance, write specific

routines that process specific types of arrays.

You can also pass a multidimensional array to a routine that expects a

Variant parameter. In this case, you can still access the array elements

through the Variants, but if you don't know at compile time how many

dimensions the array has, your routine has to determine that number before

proceeding. You can get this value using a trial-and-error approach:

Visual Basic Unit 8

Sikkim Manipal University Page No.: 159

It's perfectly legal to use the function name inside a function's code as if it

were a local variable, as the previous code snippet does. Often this

technique lets you save a local variable and a final assignment before

exiting the routine, which indirectly makes your code run slightly faster.

Here's a modified ArraySum routine that uses NumberOfDims and works

with both one- and two-dimensional arrays:

Function ArraySum2(arr As Variant) As Variant

Dim i As Long, j As Long, result As Variant

' First check whether we can really work with this array.

Select Case NumberOfDims(arr)

Case 1 ' One-dimensional array

For i = LBound(arr) To UBound(arr)

result = result + arr(i)

Next

Case 2 ' Two-dimensional array

For i = LBound(arr) To UBound(arr)

For j = LBound(arr, 2) To UBound(arr, 2)

result = result + arr(i, j)

Next

Next

Case Else ' Not an array, or too many dimensions

Err.Raise 1001, , "Not an array or more than two dimensions"

End Select

ArraySum2 = result

End Function

' This routine returns the number of dimensions of the array ' passed as an argument, or 0 if it isn't an array. Function NumberOfDims(arr As Variant) As Integer Dim dummy as Long On Error Resume Next Do dummy = UBound(arr, NumberOfDims + 1) If Err Then Exit Do NumberOfDims = NumberOfDims + 1 Loop End Function

Visual Basic Unit 8

Sikkim Manipal University Page No.: 160

Often, if a Variant contains an array, you don't know the basic type of that

array in advance. The VarType function returns the sum of the vbArray

constant (decimal 8192), plus the VarType of the data included in the array.

This lets you test that the array passed to a routine is of a given type:

If VarType(arr) = (vbArray + vbInteger) Then

' Array of integers

ElseIf VarType(arr) = (vbArray + vbLong) Then

' Array of Longs

ElseIf VarType(arr) And vbArray Then

' An array of another type (just tests a bit)

End If

You can also test whether a Variant holds an array using the IsArray

function. When a Variant variable holds an array, the TypeName function

appends a pair of empty parentheses to its result:

Print TypeName(arr) ' Displays "Integer()"

As I've explained, you can either assign an array to a Variant variable or you

can pass an array as a Variant parameter of a procedure. While the two

operations look very similar, they're substantially different. To execute an

assignment, Visual Basic makes a physical copy of the array. As a result,

the Variant variable doesn't point to the original data but to the copy; from

this point on, all the manipulations you do through the Variant variable don't

affect the original array.

Conversely, if you call a procedure and pass an array as a Variant

parameter, no data is physically copied and the Variant simply works as an

alias of the array. You can reorder array items or modify their values, and

your changes are immediately reflected in the original array.

Self Assessment Questions

4. Arrays returned by the Array() function are zero based. (True / False)

5. If you call a procedure and pass an array as a _____ parameter, no data

is physically copied and the Variant simply works as an alias of the

array.

Visual Basic Unit 8

Sikkim Manipal University Page No.: 161

8.4 Assigning and Returning Arrays

Visual Basic adds two important features to arrays. First, you can perform

assignments between arrays. Second, you can write procedures that return

arrays. You can assign arrays only of the same type and only if the target is

a dynamic array. (The latter condition is necessary because Visual Basic

might need to resize the target array.)

ReDim a(10, 10) As Integer

Dim b() As Integer

' Fill the a array with data (omitted).

b() = a() ' This works!

It's no surprise that native assignment commands are always faster than the

corresponding For…Next loops that copy one item at a time. The actual

increment in speed heavily depends on the data type of the arrays and can

vary from 20 percent to 10 times faster. A native assignment between arrays

also works if the source array is held in a Variant. Under Visual Basic 4 and

5, you could store an array in a Variant, but you couldn't do the opposite –

that is, retrieve an array stored in a Variant variable and store it back in an

array of a specific type. This flaw has been fixed in Visual Basic 6:

Dim v As Variant, s(100) As String, t() As String

' Fill the s() array (omitted).

v = s() ' Assign to a Variant.

t() = v ' Assign from a Variant to a dynamic string array.

You often use the capacity to assign arrays to build functions that return

arrays. Notice that pair of brackets at the end of the first line in the following

procedure:

Function InitArray(first As Long, Last As Long) As Long()

ReDim result(first To Last) As Long

Dim i As Long

For i = first To Last

result(i) = i

Next

InitArray = result

End Function

Visual Basic Unit 8

Sikkim Manipal University Page No.: 162

The new capability of returning arrays lets you write highly versatile array

routines. Visual Basic 6 itself includes a few new string functions – namely

Join, Split, and Filter – that rely on it. Here are two examples of what you

can do with this intriguing feature:

Example 1

' Returns a portion of a Long array

' Note: fails if FIRST or LAST are not valid

Function SubArray(arr() As Long, first As Long, last As Long, _

newFirstIndex As Long) As Long()

Dim i As Long

ReDim result(newFirstIndex To last _ first + newFirstIndex) As

Long

For i = first To last

result(newFirstIndex + i - first) = arr(i)

Next

SubArray = result

End Function

Example 2

' Returns an array with all the selected items in a ListBox

Function SelectedListItems(lst As ListBox) As String()

Dim i As Long, j As Long

ReDim result(0 To lst.SelCount) As String

For i = 0 To lst.ListCount - 1

If lst.Selected(i) Then

j = j + 1

result(j) = lst.List(i)

End If

Next

SelectedListItems = result

End Function

Self Assessment Question

6. You can assign arrays only of the same type and only if the target is a

____ array.

Visual Basic Unit 8

Sikkim Manipal University Page No.: 163

8.5 Inserting and Deleting items using Arrays

Some of the most common operations you perform on arrays are inserting

and deleting items, shifting all the remaining elements toward higher indices

to make room or toward lower indices to fill the "hole" a deletion has left.

You usually do this with a For…Next loop, and you can even write generic

array procedures that work with any type of array (with the usual restrictions

about arrays of UDTs and fixed-length strings that can't be passed to a

Variant parameter):

Sub InsertArrayItem(arr As Variant, index As Long, newValue

As Variant)

Dim i As Long

For i = UBound(arr) - 1 To index Step -1

arr(i + 1) = arr(i)

Next

arr(index) = newValue

End Sub

Sub DeleteArrayItem(arr As Variant, index As Long)

Dim i As Long

For i = index To UBound(arr) - 1

arr(i) = arr(i + 1)

Next

' VB will convert this to 0 or to an empty string.

arr(UBound(arr)) = Empty

End Sub

If your application works intensively with arrays, you might find that an

approach based on For…Next loops is too slow. In some cases, you can

considerably speed up these operations by using the RtlMoveMemory API

function, which many Visual Basic programmers know under its popular

alias name, CopyMemory. This function lets you move a block of bytes from

one memory address to another memory address and works correctly even

if the two areas partially overlap.

Visual Basic Unit 8

Sikkim Manipal University Page No.: 164

Here's the code that inserts a new item in an array of Longs:

Private Declare Sub CopyMemory Lib "kernel32" Alias

"RtlMoveMemory" _

(dest As Any, source As Any, ByVal numBytes As Long)

Sub InsertArrayItemLong(arr() As Long, index As Long, newValue

As Long)

' We let VB evaluate the size of each item using LenB().

If index < UBound(arr) Then

CopyMemory arr(index + 1), arr(index), _

(UBound(arr) _ index) * LenB(arr(index))

End If

arr(index) = newValue

End Sub

Sub DeleteArrayItemLong(arr() As Long, index As Long)

If index < UBound(arr) Then

CopyMemory arr(index), arr(index + 1), _

(UBound(arr) _ index) * LenB(arr(index))

End If

arr(index) = Empty

End Sub

Important Note: The prerequisite for using the CopyMemory API function is

that data must be stored in contiguous memory locations, so you absolutely

can't use it to insert or remove elements in String and Object arrays, nor in

arrays of UDTs that contain conventional strings, object references, or

dynamic arrays. (Fixed-length strings and static arrays in UDTs are OK,

though.)

Note that while you can't use the preceding routines for arrays other than

Long arrays, the statements in the procedure body can be recycled for

another data type without any change, thanks to the use of the LenB

function. Therefore, you can derive new array functions that work for other

data types by simply modifying the procedure's name and its parameter list.

Example A function that deletes an item in a Double array by editing just the

first line of code (shown in boldface):

Sub DeleteArrayItemDouble(arr() As Double, index As Long)

' All the other statements here are the same as in

Visual Basic Unit 8

Sikkim Manipal University Page No.: 165

DeleteArrayItemLong

' ...

End Sub

8.6 Sorting using Arrays

Sorting is an operation that you often perform on arrays. As you probably

know, there are dozens of different sort algorithms, each one with its

strengths and weaknesses. We found that the Shell Sort algorithm works

well in most cases, and I've prepared a generic routine that sorts any one-

dimensional array of a data type compatible with the Variant type, either in

ascending or descending order:

Example:

Sub ShellSortAny(arr As Variant, numEls As Long,

descending As Boolean)

Dim index As Long, index2 As Long, firstItem As Long

Dim distance As Long, value As Variant

' Exit if it is not an array.

If VarType(arr) < vbArray Then Exit Sub

firstItem = LBound(arr)

' Find the best value for distance.

Do

distance = distance * 3 + 1

Loop Until distance > numEls

' Sort the array.

Do

distance = distance \ 3

For index = distance + firstItem To numEls + firstItem - 1

value = arr(index)

index2 = index

Do While (arr(index2 - distance) > value) Xor descending

arr(index2) = arr(index2 - distance)

index2 = index2 - distance

If index2 - distance < firstItem Then Exit Do

Loop

arr(index2) = value

Next

Loop Until distance = 1

End Sub

Visual Basic Unit 8

Sikkim Manipal University Page No.: 166

Arrays of Arrays

While you can create two-dimensional arrays in Visual Basic, their structure

isn't really flexible for at least two reasons: All rows in the array must have

the same number of elements, and you can use ReDim Preserve to change

the number of columns but you can't add new rows. The first point is

especially important because it often leads you to declare an array that's far

too large for your needs, thus allocating a lot of memory that in most cases

remains largely unused. You can solve both problems using a structure

known as an array of arrays.

The technique is conceptually simple: Since you can store an array in a

Variant variable, you can build an array of Variants, where each item holds

an array. Each subarray – a row of this pseudo-array – can hold a different

number of elements, and you don't need to use more memory than is strictly

necessary as shown in figure 8.1 below.

Figure 8.1: Array of Arrays

Here's an example, based on an imaginary PIM (Personal Information

Manager) program. In this program, you need to keep track of a list of

appointments for each day of the year. The simplest solution would be to

use an array in which each row corresponds to a day in the year and each

column to a possible appointment. (For the sake of simplicity, let's assume

that each appointment's data can be held in a string.)

ReDim apps(1 To 366, 1 To MAX_APPOINTMENTS) As String

Of course, you now have the problem of setting a reasonable value for the

MAX_APPOINTMENTS symbolic constant. It should be high enough to

Visual Basic Unit 8

Sikkim Manipal University Page No.: 167

account for all possible appointments in a day but not too high because you

might be wasting a lot of memory without any real reason. Let's see how the

array of arrays technique can help us save memory without posing any

artificial limit to your application:

Example:

' A module-level variable

Dim apps(1 To 366) As Variant

' Add an appointment for a given day.

Sub AddNewAppointment(day As Integer, description As

String)

Dim arr As Variant

If IsEmpty(apps(day)) Then

' This is the first appointment for this day.

apps(day) = Array(description)

Else

' Add the appointment to those already scheduled.

arr = apps(day)

ReDim Preserve arr(0 To UBound(arr) + 1) As Variant

arr(UBound(arr)) = description

apps(day) = arr

End If

End Sub

' Extract all the appointments for a given day.

Sub ListAppointments(day As Integer, lst As ListBox)

Dim i As Long

For i = 0 To UBound(apps(1))

lst.AddItem apps(1)(i)

Next

End Sub

In this example, we have kept the code as simple as possible and used an

array of Variant arrays. You could save even more memory if each row of

this array were built using an array of a more specific data type (String, in

this case). Note the special syntax used to address an item in an array of

arrays:

' Change the description for the Nth appointment.

apps(day)(n) = newDescription

Visual Basic Unit 8

Sikkim Manipal University Page No.: 168

Nothing keeps you from extending this concept further, introducing an array

of arrays of arrays, and so on. If you're dealing with arrays in which each

row can vary considerably in length, this approach is going to save you a lot

of memory and, in most cases, improve your overall performance too. A key

feature of an array of arrays is that you can process entire rows of your

pseudo-array as if they were single entities. For example, you can swap

them, replace them, add and delete them, and so on.

' Move the January 1st appointments to January 2nd.

apps(2) = apps(1)

apps(1) = Empty

Finally, an important advantage of this technique is that you can add new

rows without losing the current contents of the array. (Remember that you

can use ReDim Preserve on regular arrays only to modify the number of

columns, not the number of rows.)

' Extend the appointment book for another nonleap year.

ReDim Preserve apps(1 to UBound(apps) + 365) As Variant

Self Assessment Questions

7. The _______ function lets you move a block of bytes from one memory

address to another memory address and works correctly even if the two

areas partially overlap.

8. A key feature of an array of arrays is that you can process entire rows of

your pseudo-array as if they were _____ entities.

8.7 Control Arrays

So far, we've dealt with individual controls, each one with a distinctive name

and a distinct set of properties and events. In addition to these, Visual Basic

embodies the concept of control arrays, in which multiple controls share the

same set of event procedures even though each individual element in the

array can have different values for its properties. A control array can be

created only at design time, and at the very minimum at least one control

must belong to it. You create a control array following one of these three

methods:

You create a control and then assign a numeric, non-negative value to

its Index property; you have thus created a control array with just one

element.

Visual Basic Unit 8

Sikkim Manipal University Page No.: 169

You create two controls of the same class and assign them an identical

Name property. Visual Basic shows a dialog box warning you that

there's already a control with that name and asks whether you want to

create a control array. Click on the Yes button.

You select a control on the form, press Ctrl+C to copy it to the clipboard,

and then press Ctrl+V to paste a new instance of the control, which has

the same Name property as the original one. Visual Basic shows the

warning mentioned in the previous bullet.

Control arrays are one of the most interesting features of the Visual Basic

environment, and they add a lot of flexibility to your programs:

Controls that belong to the same control array share the same set of

event procedures; this often dramatically reduces the amount of code

you have to write to respond to a user's actions.

You can dynamically add new elements to a control array at run time; in

other words, you can effectively create new controls that didn't exist at

design time.

Elements of control arrays consume fewer resources than regular

controls and tend to produce smaller executables. Besides, Visual Basic

forms can host up to 256 different control names, but a control array

counts as one against this number. In other words, control arrays let you

effectively overcome this limit.

The importance of using control arrays as a means of dynamically creating

new controls at run time is somewhat reduced in Visual Basic 6, which has

introduced a new and more powerful capability.

Don't let the term array lead you to think control array is related to VBA

arrays; they're completely different objects. Control arrays can only be one-

dimensional. They don't need to be dimensioned: Each control you add

automatically extends the array. The Index property identifies the position of

each control in the control array it belongs to, but it's possible for a control

array to have holes in the index sequence. The lowest possible value for the

Index property is 0. You reference a control belonging to a control array as

you would reference a standard array item:

Text1(0).Text = ""

Visual Basic Unit 8

Sikkim Manipal University Page No.: 170

Sharing Event Procedures

Event procedures related to items in a control array are easily recognizable

because they have an extra Index parameter, which precedes all other

parameters. This extra parameter receives the index of the element that's

raising the event, as you can see in this example:

Private Sub Text1_KeyPress(Index As Integer, KeyAscii As

Integer)

MsgBox "A key has been pressed on Text1(" & Index & ") control"

End Sub

The fact that multiple controls can share the same set of event procedures

is often in itself a good reason to create a control array. For example, say

that you want to change the background color of each of your TextBox

controls to yellow when it receives the input focus and restore its

background color to white when the user clicks on another field:

Private Sub Text1_GotFocus(Index As Integer)

Text1(Index).BackColor = vbYellow

End Sub

Private Sub Text1_LostFocus(Index As Integer)

Text1(Index).BackColor = vbWhite

End Sub

Control arrays are especially useful with groups of OptionButton controls

because you can remember which element in the group has been activated

by adding one line of code to their shared Click event. This saves code

when the program needs to determine which button is the active one:

' A module-level variable

Dim optFrequencyIndex As Integer

Private Sub optFrequency_Click(Index As Integer)

' Remember the last button selected.

optFrequencyIndex = Index

End Sub

Visual Basic Unit 8

Sikkim Manipal University Page No.: 171

Creating Controls at Run Time

Once you have created a control array at design time, even with just one

item, it's straightforward to create new items at run time using the Load

command:

' Suppose you created Text(0) at design time.

Load Text1(1)

' Move the new control where you need it, and resize it.

Text1(1).Move 1200, 2000, 800, 350

' Set other properties as required.

Text1(1).MaxLength = 10

...

' Finally make it visible.

Text1(1).Visible = True

The Load command creates the new control with exactly the same set of

properties that the first item of the array – Text1(0) in the preceding example

– had at design time, including the position on the form. The only exception

to this rule is that the Visible property for a control created in this way is

always False because Visual Basic correctly expects that you want to move

the new control to a different position before making it visible. Once you

have dynamically added a control, it belongs to the control array and can be

treated exactly like those controls created at design time.

You can remove controls from a control array using the Unload command,

as in the following line of code:

Unload Text(1)

You can unload only controls that were added dynamically at run time; if you

use the Unload command on an item of the array that had been created at

design time, an error occurs. If you unload an item and then reload an item

with the same index, you're actually creating a brand-new instance, which

inherits its properties, size, and position from the first element in the array.

Iterating on the Items of a Control Array

Control arrays often let you save many lines of code because you can

execute the same statement, or group of statements, for every control in the

array without having to duplicate the code for each distinct control. For

Visual Basic Unit 8

Sikkim Manipal University Page No.: 172

example, you can clear the contents of all the items in an array of TextBox

controls as follows:

For i = txtFields.LBound To txtFields.UBound

txtFields(i).Text = ""

Next

Here you're using the LBound and UBound methods exposed by the control

array object, which is an intermediate object used by Visual Basic to gather

all the controls in the array. In general, you shouldn't use this approach to

iterate over all the items in the array because if the array has holes in the

Index sequence an error will be raised. A better way to loop over all the

items of a control array is using the For Each statement:

Dim txt As TextBox

For Each txt In txtFields

txt.Text = ""

Next

A third method exposed by the control array object, Count, returns the

number of elements it contains. It can be useful on several occasions (for

example, when removing all the controls that were added dynamically at run

time):

' This code assumes that txtField(0) is the only control that was

' created at design time (you can't unload it at run time).

Do While txtFields.Count > 1

Unload txtFields(txtFields.UBound)

Loop

8.8 Jagged Arrays

Definition – 1: An array of which each element is itself an array is called an

array of arrays, or a jagged array.

Definition – 2: An array of which each element is itself an array is called an

array of arrays, or a jagged array.

Note: Having arrays as elements is not the same thing as a

multidimensional array, which has more than one index on a single array.

Sometimes the data structure in your application is two-dimensional but not

rectangular. For example, you might have an array of months, each element

Visual Basic Unit 8

Sikkim Manipal University Page No.: 173

of which is an array of days. Since different months have different numbers

of days, the elements do not form a rectangular two-dimensional array. In

such a case, you can use a jagged array instead of a multidimensional

array.

Example:

The following example declares an array variable to hold an array of arrays

with elements of the Double Data Type (Visual Basic). Each element of the

array sales is itself an array that represents a month. Each month array

holds values for each day in that month.

The New clause in the declaration of sales sets the array variable to a

12-element array, each element of which is of type Double(), an array of

Double elements. The For loop then determines how many days are in

each month this year (Year(Now)), and sets the corresponding element of

sales to a Double array of the appropriate size.

In the previous example, the jagged array saves seven elements (six in a

leap year) as compared to a two-dimensional array. In a more extreme case

the memory savings could be significant.

When you initialize a jagged array variable, you can specify the dimension

lengths only for the top-level array. There are several ways you can do this:

Initializing Jagged Array Variables

In the array variable declaration, specify the top-level index upper bound

inside the first pair of parentheses, separated by commas. The following

example declares and creates a variable to hold a jagged array of Byte

elements, specifying only the top-level upper bound.

Dim rainfall(11)() As Byte

Following the execution of this statement, the array in variable rainfall holds

12 elements, each of which is an empty array of Byte elements.

Or

Dim sales()() As Double = New Double(11)() {} Dim month As Integer Dim days As Integer For month = 0 To 11 days = DateTime.DaysInMonth(Year(Now), month + 1) sales(month) = New Double(days - 1) {}

Next month

Visual Basic Unit 8

Sikkim Manipal University Page No.: 174

In the New clause, specify the top-level index upper bound inside the

first pair of parentheses, and supply empty braces ({}). The following

example declares and creates a variable to hold a jagged array of Short

elements, specifying only the top-level upper bound.

Dim snowfall()() As Short = New Short(11)() {}

Following the execution of this statement, the array in variable snowfall

holds 12 elements, each of which is an empty array of Short elements.

Or

In the New clause, specify the top-level index upper bound inside the

parentheses, and supply the element values inside the braces ({}). The

following example declares, creates, and initializes a variable to hold a

jagged array of Char elements, specifying the top-level upper bound and

the values. Note the nested New clauses to initialize the bottom-level

arrays.

Dim decodeValues()() As Char = New Char(1)() {New Char()

{"a"c, "b"c}, New Char() {"p"c, "q"c}}

Following the execution of this statement, the array in variable

decodeValues holds two elements, each of which is a Char array of length 1

with the element at index 0 holding an initialized value. If you supply both

the top-level upper bound and the values, you must include a value for

every top-level element from index 0 through the upper bound.

Or

In the New clause, omit the top-level parentheses and supply the

element values inside the braces ({}). The following example declares,

creates, and initializes a variable to hold a jagged array of Byte

elements, specifying only the element values. Note the two levels of

braces in the New clause.

Dim firstValues()() As Byte = {New Byte() {2, 1}, New Byte() {3, 0}}

Following the execution of this statement, the array in variable irstValues

has length 2, with elements firstValues(0) and firstValues(1). Each of the

elements is initialized to a two-element Byte array, the first with element

values 2 and 1 and the second with element values 3 and 0.

Self Assessment Questions

9. A _____ array can be created only at design time, and at the very

minimum at least one control must belong to it.

Visual Basic Unit 8

Sikkim Manipal University Page No.: 175

10. When you initialize a jagged array variable, you can specify the

dimension lengths only for the ____ array.

8.9 Summary

This unit has covered the following topics:

Declaring Arrays in Visual Basic

An array is a consecutive group of memory locations that all have the same

name and the same type. To refer to a particular location or element in the

array, we specify the array name and the array element position number.

Arrays occupy space in memory. Arrays have upper and lower bounds.

Arrays and Variants

Arrays can be stored in variant variables. It also discusses about passage of

multidimensional arrays to routines expecting variant parameters. You can

create an array of Variant elements on the fly using the Array function and

store it in a Variant variable.

Assigning and Returning Arrays

You can perform assignments between arrays. You can write procedures

that return arrays. You can assign arrays only of the same type and only if

the target is a dynamic array.

Inserting and deleting items using Arrays

The insertion and deletion of items in an array is carried out by shifting all

the remaining elements toward higher indices to make room or toward lower

indices to fill the "hole" a deletion has left. You can do this with a For…Next

loop, and you can even write generic array procedures that work with any

type of array.

Sorting using Arrays

Sorting is an operation that you often perform on arrays. As you probably

know, there are dozens of different sort algorithms, each one with its

strengths and weaknesses. The Shell Sort algorithm on a single

dimensional array has been listed here

Control Arrays

Visual Basic embodies the concept of control arrays, in which multiple

controls share the same set of event procedures even though each

individual element in the array can have different values for its properties. A

Visual Basic Unit 8

Sikkim Manipal University Page No.: 176

control array can be created only at design time, and at the very minimum at

least one control must belong to it.

Jagged Arrays

An array of which each element is itself an array is called an array of arrays,

or a jagged array. Note that having arrays as elements is not the same thing

as a multidimensional array, which has more than one index on a single

array.

8.10 Terminal Questions

1. Describe the theory behind declaring arrays in VB.Net.

2. Explain the usage of variants in VB.Net

3. Explain the application of control arrays with sample code.

4. Describe the usage of Jagged Arrays

8.11 Answers

Self Assessment Questions

1. array

2. Module

3. 60

4. True

5. Variant

6. dynamic

7. Copy Memory

8. single

9. control

10. top-level

Terminal Questions

1. Arrays may be declared as Public (in a code module), module or local.

Module arrays are declared in the general declarations using keyword

Dim or Private. Local arrays are declared in a procedure using Dim or

Static. Array must be declared explicitly with keyword "As". (Refer

Section 8.2)

2. Visual Basic lets you store arrays in Variant variables and then access

the array items using the Variant variable as if it were an array:

Visual Basic Unit 8

Sikkim Manipal University Page No.: 177

ReDim Names(100) As String, var As Variant

' Initialize the Names array (omitted).

var = Names() ' Copy the array into the Variant.

Print var(1) ' Access array items through the Variant.

You can even create an array of Variant elements on the fly using the

Array function and store it in a Variant variable:

' Arrays returned by the Array() function are zero-based.

Factorials = Array(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880,

3628800)

(Refer Section 8.3)

3. Visual Basic embodies the concept of control arrays, in which multiple

controls share the same set of event procedures even though each

individual element in the array can have different values for its

properties. A control array can be created only at design time, and at the

very minimum at least one control must belong to it. (Refer Section 8.7)

4. An array of which each element is itself an array is called an array of

arrays, or a jagged array. Note that having arrays as elements is not the

same thing as a multidimensional array, which has more than one index

on a single array. (Refer Section 8.8)

Visual Basic Unit 9

Sikkim Manipal University Page No.: 178

Unit 9 ImageList and TreeView Controls

Structure:

9.1 Introduction

Objectives

9.2 The ImageList Control

Adding Images

Extracting and Drawing Images

Extracting Individual Images

Creating Transparent Images

Using the Draw Method

Creating Composite Images

9.3 The TreeView Control

Setting Design-Time Properties

Run-Time Operations

Adding Node objects

Appearance and Visibility

Showing information about a Node

Editing Node Text

Using Check Boxes

9.4 Summary

9.5 Terminal Questions

9.6 Answers

9.1 Introduction

In the previous units, we have seen the basic programming techniques

using normal variables, programming loops, and record sets. In this unit, we

describe the features of all the Windows common controls included in

MsComCtr.ocx, To test the code presented here, you first make the controls

available to your Visual Basic environment. To do so, execute the

Components command from the Project menu (or just press the Ctrl+T key

combination) to display the Components dialog box similar to the one in

Figure 9.1, and then select the OCXs that interest you, as shown in

Figure 9.2.

When you load into the Visual Basic 6 environment a project built with a

previous version of the language that contains references to older versions

Visual Basic Unit 9

Sikkim Manipal University Page No.: 179

of Windows common controls, a message box appears asking whether you

want to upgrade those controls with their newer versions.

For the maximum compatibility with existing applications, you might decide

to continue to use the older controls, even though upgrading to the newer

versions is the best choice if you want to improve the application's user

interface and functionality. You can turn this warning off by deselecting the

Upgrade ActiveX Controls check box on the General tab of the Project

Properties dialog box.

Figure 9.1: The Components dialog box, with all the Windows common

controls OCXs selected

Figure 9.2: The Common Controls in the Toolbox

Visual Basic Unit 9

Sikkim Manipal University Page No.: 180

Objectives:

After studying this unit, you should be able to:

describe the usage of ImageList control in Windows Programming

describe the process of drawing and extracting images using ImageList

control

describe and illustrate the TreeView control and its importance in

designing the user interfaces

explain the run time operations on TreeView control

9.2 The ImageList Control

The ImageList control is most often used as a container for images and

icons that are employed by other controls, such as TreeView, ListView,

TabStrip, and ImageCombo controls. For this reason, it makes sense to

describe it before any other controls. The ImageList control is invisible at run

time, and to display one of the images it contains you must draw it on a

form, a PictureBox control, or an Image control, or associate it with another

control.

Using the ImageList control as a repository for images that are then used by

other controls offers a number of advantages. Without this control, in fact,

you would have to load images from disk at run time using a LoadPicture

function, which slows down execution and increases the number of files to

be distributed with your program, or an array of Image controls, which slows

down form loading. It's much easier and more efficient to load all the images

in the ImageList control at design time and then refer to them from the other

controls or in source code.

9.2.1 Adding Images

The ImageList control exposes a ListImages collection, which in turn

contains a number of ListImage objects. Each ListImage item holds an

individual image. As with any collection, an individual ListImage object can

be referenced through its numerical index or its string key (if it has one).

Each ListImage object can hold an image in one of the following graphic

formats: bitmap (.bmp), icon (.ico), cursor (.cur), JPEG (.jpg), or GIF (.gif).

The latter two formats weren't supported by the ImageList control distributed

with Visual Basic 5.

Visual Basic Unit 9

Sikkim Manipal University Page No.: 181

Adding Images at Design Time

Adding images at design-time is easy. After you place an ImageList control

on a form, right-click on it, select the Properties command from the pop-up

menu, and switch to the Images tab, as shown in Figure 9.3.

All you have to do now is click on the Insert Picture button and pick up your

images from disk. You should associate a string key with each image so that

you can refer to it correctly later, even if you add or remove other images in

the future (which would affect its numerical index).

Of course, all string keys must be unique in the collection. You can also

specify a string for the Tag property of an image, for example, if you want to

provide a textual description of the image or any other information

associated with this image. Visual Basic never directly uses this property, so

you're free to store any string data in it.

Figure 9.3: The Images tab of the Properties window of an ImageList control

Images added to the ListImages collection can be of any size, with a caveat:

If you're going to use these images inside another common control, all the

images after the first one will be resized and stretched to reflect the size of

the first image added to the control. This isn't an issue if you're going to

display these images on a form, a PictureBox control, or an Image control.

If the ImageList control doesn't contain any images, you can set the size you

want the images to be in the General tab of the Properties dialog box. Trying

to do this when the control already contains one or more ListImage items

raises an error.

Visual Basic Unit 9

Sikkim Manipal University Page No.: 182

Adding Images at Run Time

Adding images at run time requires you to use the Add method of the

ListImages collection, the syntax of which is the following:

Add([Index], [Key], [Picture]) As ListImage

If you omit the Index argument, you add the new image at the end of the

collection. The following code creates a new ListImage item and associates

it with a bitmap loaded from disk:

Dim li As ListImage

Set li = ImageList1.ListImages.Add(, "Cut", _

LoadPicture("d:\bitmaps\cut.bmp"))

You don't need to assign the result value of the Add method to a ListImage

object unless you want to assign a string to the Tag property of the object

just created. Even in that case, you can do without an explicit variable:

With ImageList1.ListImages.Add(, "Cut",

LoadPicture("d:\bitmaps\cut.bmp"))

.Tag = "The Cut icon"

End With

You can remove individual ListImage objects (added either at design time or

at run time) by using the Remove method of the ListImages collection.

' You can use a numerical index or a string key

' to remove the associated image.

ImageList1.ListImages.Remove "Cut"

You can also remove all the images in one operation by using the

collection's Clear method:

' Remove all images.

ImageList1.ListImages.Clear

You can learn the size of the images currently stored in the control by using

the ImageList's ImageWidth and ImageHeight properties. These properties

are in pixels and can be written to only if the ListImages collection is empty;

after you add the first image, they become read-only properties.

9.2.2 Extracting and Drawing Images

If you associate an ImageList control with another common control, you

usually don't have to worry about extracting and showing individual images

because everything is done automatically for you. But if you want to

Visual Basic Unit 9

Sikkim Manipal University Page No.: 183

manually display or print images, you have to learn how to use a few

properties and methods from the ImageList control and its ListImage

dependent objects.

9.2.3 Extracting Individual Images

Each ListImage object exposes a Picture property, which lets you extract the

image and assign it to another control, typically a PictureBox or Image

control:

Set Picture1.Picture = ImageList1.ListImages("Cut").Picture

In general, you can use the Picture property of a ListImage object whenever

you would use the Picture property of a PictureBox or an Image control, as

in the following example:

' Save an image to a disk file.

SavePicture ImageList1.ListImages("Cut").Picture, "C:\cut.bmp"

' Display an image on the current form, zooming it by a factor

' of 4 along the X-axis, and 8 along the Y-axis.

With ImageList1

PaintPicture .ListImages("Cut").Picture, 0, 0, _

ScaleX(.ImageWidth, vbPixels) * 4, ScaleY(.ImageHeight,

vbPixels) * 8

End With

Using the PaintPicture method, you can display any ListImage object on a

form or in a PictureBox control, or you can print it to the Printer object.

ListImage objects also expose an ExtractIcon method, which creates an

icon out of the image and returns it to the caller. You can therefore use this

method whenever an icon is expected, as in this code:

Form1.MouseIcon = ImageList1.ListImages("Pointer").ExtractIcon

Unlike standard collections, keys in the ListImages collection are dealt with

in a case-sensitive way. In other words, "Pointer" and "pointer" are assumed

to be different items.

9.2.4 Creating Transparent Images

The ImageList control has a MaskColor property whose value determines

the color that should be considered transparent when you're performing

graphical operations on individual ListImage objects or when you're

Visual Basic Unit 9

Sikkim Manipal University Page No.: 184

displaying images inside other controls. By default, this is the gray color

(&HC0C0C0), but you can change it both at design time in the Color tab of

the Properties dialog box and at run time via code.

When a graphical operation is performed, none of the pixels in the image

that are the color defined by MaskColor are transferred. To actually display

transparent images, however, you must ensure that the UseMaskColor

property is set to True, which is its default value. You can modify this value

in the General tab of the Properties dialog box or at run time via code:

' Make white the transparent color.

ImageList1.MaskColor = vbWhite

ImageList1.UseMaskColor = True

9.2.5 Using the Draw Method

ListImage objects support the Draw method, which has the following syntax:

Draw hDC, [x], [y], [Style]

where hDC is the handle of a device context (typically the value returned by

the hDC property of a form, a PictureBox control, or the Printer object) and x

and y are the coordinates in pixels where the image should be displayed in

the target object. Style is one of the following values: 0-imlNormal (default,

draw the image without any change), 1-imlTransparent (use the MaskColor

property to account for transparent areas), 2-imlSelected (draw the image

dithered with the system highlight color), or 3-imlFocus (as imlSelected, but

create a hatched effect to indicate that the image has the focus):

' Show an image in the upper left corner of a PictureBox control.

ImageList1.ListImages("Cut").Draw Picture1.hDC, 0, 0

9.2.6 Creating Composite images

The ImageList control also includes the ability to create composite images

by overlaying two individual images held in ListImage objects. This can be

accomplished using the Overlay method. Figure 9.4 shows two individual

images and then what you can get by overlaying the second one on the first

one:

PaintPicture ImageList1.ListImages(1).Picture, 0, 10, 64, 64

PaintPicture ImageList1.ListImages(2).Picture, 100, 10, 64, 64

PaintPicture ImageList1.Overlay(1, 2), 200, 10, 64, 64

Visual Basic Unit 9

Sikkim Manipal University Page No.: 185

Figure 9.4: The effect of the Overlay method

The Overlay method implicitly uses the MaskColor property to determine

which color is to be considered as the transparent color, so you must ensure

that the UseMaskColor property is set to True.

Self Assessment Questions

1. To execute the Components command from the Project menu press the

______ key combination to display the Components dialog box.

2. The ____ control is invisible at run time.

3. As with any collection, an individual ________ object can be referenced

through its numerical index or its string key (if it has one).

9.3 The TreeView Control

The TreeView control is probably the first Windows common control that

users become acquainted with because it's the control Windows Explorer is

based on. Basically, the TreeView control displays a hierarchy of items. A

plus sign beside an item indicates that it has one or more child items. An

item that has child items can be expanded to show them or collapsed to

hide them. This can be done interactively by the user or via code.

The Visual Basic 6 version of the TreeView control has a number of

improvements and now supports check boxes beside each item and full row

selection. Moreover, individual nodes can have different Bold, Foreground,

and Background attributes.

The TreeView control exposes a Nodes collection, which in turn includes all

the Node objects that have been added to the control. Each individual Node

object exposes a number of properties that let you define the look of the

control. Typically, a TreeView control has one single root Node object, but

you can also create multiple Node objects at the root level.

Visual Basic Unit 9

Sikkim Manipal University Page No.: 186

9.3.1 Setting Design-Time Properties

Immediately after creating a TreeView control on a form, you should display

its Properties dialog box (shown in Figure 9.5), which you do by right-

clicking on the control and selecting the Properties menu item. Of course,

you can also set properties that appear in this page at run time, but you

rarely need to change the appearance of a TreeView control once it has

been displayed to the user.

The Style property affects which graphical elements will be used inside the

control. A TreeView control can display four graphical elements: the text

associated with each Node object, the picture associated with each Node

object, a plus or minus sign beside each Node object (to indicate whether

the Node is in collapsed or expanded state), and the lines that go from each

Node object to its child objects.

The Style property can be assigned one of eight values, each one

representing a different combination of these four graphical elements. In

most cases, you use the default value, 7-tvwTreelinesPlusMinusPictureText,

which displays all graphical elements.

Fig. 9.5: The General tab of the Properties dialog box of a TreeView control

The LineStyle property affects how lines are drawn. The value

0-tvwTreeLines doesn't display lines among root Node objects (this is the

default setting), whereas the value 1-tvwRootLines also displays lines

among all root Nodes and makes them appear as if they were children of a

Visual Basic Unit 9

Sikkim Manipal University Page No.: 187

fictitious Node located at an upper level. The Indentation property states the

distance in twips between vertical dotted lines.

The LabelEdit property affects how the end user can modify the text

associated with each Node object. If it's assigned the value 0-tvwAutomatic

(the default), the end user can edit the text by clicking on the Node at run

time; if it's assigned the value 1-tvwManual, the edit operation can be

started only programmatically, by your issuing a StartLabelEdit method.

The ImageList combo box lets you select which ImageList control will be

used to retrieve the images of individual Node objects. The combo box lists

all the ImageList controls located on the current form.

You can associate a TreeView control (or any control) with an ImageList

control located on another form by making the assignment at run time, as

shown in this code:

This technique allows you to use a group of bitmaps and icons in all the

forms of your application without having to duplicate them and thus shrink

the size of the EXE file. This way, you save memory and resources at run

time.

The HideSelection property determines whether the selected Node object

will continue to be highlighted when the TreeView control loses the focus.

The PathSeparator property states which character or string should be used

in the FullPath property of the Node object. The default value for the

PathSeparator property is the backslash character. For example, if you have

a root Node labeled "Root" and a child Node labeled "FirstChild", the

FullPath property of the child Node will be "Root\FirstChild".

The Sorted property states whether Nodes in the control are automatically

sorted in alphabetical order. The documentation omits an important detail:

This property affects only how root Node objects are sorted but has no

effect on the order of child Node objects at lower levels. If you want all the

branches of the tree to be sorted, you should set the Sorted properties of all

individual Node items to True.

Private Sub Form_Load() Set TreeView1.ImageList = AnotherForm.ImageList1 End Sub

Visual Basic Unit 9

Sikkim Manipal University Page No.: 188

The TreeView control that comes with Visual Basic 6 adds a few interesting

properties not available in previous versions of the language. The

FullRowSelect property, if True, causes a Node of the control to be selected

if the user clicks anywhere on its row. (By default, this property is False, in

which case an item can be selected only with a click over it or its plus or

minus symbol.)

If you set the Checkboxes property to True, a check box appears beside

each Node object so that the end user can select multiple Node objects.

By default, you need to double-click on Node items to expand or collapse

them (or click on the plus or minus sign, if present), and you can expand

and collapse any number of tree branches independently of one another.

But if you set the SingleSel property to True, the control's behavior is

different: You expand and collapse items with a single click – that is, as

soon as you select them. Moreover, when you expand a Node, the item that

was previously expanded is automatically collapsed.

The Scroll property determines whether the TreeView control displays a

vertical or horizontal scroll bar if necessary. The default value is True, but

you can set it to False to disable this behavior (even though, honestly, I

can't find a reason why you would want to do that).

Finally the HotTracking property lets you create a Web-like user interface. If

you set this property to True, the cursor changes into a hand when the

mouse passes over the Node object and the TreeView control underlines

the Node's Text property.

9.3.2 Run-Time Operations

To fully exploit the potential of the TreeView control, you must learn to deal

with the Nodes collections and the many properties and methods of Node

objects.

9.3.3 Adding Node objects

One of the shortcomings of the TreeView control is that you can't add items

at design time as you can with ListBox and ComboBox controls. You can

add Node objects only at run time using the Add method of the Nodes

collection.The Add method's syntax is the following:

Visual Basic Unit 9

Sikkim Manipal University Page No.: 189

Relative and Relationship indicate where the new Node should be inserted.

Key is its string key in the Nodes collection, Text is the label that will appear

in the control, and Image is the index or the string key in the companion

ImageList control of the image that will appear beside the Node.

SelectedImage is the index or key of the image that will be used when the

Node is selected. For example, if you're creating a TreeView control that

mimics Windows Explorer and its directory objects, you might write

something like this:

To place the new Node in a given position in the tree, you must provide the

first two arguments. The first argument specifies an existing item in the

Nodes collection by its numerical index or string key; the second argument

states the relationship between the Node being added and its relative. Such

a relationship can be 0-tvwFirst, in which the new Node becomes the first

item at the level of its relative – in other words, it becomes the first sibling of

the relative Node.

Or the relationship can be 1-tvwLast (the new Node becomes the last sibling

of the relative Node); 2-tvwNext (default, the new Node is added

immediately after the relative Node, at the same level in the hierarchy);

3-tvwPrevious (the new Node is inserted immediately before the relative

Node, at the same level in the hierarchy); or 4-tvwChild (the new Node

becomes a child of the relative Node and is inserted after all existing child

nodes).

Here's an example of a routine that fills a TreeView control with the structure

of an MDB file – that is, the tables it contains and the fields for each table.

The routine accepts a reference to the control in its second argument so that

you can easily reuse it in your applications. The third argument passed to

the routine is a Boolean value that states whether system tables should be

displayed:

Add([Relative],[Relationship],[Key],[Text],[Image],[SelectedImage]) As Node

Dim nd As Node Set nd = Add(, , ,"C:\System", "Folder", "OpenFolder")

Visual Basic Unit 9

Sikkim Manipal University Page No.: 190

Note that the routine doesn't include any error handler: if the file doesn't

exist or is an invalid or corrupted MDB archive, the error is simply returned

to the caller. It's usual to show a TreeView control with the root object

already expanded in order to save the end user a mouse click. The routine

does this by setting the root Node object's Expanded property to True.

9.3.4 Appearance and Visibility

You can control the appearance of individual Node objects by setting their

ForeColor, BackColor, and Bold properties, the effects of which are shown

in Figure 9.6. This new feature permits you to visually convey more

information about each Node. Typically, you set these properties when you

add an item to the Nodes collection:

Sub ShowDatabaseStructure(MdbFile As String, TV As TreeView, _ ShowSystemTables As Boolean) Dim db As DAO.Database, td As DAO.TableDef, fld As DAO.Field Dim nd As Node, nd2 As Node ' Clear the current contents of the TreeView control. TV.Nodes.Clear ' Open the database. Set db = DBEngine.OpenDatabase(MdbFile) ' Add the root Node, and then expand it to show the tables. Set nd = TV.Nodes.Add(, , "Root", db.Name, "Database") nd.Expanded = True ' Explore all the tables in the database. For Each td In db.TableDefs ' Discard system tables if user isn't interested in them. If (td.Attributes And dbSystemObject) = 0 Or ShowSystemTables Then ' Add the table under the Root object. Set nd = TV.Nodes.Add("Root", tvwChild, , td.Name, "Table") ' Now add all the fields. For Each fld In td.Fields Set nd2 = TV.Nodes.Add(nd.Index, tvwChild, , _ fld.Name, "Field") Next End If Next db.Close End Sub

Visual Basic Unit 9

Sikkim Manipal University Page No.: 191

Figure 9.6: Effects of the ForeColor, BackColor, and Bold properties of Node

objects, as well as of the Checkboxes property of the TreeView control.

Each Node object has three images associated with it, and the Node's

current state determines which image is displayed. The Image property sets

or returns the index of the default image; the SelectedImage property sets or

returns the index of the image used when the Node is selected; the

ExpandedImage property sets or returns the index of the image used when

the Node is expanded. You can set the first two properties in the Nodes

collection's Add method, but you must explicitly assign the ExpandedImage

property after you've added the item to the collection.

You can learn whether a particular Node is currently visible by querying its

Visible property. A Node item can be invisible because it belongs to a tree

branch that's in a collapsed state or because it has scrolled away from the

visible portion of the control. This property is read-only, but you can force

the visibility state of a Node by executing its EnsureVisible method:

You can learn how many Nodes are visible in the control by executing

TreeView's GetVisibleCount method.

With TV.Nodes.Add(, , , "New Node") .Bold = True .ForeColor = vbRed .BackColor = vbYellow End With

' Scroll the TreeView, and expand any parent Node if necessary.

If aNode.Visible = False Then aNode.EnsureVisible

Visual Basic Unit 9

Sikkim Manipal University Page No.: 192

You have two ways to determine whether a Node is currently the selected

Node object in the control – either by querying its Selected property or by

testing the TreeView's SelectedItem property:

9.3.5 Showing information about a Node

Users expect the program to do something when they click on a Node object

in the TreeView control – for example, to display some information related to

that object. To learn when a Node is clicked, you have to trap the NodeClick

event. You can determine which Node has been clicked by looking at the

Index or Key property of the Node parameter passed to the event

procedure. In a typical situation, you store information about a Node in an

array of String or UDT items:

The NodeClick event differs from the regular Click event in that the latter

fires whenever the user clicks on the TreeView control, whereas the former

is activated only when the user clicks on a Node object.

The previous code snippet has a flaw: In general, the Index property of a

Node object can't be trusted because it can change when other Node

objects are removed from the Nodes collection. For this reason, you should

rely exclusively on the Key property, which is guaranteed not to vary after

the Node has been added to the collection.

' Check whether aNode is the Node currently selected (two ' equivalent ways). ' First way: If aNode.Selected Then MsgBox "Selected" ' Second way: If TreeView1.SelectedItem Is aNode Then MsgBox "Selected" ' Make aNode the currently selected Node (two equivalent ways). ' First way: aNode.Selected = True ' Second way: Set TreeView1.SelectedItem = aNode

Private Sub TreeView1_NodeClick(ByVal Node As MSComctlLib.Node) ' info() is an array of strings that hold nodes' descriptions. lblData.Caption = info(Node.Index) End Sub

Visual Basic Unit 9

Sikkim Manipal University Page No.: 193

For example, you can use the Key property to search for an item in a

standard Collection object, where you store information that's related to the

Node. Here's a better technique: You store the data in the Tag property of

the Node object so that you don't have to worry about removing items from

the control's Node collection.

The BrowMdb.vbp project on the companion CD includes a revised version

of the ShowDatabaseStructure routine to show properties and attributes of

all the Field and TableDef objects displayed in the TreeView control, as you

can see in Figure 9.7.

Fig. 9.7: A simple browser for Microsoft Jet databases

9.3.6 Editing Node Text

By default, the user can click on a Node object to enter Edit mode and

indirectly change the Node object's Text property. If you don't like this

behavior, you can set the LabelEdit property to 1-tvwManual. In this case,

you can enter Edit mode only by programmatically executing a

StartLabelEdit method.

Regardless of the value of the LabelEdit property, you can trap the instant

when the user begins editing the current value of the Text property by

writing code in the BeforeLabelEdit event procedure. When this event fires,

you can discover which Node is currently selected by using the TreeView's

Visual Basic Unit 9

Sikkim Manipal University Page No.: 194

SelectedItem property, and you can cancel the operation by setting the

event's Cancel parameter to True:

Similarly, you can find out when the user has completed the editing and

reject, if you want to, the new value of the Text property by trapping the

AfterLabelEdit event. Typically, you use this event to check whether the new

value follows any syntactical rule enforced by the particular object. For

example, you can reject empty strings by writing the following code:

9.3.7 Using Check Boxes

To display a check box beside each Node in the TreeView control, you

simply need to set the control's Checkboxes property to True, either at

design time or run time. You can then query or modify the state of each

Node using its Checked property:

You can enforce tighter control over what happens when a Node is checked

by writing code in the control's NodeChecked event. This event doesn't fire if

you modify a Node's Checked property using code:

Private Sub TreeView1_BeforeLabelEdit(Cancel As Integer) ' Prevent the root Node's Text property from editing. If TreeView1.SelectedItem.Key = "Root" Then Cancel = True End Sub

Private Sub TreeView1_AfterLabelEdit(Cancel As Integer, _ NewString As String) If Len(NewString) = 0 Then Cancel = True End Sub

' Count how many Node objects are checked, and then reset all check boxes. Dim i As Long, SelCount As Long For i = 1 To TreeView1.Nodes.Count If TreeView1.Nodes(i).Checked Then SelCount = SelCount + 1 TreeView1.Nodes(i).Checked = False End If Next

Visual Basic Unit 9

Sikkim Manipal University Page No.: 195

If you want to prevent the user from modifying the Checked state of a given

Node object, you can't simply reset its Checked property within the

NodeCheck event because all changes to this property are lost when the

event procedure is exited. You can solve this problem by adding a Timer

control on the form and writing this code:

Self Assessment Questions

4. A ___ sign beside an item indicates that it has one or more child items.

5. A TreeView control can display ___ graphical elements.

6. You store the data in the ____ property of the Node object so that you

don't have to worry about removing items from the control's Node

collection.

Dim SelCount As Long ' The number of selected items Private Sub TreeView1_NodeCheck(ByVal Node As MSComctlLib.Node) ' Display the number of selected Nodes. If Node.Checked Then SelCount = SelCount + 1 Else SelCount = SelCount _ 1 End If lblStatus = "Selected Items = " & SelCount End Sub

Dim CheckedNode As Node ' A form-level variable Private Sub TreeView1_NodeCheck(ByVal Node As MSComctlLib.Node) ' Prevent the user from checking the first Node. If Node.Index = 1 Then ' Remember which Node has been clicked on. Set CheckedNode = Node ' Let the Timer routine do the job. Timer1.Enabled = True End If End Sub Private Sub Timer1_Timer() ' Reset the Checked property, and then go to sleep. CheckedNode.Checked = False Timer1.Enabled = False End Sub

Visual Basic Unit 9

Sikkim Manipal University Page No.: 196

9.4 Summary

This unit has covered the following topics:

The ImageList Control

This control is used as a container for images and icons that are employed

by other controls, such as TreeView, ListView, and so on. The advantage of

this control is its inclusion provides the runtime environment to use the

images embedded in this control.

The TreeView Control

The TreeView control is probably the first Windows common control that

users become acquainted with because it's the control Windows Explorer is

based on. Basically, the TreeView control displays a hierarchy of items. A

plus sign beside an item indicates that it has one or more child items. An

item that has child items can be expanded to show them or collapsed to

hide them. This can be done interactively by the user or via code.

9.5 Terminal Questions

1. Describe the process of extracting and drawing images using ImageList

control.

2. Describe the mechanism of creating transparent images using ImageList

control.

3. Describe the methodology of adding node objects to a TreeView control.

4. Explain the usage of check boxes in a TreeView control.

9.6 Answers

Self Assessment Questions

1. Ctrl+T

2. ImageList

3. ListImage

4. plus

5. four

6. Tag

Visual Basic Unit 9

Sikkim Manipal University Page No.: 197

Terminal Questions

1. Each ListImage object exposes a Picture property, which lets you extract

the image and assign it to another control, typically a PictureBox or

Image control. (Refer Section 9.2)

2. The ImageList control has a MaskColor property whose value

determines the color that should be considered transparent when you're

performing graphical operations on individual ListImage objects or when

you're displaying images inside other controls. (Refer Section 9.2)

3. One of the shortcomings of the TreeView control is that you can't add

items at design time as you can with ListBox and ComboBox controls.

You can add Node objects only at run time using the Add method of the

Nodes collection. (Refer Section 9.3)

4. To display a check box beside each Node in the TreeView control, you

simply need to set the control's Checkboxes property to True, either at

design time or run time. You can then query or modify the state of each

Node using its Checked property. (Refer Section 9.3).

Visual Basic Unit 10

Sikkim Manipal University Page No.: 198

Unit 10 The ListView Control

Structure:

10.1 Introduction

Objectives

10.2 Features of ListView Control

10. 3 Setting Design – Time Properties

10.4 General Properties

10.5 Column Headers

10.6 Run-Time Operations

Adding ListItem Objects

Adding ColumnHeaders Objects

Adding ListSubItems

Loading Data from Databases

Sorting and Reordering Columns

Searching Items

10.7 Other Properties, Methods, and Events

10.8 Summary

10.9 Terminal Questions

10.10 Answers

10.1 Introduction

In the previous unit, you have seen the usage of ImageList and TreeView

controls. In this unit, you would see the usage of List View Control and its

applications in the real world GUI design. You would also be going through

the concepts of loading, retrieving, and performing various operations on a

ListView control.

Objectives:

After studying this unit, you should be able to:

define and illustrate the applications of ListView control

describe the general properties of ListView control

explain the setting of run time properties of ListView control

describe the process of adding various items to ListView control

explain data loading from an underlying database

describe the applications of sorting and searching using ListView control

Visual Basic Unit 10

Sikkim Manipal University Page No.: 199

10.2 Features of ListView Control

Together with the TreeView control, the ListView control has been made

popular by Windows Explorer. Now many Windows applications use this

pair of controls side by side, and they're therefore called Windows Explorer-

like applications. In these applications, the end user selects a Node in the

TreeView control on the left and sees some information related to it in the

rightmost ListView control.

The ListView control supports four basic view modes: Icon, SmallIcon, List,

and Report. To see how each mode is rendered, try the corresponding items

in the Windows Explorer View menu. (The Report mode corresponds to the

Details menu command.) To give you an idea of the flexibility of this control,

you should know that the Windows desktop is nothing but a large ListView

control in Icon mode with a transparent background. When used in Report

mode, the ListView control resembles a grid control and lets you display

well-organized information about each item.

The Visual Basic 6 version of the ListView control has many new features. It

can display icons in column headers and grid cells; it supports hot tracking,

full row selection, and reordering of columns; and its items can have

independent Bold and Color attributes. The new ListView control can also

show a background bitmap, grid lines, and check boxes beside each item.

The ListView control exposes two distinct collections: The ListItems

collection comprises individual ListItem objects, each one corresponding to

an item in the control, whereas the ColumnHeaders collection includes

ColumnHeader objects that affect the appearance of the individual headers

visible in Report mode. A third collection, ListSubItems, contains data for all

the cells displayed in Report mode.

Visual Basic Unit 10

Sikkim Manipal University Page No.: 200

Figure 10.1: Hierarchy of objects in a ListView control

10.3 Setting Design – Time Properties

While you can use the regular Properties window to set most properties of a

ListView control, it's surely preferable to use a ListView control's custom

Properties dialog box, shown in Figure 10.2.

Figure 10.2: The General tab of the Properties dialog box of a ListView control

Visual Basic Unit 10

Sikkim Manipal University Page No.: 201

Self Assessment Questions

1. The ListView control supports ____ basic view modes.

2. The _____ collection comprises individual ListItem objects, each one

corresponding to an item in the control.

10.4 General Properties

We have already referred to the View property, which can be one of the

following values: 0-lvwIcon, 1-lvwSmallIcon, 2-lvwList, or 3-lvwReport. You

can change this property at run time as well as let the user change it

(typically by offering four options in the View menu of your application). The

Arrange property lets you decide whether icons are automatically aligned to

the left of the control (1-lvwAutoLeft) or to the top of the control

(2-lvwAutoTop), or whether they shouldn't be aligned at all (0-lvwNone, the

default behavior). This property takes effect only when the control is in Icon

or SmallIcon display mode.

The LabelEdit property determines whether the user can edit the text

associated with an item in the control. If this property is set to

0-lvwAutomatic, the edit operation can be initiated only by code using a

StartLabelEdit method. The LabelWrap Boolean property specifies whether

longer labels wrap on multiple lines of text when in Icon mode. The

HideColumnHeaders Boolean property determines whether column headers

are visible when in Report mode. (The default value is False, which makes

the columns visible.) If you assign the MultiSelect property the True value,

the ListView control behaves much like a ListBox control whose MultiSelect

property has been set to 2-Extended.

A few properties are new to Visual Basic 6. If you set AllowColumnReorder

to True, users can reorder columns by dragging their headers when the

control is in Report mode. You can change the appearance of the ListView

control by setting the GridLines property to True (thus adding horizontal and

vertical lines). The third new property designed to change the appearance of

the ListView control, the FlatScrollBar property, seems to be buggy: If you

set it to True, the scroll bars don't show. The ListView control shares a few

new properties with the TreeView control. I've already described the

Checkboxes property (which lets you display a check box beside each item)

and the FullRowSelect property (for highlighting entire rows instead of a

row's first item only). The HotTracking Boolean property, if True, changes

Visual Basic Unit 10

Sikkim Manipal University Page No.: 202

the appearance of an item when the user moves the mouse cursor over it.

The HoverSelection Boolean property, if True, lets you select an item by

simply moving the mouse cursor over it. See Figure 10.3 for an example of

what you can get with these new properties.

Figure 10.3: A gallery of new features of ListView controls: Check boxes, grid

lines, and Bold and ForeColor properties for individual items. The alternate

row effect is achieved by means of a tiled background picture

You can associate up to three ImageList subsidiaries with a ListView

control: The first ImageList is used when the control is in Icon mode, the

second is used when the control is in any other display mode, and the third

is used for icons in column headers. You can set these associated

ImageList controls at design time in the Image Lists tab of the Properties

dialog box, or you can set them at run time by assigning an ImageList

control to the ListView's Icons, SmallIcons, and ColumnHeaderIcons

properties, respectively.

The ColumnHeaders property is new to Visual Basic 6 because previous

versions of the ListView control didn't support icons in column headers:

' You can use the same ImageList control for different properties.

Set ListView1.Icons = ImageList1

Set ListView1.SmallIcons = ImageList2

Set ListView1.ColumnHeaderIcons = ImageList2

Visual Basic Unit 10

Sikkim Manipal University Page No.: 203

You can automatically sort the items in the ListView control by setting a few

properties in the Sorting tab of the Properties dialog box. Set the Sorted

property to True if you want to sort items. SortKey is the index of the column

that will be used for sorting (0 for the first column), and SortOrder is the

sorting order (0-lvwAscending or 1-lvwDescending). You can also set these

properties at run time.

10.5 Column Headers

You can create one or more ColumnHeader objects at design time by using

the Column Header tab of the Properties dialog box. You just have to click

on the Insert Column button and then type the values of the Text property

(which will be displayed in the header), the Alignment property (Left, Right,

or Center, although the first column header can only be left-aligned), and the

Width in twips. You can also specify a value for the Key and Tag properties

and set the index of the icon to be used for this header. (It's an index

referred to by the ColumnHeaderIcons property in the ImageList control, or

it's 0 if this column header doesn't have any icons.)

The ListView control that comes with Visual Basic 6 supports a background

bitmap. You can load an image into the control at design time by using the

Picture tab of the Properties dialog box and then selecting the Picture

property in the leftmost list box. You can load an image in any format

supported by the PictureBox control. Two additional properties affect how a

background image is displayed in the control, but you can set them only in

the regular Properties window. The PictureAlignment property lets you align

the image in one of the four corners of the control, center it, or tile it to

spread over the entire control's internal area. The TextBackground property

determines whether the background of ListView's items is transparent

(0lvwTransparent, the default value) or not (1-lvwOpaque); in the latter case,

the background image will be visible only in the area not occupied by

ListItem objects.

The background image offers a great method for displaying rows with

alternate background colors, as shown in Figure 10-12. All you have to do is

create a bitmap as tall as two rows and then set PictureAlignment =

5-lvwTile and TextBackground = 0-lvwTransparent.

Visual Basic Unit 10

Sikkim Manipal University Page No.: 204

10.6 Run-Time Operations

While you can define the appearance of a ListView control at design time,

you can fill it with data only through code. In this section, we would see how

to add and manipulate data for this control.

Self Assessment Questions

3. The _____ property lets you decide whether icons are automatically

aligned to the left of the control (1-lvwAutoLeft) or to the top of the

control (2-lvwAutoTop), or whether they shouldn't be aligned at all.

4. When you have to assign multiple properties, you can use a ___ clause

with the Add method.

Adding ListItem Objects

You add new items to the ListView controls with the ListItems collection's

Add method, which has the following syntax:

Add([Index], [Key], [Text], [Icon], [SmallIcon]) As ListItem

Index is the position at which you place the new item. (If you omit Index, the

item is added to the end of the collection.) Key is the inserted item's optional

key in the ListItems collection, Text is the string displayed in the control,

Icon is an index or a key in the ImageList control pointed to by the Icons

property, and SmallIcon is an index or a key in the ImageList control pointed

to by the SmallIcons property. All these arguments are optional.

The Add method returns a reference to the ListItem object being created,

which you can use to set those properties whose values can't be passed to

the Add method itself, as in the following example:

' Create a new item with a "ghosted" appearance.

Dim li As ListItem

Set li = ListView1.ListItems.Add(, , "First item", 1)

li.Ghosted = True

ListItem objects support a number of new properties. The Bold and

ForeColor properties affect the boldface and color attributes of the objects.

The ToolTipText property allows you to define a different ToolTip for each

item, and the Checked property sets or returns the state of the check box

beside the item (if the ListView's Checkboxes property is True). When you

have to assign multiple properties, you can use a With clause with the Add

method:

Visual Basic Unit 10

Sikkim Manipal University Page No.: 205

With ListView1.ListItems.Add(, , "John Ross", 1)

.Bold = True

.ForeColor = vbRed

.ToolTipText = "Manager of the Sales Dept."

End With

When working with ListView controls whose MultiSelect property is True, the

user can select multiple items by clicking on them while pressing the Ctrl or

the Shift key. You can modify the selection state of a ListItem object via

code by assigning the appropriate value to the Selected property. With such

ListView controls, you must also assign the SelectedItem property to make a

ListItem the current item:

' Make the first ListItem object the current one.

Set ListView1.SelectedItem = ListView1.ListItems(1)

' Select it.

ListView1.ListItems(1).Selected = True

Adding ColumnHeaders Objects

Often you don't know at design time what columns should be displayed in a

ListView control. For example, you might be showing the result of a user-

defined query, in which case you don't know the number and the names of

the fields involved. In such circumstances, you must create ColumnHeader

objects at run time with the Add method of the ColumnHeaders collection,

which has this syntax:

Add([Index], [Key], [Text], [Width], [Alignment], [Icon]) _

As ColumnHeader

Index is the position in the collection, Key is an optional key, Text is the

string displayed in the header, and Width is the column's width in twips.

Alignment is one of the following constants: 0-lvwColumnLeft, 1-

lvwColumnRight, or 2-lvwColumnCenter. Icon is an index or a key in the

ListImage control referenced by the ColumnHeaderIcons property. With the

exception of the Tag property, these are the only properties that can be

assigned when a ColumnHeader object is created, so you can usually

discard the return value of the Add method:

Visual Basic Unit 10

Sikkim Manipal University Page No.: 206

' Clear any existing column header.

ListView1.ColumnHeaders.Clear

' The alignment for the first column header must be lvwColumnLeft.

ListView1.ColumnHeaders.Add , , "Last Name", 2000, lvwColumnLeft

ListView1.ColumnHeaders.Add , , "First Name", 2000, lvwColumnLeft

ListView1.ColumnHeaders.Add , , "Salary", 1500, lvwColumnRight

Adding ListSubItems

Each ListItem object supports a ListSubItems collection, which lets you

create values displayed in the same row as the main ListItem object when

the control is in Report mode. This collection replaces the SubItems array

that was present in previous versions of the control. (The array is still

supported for backward compatibility.) You can create new ListSubItem

objects using the Add method of the ListSubItems collection:

Add([Index], [Key], [Text], [ReportIcon], [ToolTipText]) _

As ListSubItem

Index is the position in the collection of the new item, Key is its optional key,

Text is the string that will be displayed in the grid cell, ReportIcon is the

index or the key of an icon in the ImageList control referenced by the

SmallIcons property, and ToolTipText is the text of a ToolTip that appears

when the user keeps the mouse hovering over this item. You can also

assign individual Bold and ForeColor attributes to each ListSubItem:

' This ListItem goes under ColumnHeader(1).

With ListView1.ListItems.Add(, , "Ross", 1)

.Bold = True

' This ListSubItem goes under ColumnHeader(2).

With .ListSubItems.Add(, , "John")

.Bold = True

End With

' This ListSubItem goes under ColumnHeader(3).

With .ListSubItems.Add(, , "80,000")

.Bold = True

.ForeColor = vbRed

End With

End With

Visual Basic Unit 10

Sikkim Manipal University Page No.: 207

ListSubItem objects are actually displayed only if the ListView control is in

Report mode and only if there are enough ColumnHeader objects. For

example, if the ColumnHeaders collection includes only three elements, the

ListView control will display only up to three items in each row. Because the

leftmost ColumnHeader object is located above ListItem elements, only the

first two elements in the ListSubItems collection will be visible.

ListSubItem objects also support the Tag property, which you can use to

store additional information associated with the items.

Loading Data from Databases

The ListView control can't be automatically bound to a database through

Data, RemoteData, or an ADO Data control. In other words, if you want to

load database data into this control you're on your own. The task of filling a

ListView control with data read from a recordset isn't conceptually difficult,

but you have to account for a few details. First you must retrieve the list of

fields contained in the recordset and create a corresponding number of

ColumnHeader objects of a suitable width. You also have to discard fields

that can't be displayed in ListView controls (for example, BLOB fields), and

you must determine the best alignment for each field (to the right for

numbers and dates, to the left for all others). A routine that does all this,

which you can easily reuse in your applications, is shown below.

Sub LoadListViewFromRecordset(LV As ListView, rs As

ADODB.Recordset, _

Optional MaxRecords As Long)

Dim fld As ADODB.Field, alignment As Integer

Dim recCount As Long, i As Long, fldName As String

Dim li As ListItem

' Clear the contents of the ListView control.

LV.ListItems.Clear

LV.ColumnHeaders.Clear

' Create the ColumnHeader collection.

For Each fld In rs.Fields

' Filter out undesired field types.

Select Case fld.Type

Case adBoolean, adCurrency, adDate, adDecimal, adDouble

Visual Basic Unit 10

Sikkim Manipal University Page No.: 208

alignment = lvwColumnRight

Case adInteger, adNumeric, adSingle, adSmallInt,

adVarNumeric

alignment = lvwColumnRight

Case adBSTR, adChar, adVarChar, adVariant

alignment = lvwColumnLeft

Case Else

alignment = -1 ' This means "Unsupported field type".

End Select

' If field type is OK, create a column with the correct alignment.

If alignment <> -1 Then

' The first column must be left-aligned.

If LV.ColumnHeaders.Count = 0 Then alignment =

lvwColumnLeft

LV.ColumnHeaders.Add , , fld.Name, fld.DefinedSize * 200, _

alignment

End If

Next

' Exit if there are no fields that can be shown.

If LV.ColumnHeaders.Count = 0 Then Exit Sub

' Add all the records in the recordset.

rs.MoveFirst

Do Until rs.EOF

recCount = recCount + 1

' Add the main ListItem object.

fldName = LV.ColumnHeaders(1).Text

Set li = LV.ListItems.Add(, , rs.Fields(fldName) & "")

' Add all subsequent ListSubItem objects.

For i = 2 To LV.ColumnHeaders.Count

fldName = LV.ColumnHeaders(i)

li.ListSubItems.Add , , rs.Fields(fldName) & ""

Next

If recCount = MaxRecords Then Exit Do

rs.MoveNext

Loop

End Sub

Visual Basic Unit 10

Sikkim Manipal University Page No.: 209

The LoadListViewFromRecordset routine expects an ADO Recordset and

an optional MaxRecords argument that lets you limit the number of records

displayed. This is necessary, because – as opposed to what happens with

bound controls, which load only the information that is actually displayed –

this routine reads all the rows in the recordset, which might be a lengthy

process. I suggest that you set MaxRecords to 100 or 200, depending on

the type of connection you have to your database and the speed of your

CPU.

Another problem you face when loading data from a database is that you

might need to manually adjust the width of each column. The

LoadListViewFromRecordset routine initializes the width of all

ColumnHeader objects using the fields' maximum width, but in most cases

values stored in database fields are considerably shorter than this value.

Instead of leaving the burden of the manual resizing on your users, you can

change all columns' width programmatically using the following routine:

Sub ListViewAdjustColumnWidth(LV As ListView, _

Optional AccountForHeaders As Boolean)

Dim row As Long, col As Long

Dim width As Single, maxWidth As Single

Dim saveFont As StdFont, saveScaleMode As Integer, cellText As

String

' Exit if there aren't any items.

If LV.ListItems.Count = 0 Then Exit Sub

' Save the font used by the parent form, and enforce ListView's

' font. (We need this in order to use the form's TextWidth

' method.)

Set saveFont = LV.Parent.Font

Set LV.Parent.Font = LV.Font

' Enforce ScaleMode = vbTwips for the parent.

saveScaleMode = LV.Parent.ScaleMode

LV.Parent.ScaleMode = vbTwips

For col = 1 To LV.ColumnHeaders.Count

maxWidth = 0

If AccountForHeaders Then

Visual Basic Unit 10

Sikkim Manipal University Page No.: 210

maxWidth =

LV.Parent.TextWidth(LV.ColumnHeaders(col).Text)+200

End If

For row = 1 To LV.ListItems.Count

' Retrieve the text string from ListItems or ListSubItems.

If col = 1 Then

cellText = LV.ListItems(row).Text

Else

cellText = LV.ListItems(row).ListSubItems(col - 1).Text

End If

' Calculate its width, and account for margins.

' Note: doesn't account for multiple-line text fields.

width = LV.Parent.TextWidth(cellText) + 200

' Update maxWidth if we've found a larger string.

If width > maxWidth Then maxWidth = width

Next

' Change the column's width.

LV.ColumnHeaders(col).width = maxWidth

Next

' Restore parent form's properties.

Set LV.Parent.Font = saveFont

LV.Parent.ScaleMode = saveScaleMode

End Sub

To determine the optimal width of all the values stored in a given column,

the ListViewAdjustColumnWidth routine evaluates the maximum width of all

the strings stored in that column. The problem is that the ListView control

doesn't support the TextWidth method, so the routine relies on the

TextWidth method exposed by the control's parent form. If a True value is

passed in the second argument, the routine also accounts for the Text

property of all ColumnHeader objects, so no header title is truncated.

The ListView control already allows you to automatically resize columns to

fit their contents, even though this capability hasn't been exposed in the

Visual Basic ActiveX control. In fact, you can interactively resize a column to

fit the longest item it contains by double-clicking on its right border in the

column header (as you would in the Details view mode of Windows

Explorer). In the demonstration program on the companion CD, you'll find

Visual Basic Unit 10

Sikkim Manipal University Page No.: 211

another version of the ListViewAdjustColumnWidth routine that does the

resizing by using API calls instead of plain Visual Basic code. The following

code sample shows how to use the ListViewAdjustColumnWidth routine to

display all the records in the Orders table of the NorthWind.Mdb database,

as shown in Figure 10.3:

Private Sub Form_Load()

Dim cn As New ADODB.Connection, rs As New ADODB.Recordset

' WARNING: you might need to modify the DB path in the next line.

cn.Open "Provider=Microsoft.Jet.OLEDB.3.51;" _

& "Data Source=C:\VisStudio\VB98\NWind.mdb"

rs.Open "Orders", cn, adOpenForwardOnly, adLockReadOnly

LoadListViewFromRecordset ListView1, rs

ListViewAdjustColumnWidth ListView1, True

End Sub

On my 233-MHz machine, this code takes about 15 seconds to complete,

which is more than most customers are willing to wait. Therefore, you

should use this technique judiciously and set an upper limit to the number of

records that are read from a database.

Figure 10.3: This demonstration program loads NorthWind's Orders table into

a ListView control and lets you sort on any field by clicking on the

corresponding column's header

Visual Basic Unit 10

Sikkim Manipal University Page No.: 212

Sorting and Reordering Columns

I already explained how you can define a sort key and a sort order at design

time. You can get the same effect at run time by setting the Sorted, SortKey,

and SortOrder properties. Usually you do this when the end user clicks on a

column header, an action that you can trap in the ColumnClick event:

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As _

MSComctlLib.ColumnHeader)

ListView1.SortKey = ColumnHeader.Index - 1

ListView1.Sorted = True

End Sub

Things are slightly more complicated if you want to offer the ability to sort in

either direction: The first click sorts in ascending order, and the second click

sorts in descending order. In this case, you must check to see whether the

column being clicked is already sorted:

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As _

MSComctlLib.ColumnHeader)

' Sort according to data in this column.

If ListView1.Sorted And _

ColumnHeader.Index - 1 = ListView1.SortKey Then

' Already sorted on this column, just invert the sort order.

ListView1.SortOrder = 1 - ListView1.SortOrder

Else

ListView1.SortOrder = lvwAscending

ListView1.SortKey = ColumnHeader.Index - 1

End If

ListView1.Sorted = True

End Sub

The ListView control is able to sort string data exclusively. If you want to sort

on columns that hold numeric or date information, you must resort to a trick.

Create a new ColumnHeader object, fill it with string data derived from the

numbers or dates you want to sort on, sort on that column, and finally delete

those items. Here's a reusable routine that does all this for you:

Sub ListViewSortOnNonStringField(LV As ListView, ByVal

ColumnIndex As _

Integer, SortOrder As Integer, Optional IsDateValue As Boolean)

Visual Basic Unit 10

Sikkim Manipal University Page No.: 213

Dim li As ListItem, number As Double, newIndex As Integer

' This speeds up things by a factor of 10 or more.

LV.Visible = False

LV.Sorted = False

' Create a new, hidden field.

LV.ColumnHeaders.Add , , "dummy column", 1

newIndex = LV.ColumnHeaders.Count - 1

For Each li In LV.ListItems

' Extract a number from the field.

If IsDateValue Then

number = DateValue(li.ListSubItems(ColumnIndex - 1))

Else

number = CDbl(li.ListSubItems(ColumnIndex - 1))

End If

' Add a string that can be sorted using the Sorted property.

li.ListSubItems.Add , , Format$(number,

"000000000000000.000")

Next

' Sort on this hidden field.

LV.SortKey = newIndex

LV.SortOrder = SortOrder

LV.Sorted = True

' Remove data from the hidden column.

LV.ColumnHeaders.Remove newIndex + 1

For Each li In LV.ListItems

li.ListSubItems.Remove newIndex

Next

LV.Visible = True

End Sub

You can use the ListViewSortOnNonStringField routine from a ColumnClick

event procedure, as I explained previously. The code I just showed you

doesn't work with negative values, but the complete version on the

companion CD solves this problem.

Visual Basic Unit 10

Sikkim Manipal University Page No.: 214

Columns can be moved and reordered at run time. You can let the user drag

a column to a new position by setting the AllowColumnReorder property to

True. However, you shouldn't do this when your ListView control has the

property Checkboxes set to True. If the user moves the first column, the

control's contents will look pretty unusual because the check boxes will

move with the first column.

Reordering columns from your code ensures better control over which

columns are moved and where. In this case, you only have to assign a new

value to the Position property of a ColumnHeader object. For example, you

can exchange the position of the first two columns with this code:

ListView1.ColumnHeaders(1).Position =

ListView1.ColumnHeaders(1).Position _

+ 1

' You need to refresh after reordering one or more columns.

ListView1.Refresh

Searching Items

You can quickly search for a string in a ListView control using the FindItem

method, which has this syntax:

FindItem(Search, [Where], [Start], [Match]) As ListItem

Search is the string being searched. Where specifies in which property the

string will be searched: 0-lvwText for the Text property of ListItem objects,

1-lvwSubItem for the Text property of ListSubItem objects, or 2-lvwTag for

the Tag property of ListItem objects. Start is the index or the key of the

ListItem object from which the search begins. Match can be

0-lvwWholeWord or 1-lvwPartial and defines whether an item that begins

with the searched string makes for a successful search. (Match can be used

only if Where = 0-lvwText.)

Note that you can't search in the Tag property of ListSubItem objects, nor

can you restrict the search to a single column of ListSubItems. All search

operations are case insensitive.

10.7 Other Properties, Methods, and Events

The ListView control supports properties, methods, and events that are

similar to those exposed by the TreeView control, so I won't describe them

in detail here.

Visual Basic Unit 10

Sikkim Manipal University Page No.: 215

You can control when the user edits a value in the control using the

BeforeLabelEdit and AfterLabelEdit events. Regardless of where the user

clicks on the row, the only item that can actually be edited is the one in the

leftmost column. If you want to programmatically start an edit operation, you

have to make a given ListItem object the selected one and then invoke the

StartLabelEdit method:

ListView1.SetFocus

Set ListView1.SelectedItem = ListView1.ListItems(1)

ListView1.StartLabelEdit

If the control's Checkboxes property is set to True, you can read and modify

the checked state of each row through the Checked property of individual

ListItem objects. You can trap the action of ticking a check box by writing

code in the ItemCheck event procedure. Similarly, the ItemClick event fires

when a ListItem object is clicked.

ListItem objects expose an EnsureVisible method that, if necessary, scrolls

the contents of the control to move the item into the visible area of the

control. You can also query the ListView's GetFirstVisible method, which

returns a reference to the first visible ListItem object.

The ListView's HitTest method returns the ListItem object at the specified

coordinates. You typically use this method in drag-and-drop operations

together with the DropHighlight property, as I explained in the section

devoted to the TreeView control. By the way, there's no simple way to

determine which column the mouse is on when the control is in Report

mode.

Self Assessment Questions

5. _____ is the index or the key of an icon in the ImageList control

referenced by the SmallIcons property.

6. The ListView control can be automatically bound to a database through

Data, RemoteData, or an ADO Data control. (True / False)

10.8 Summary

This unit has covered the following topics:

ListView Control: Many Windows applications use this pair of controls side

by side, and they're therefore called Windows Explorer-like applications. In

Visual Basic Unit 10

Sikkim Manipal University Page No.: 216

these applications, the end user selects a Node in the TreeView control on

the left and sees some information related to it in the rightmost ListView

control. The ListView control supports four basic view modes: Icon,

SmallIcon, List, and Report.

10.9 Terminal Questions

1. Explain the design time property settings of a ListView control.

2. Describe the runtime properties of ListView control.

3. Explain the procedure to load data from databases in a ListView control.

10.10 Answers

Self Assessment Questions

1. four

2. ListItems

3. Arrange

4. With

5. ReportIcon

6. False

Terminal Questions

1. While you can use the regular Properties window to set most properties

of a ListView control, it's surely preferable to use a ListView control's

custom Properties dialog box. (Refer Section 10.3)

2. While you can define the appearance of a ListView control at design

time, you can fill it with data only through code. In this section, we would

see how to add and manipulate data for this control.

(Refer Section 10.6)

3. if you want to load database data into this control you're on your own.

The task of filling a ListView control with data read from a recordset isn't

conceptually difficult, but you have to account for a few details. First you

must retrieve the list of fields contained in the recordset and create a

corresponding number of ColumnHeader objects of a suitable width.

You also have to discard fields that can't be displayed in ListView

controls. (Refer Section 10.6)

Visual Basic Unit 11

Sikkim Manipal University Page No.: 217

Unit 11 Classes and Objects

Structure:

11.1 Introduction

Objectives

11.2 OOP in Visual Basic .NET

11.3 How to Objectify Your Programs

11.4 Defining a Class

11.5 Relationships between Classes

11.6 Inheritance in VB.Net

11.7 Building Constructors and Destructors

11.8 Creating and Destroying an Object

11.9 Using System.Object

11.10 Namespaces

11.11 The Imports Keyword

11.12 Summary

11.13 Terminal Questions

11.14 Answers

11.1 Introduction

In the previous units, you have learnt about utilizing various programming

objects like variables, procedures, record sets and so on. All these are

based on objects, which are the fundamental building blocks of VB.Net

programming. In this unit, you will learn about the theoretical concepts of

classes and objects, and their applications in programming.

The original versions of Microsoft® Visual Basic® provided a mechanism for

defining data structures in a user-defined type (UDT). A UDT encapsulates

the data, but not the processing associated with that data. Processing was

defined in global standard modules, often called BAS modules because of

their .bas extension.

The release of Visual Basic 4 dawned a new age for Visual Basic

developers. Visual Basic took its first steps toward becoming an object-

oriented programming (OOP) language by providing object-oriented features

such as class modules. A class module defines data as properties and the

processing associated with that data as methods. By defining a class for

Visual Basic Unit 11

Sikkim Manipal University Page No.: 218

each business entity, encapsulating data in properties and processing in

methods, Visual Basic developers had object-based development.

As Visual Basic evolved from version 4 to version 6, Visual Basic

developers expanded their knowledge of OO to include component-based

development (CBD) techniques. With CBD, Visual Basic developers could

build complete three-tiered applications for Microsoft Windows® and the

Web. This type of development was so common that Microsoft provided a

design pattern known as the Microsoft DNA architecture.

Visual Basic .NET provides another leap in Visual Basic development

capabilities and features and provides for true object-oriented programming,

as detailed in this article.

Objectives:

After studying this unit, you should be able to:

explain and illustrate the use of OOP concepts

describe the design of objects in VB.Net programs

illustrate the methodology of defining classes

explain building relationships between classes

explain the application of Inheritance

explain the usage of Constructors and Destructors

describe the usage of System.object object

describe the concept of Namespaces

11.2 OOP in Visual Basic .NET

For a programming language to be a true OOP language, the language

must meet the following criteria:

Abstraction – Abstraction manages the complexities of a business problem

by allowing you to identify a set of objects involved with that business

problem.

Encapsulation – Encapsulation hides the internal implementation of an

abstraction within the particular object.

Polymorphism – Polymorphism provides for multiple implementations of

the same method. For example, different objects can have a Save method,

each of which perform different processing.

Visual Basic Unit 11

Sikkim Manipal University Page No.: 219

Inheritance – The excitement of Visual Basic .NET lies in inheritance.

Visual Basic 5 introduced the concept of interface inheritance, which allows

you to reuse the interface of a class, but not its implementation. Visual Basic

.NET provides for true implementation inheritance whereby you can reuse

the implementation of a class.

Now let's look at doing object-oriented programming in .NET.

Visual Basic .NET is not Visual Basic 6 with inheritance tacked onto it.

Rather, Visual Basic .NET has been entirely rewritten to be fully object-

oriented. In fact, everything in Visual Basic .NET can be treated as an

object. Yes, even your strings and integers can be accessed as objects in

Visual Basic .NET.

To demonstrate this, start a new Visual Basic .NET console application

project. In the Main subroutine, enter this code:

The first hint that your integer is treated as an object is the list of properties

and methods that appear when you type the dot after the i. Select one of the

properties, such as the MinValue shown in this example. Then run the

application and you will get a message box containing the value of the

selected integer property.

.NET has predefined classes for the intrinsic data types, but what about the

classes that you create? Let's walk through an example to demonstrate how

to create classes in Visual Basic .NET and inherit from them to leverage

some of the new OOP features.

Figure 11.1: Console Application Example

Dim i As Integer MsgBox(i.MinValue)

Visual Basic Unit 11

Sikkim Manipal University Page No.: 220

11.3 How to Objectify Your Programs

In the really old days we practiced what we called structured, procedure-

oriented programming. We identified what needed to be done and then did

one of two things, either:

1. Broke the task to be accomplished into subtasks, and these into smaller

subtasks, until the subtasks were simple enough to be implemented

directly (in other words, the top-down approach).

OR

2. Wrote procedures to solve simple tasks and combine them into more

sophisticated procedures, until we had the functionality we wanted (the

bottom-up approach).

Most experienced programmers did not do what the professors suggested,

of course (which was the top-down approach), and instead used a mixture

of the top-down and bottom-up strategies to solve a programming problem.

There are two important differences between OOP and procedure-oriented

programming:

1. In OOP, you first isolate the classes. Only then do you look for the

methods and properties of the class.

2. You then associate each method or property with the class that is

responsible for carrying out the operation.

Which leads to the obvious question: How do you find the classes? A good

rule of thumb is that classes are the nouns in your analysis of the problem.

In our example, employees are one of the obvious nouns. The methods in

your objects correspond to the verbs that describe actions that affect the

noun, as in RaiseSalary (verb) which affects an Employee (noun). The

properties are the adjectives that describe the noun. Of course, the noun-

verb-adjective correspondence to classes, methods, and properties is only a

first step. Only experience can help you decide which nouns, verbs, and

adjectives are the important ones.

Here is another example: Suppose you want to design a program to

manage your checking account using an object-oriented approach. Some

obvious nouns are:

Account

Check

Visual Basic Unit 11

Sikkim Manipal University Page No.: 221

Check register

Deposit slip

These would lead to classes called Account, Check, CheckRegister,

DepositSlip, and so on. Next, look for verbs. Accounts need to be opened or

closed. Checks need to be added_to the register. The check register needs

to be reconciled. Deposit slips need to be totaled. With each verb, such as

add, reconcile, and total, you have to identify the one object that has the

major responsibility for carrying it out. For example, the deposit slip has the

major responsibility for totaling itself up. Thus, Total should be a method of

the DepositSlip class.

At this point, we want to repeat one golden rule of programming that has not

changed in the march to OOP: keep things simple. Object-oriented

programming is much easier when the classes you build are not complex.

A class with a simple internal structure and limited relationships (coupling is

the buzzword) to other classes is much easier to grasp (and hence to code).

Describing relationships between classes is so important in OOP that a

whole industry has sprung up to explain how to make diagrams that make

class relationships clearer.

The most common tool is called the uniform modeling language (UML).

These diagramming tools are usually part of the Computer-Assisted

Software Engineering (CASE) tools, such as Microsoft's Visual Modeler,

Visio, and Rational Software’s Rational Rose. (A version of Visual Modeler

is included with some versions of VS .NET.)

A UML-based CASE tool can go from the diagram to actually building the

code skeletons for your classes. We recommend the Rational Web site

(www.rational.com/uml) for general overviews of UML.

Self Assessment Questions

1. A ____ encapsulates the data, but not the processing associated with

that data.

2. With ______, Visual Basic developers could build complete three-tiered

applications for Microsoft Windows® and the Web.

3. ______ manages the complexities of a business problem by allowing

you to identify a set of objects involved with that business problem.

Visual Basic Unit 11

Sikkim Manipal University Page No.: 222

4. ____ are the nouns in your analysis of the problem.

5. A _____ CASE tool can go from the diagram to actually building the

code skeletons for your classes.

11.4 Defining a Class

The basic purpose of a class has not changed in Visual Basic .NET. You still

create classes for your business objects and for any supporting objects that

you may need for your application. The primary changes from Visual Basic 6

to Visual Basic .NET involve syntax and some new features.

In Visual Basic 6, you create a class by creating a class module: one class,

one class module. This is no longer the case in Visual Basic .NET. You can

create any number of classes within a single code file. You can even create

classes within classes. But let's start out with a simple example.

Adding a class to a Visual Basic .NET project is very similar to Visual Basic

6. However, instead of getting an empty code file, your class will appear with

the following code:

Note: The current Microsoft convention is to define the class names without

a prefix.

Following that convention, this class name would be Customer instead of

CCustomer. While this convention is more user-friendly when creating

objects using retail products such as Microsoft Word and Excel,

maintenance and support of enterprise systems can benefit from the

additional information that a prefix provides.

If you want to add a second class to the same file, just add another class

statement:

Note: Normally, a class should be defined in its own code file.

Public Class CCustomer End Class

Public Class CCustomer End Class Public Class CContact End Class

Visual Basic Unit 11

Sikkim Manipal University Page No.: 223

Only put classes together if they are tightly coupled. For example, invoice

and invoice line item could be two classes within one code file because you

would normally never use invoice line item without invoice. If you would use

customer contacts (CContact) separate from customers then the CContact

class should be separate from the CCustomer class.

You can then add properties or methods to the class. As with Visual Basic 6,

you normally define a property by declaring a private variable and public

Property procedures. In Visual Basic .NET, you would define a Name

property as follows:

There are only two types of Property procedures in Visual Basic .NET, Get

and Set. The Get procedure retrieves the property value from the class and

the Set procedure assigns the property. Visual Basic 6 provided a property

Let statement that handled intrinsic data types while the Set statement

worked with objects. Now that everything in Visual Basic .NET is basically

an object, there is no need for the Let statement.

Notice that the syntax for a property procedure is also changed. Both the

Get and Set are contained within one property statement. No more

possibility of a mismatch in data types between property Get and Set. This

makes these statements easier to maintain.

Private m_sName As String Property Name() As String Get Return m_sName End Get Set(ByVal Value As String) m_sName = Value End Set End Property

Public Function SayHello() As String If Name <> "" Then Return "Hello " & Name Else Return "Hello World" End If End Function

Visual Basic Unit 11

Sikkim Manipal University Page No.: 224

11.5 Relationships between Classes

Traditional OOP provides three possible relationships between classes:

• Use: dependency

• Containment: “has a” – this is sometimes called aggregation

• Inheritance: “is a”

The use relationship is both the most obvious and the most common,

because it is just a fancy way of saying one class depends on another.

Whenever an object sends a message to another object, the two obviously

depend on each other. For example, an object of the CheckRegister class

(an actual check register) uses objects of the DepositSlip class, because a

check register needs to know what has been deposited. But the DepositSlip

class does not use the Check class, because deposit slips have nothing to

do with checks.

While a class obviously uses another class if it manipulates objects of that

class, more generally, a class A uses a class B if:

• A member of class A sends a message to an object of class B.

or

• A member of class A creates or returns objects of class B.

Note: It is best to minimize the number of classes that use each other. In

other words, do not make your classes needlessly or overly intertwined. (In

OOP-speak, this is called the loose coupling of classes.) The reason to do

this is that if a class A does not use a class B, it does not care about any

changes to B. (And this also means that changes to B will not introduce

bugs into A!)

Containment (aggregation) means that objects of class A contain objects of

class B. For example, a specific CheckRegister object could contain Check

and DepositSlip objects.

Containment is used to carry out delegation: you can delegate to the internal

contained object the tasks that need to be carried out. Aggregation with

method delegation was extremely common in earlier versions of VB,

because that was how you built controls with VB5 and VB6. (Recall that you

made a better textbox by placing a textbox inside a user control form and

then running the control interface wizard to write the delegation code for you

automatically.)

Visual Basic Unit 11

Sikkim Manipal University Page No.: 225

Aggregation is still common in VB .NET, but inheritance takes its place in

many situations. Inheritance is not only one of the three ways classes

depend on each other, it is also one of the four sacred buzzwords of OOP.

Self Assessment Questions

6. In _______ you can create any number of classes within a single code

file.

7. There are only ____ types of Property procedures in Visual Basic.

8. _______ is used to carry out delegation.

11.6 Inheritance in VB.Net

The most talked about new OOP feature in Visual Basic .NET is inheritance.

To fully understand inheritance, let's expand our example.

The Customer class example presented earlier is a small part of a complete

Customer Billing System. This system tracks customers, manages customer

orders, and generates bills in the form of invoices.

The system is complete and delivered to the users. As is typical, after a few

weeks of working with the system the users define additional requirements.

They now need the code to work differently depending on the type of

customer. Normal customers have a standard set of business rules.

Educational customers have more rules, some different data items and

special discounts.

Government customers have even more business rules, other data items,

and a steeper discount. The relationship between the customer, educational

customer, and government customer are depicted using the Unified

Modeling Language (UML) and modeled in Figure 11.2. But how will you

implement this change?

Visual Basic Unit 11

Sikkim Manipal University Page No.: 226

Figure 11.2: Customer Billing System

One solution is to modify the existing Customer class to contain all of the

information for all of the customer types. You can use Select/Case

statements or If statements to manage the logic to handle the different

types. But this can be tedious and complex, especially if there are a lot of

different rules or processing associated with the different types.

A second option is to create a separate class for each customer type,

including the "normal" type. Each class can then contain its own logic for

handling that particular customer type. But if there are similarities in some of

the logic, you may have duplication in the separate classes.

With Visual Basic .NET, there is now a third choice: inheritance. With

inheritance, you can define a common class that is the basis of other

classes. This class is called a base or parent class. In this example, you

would create a common Customer class.

You then create any specialized classes that inherit from the base class.

These classes are called derived or child classes. These classes inherit

functionality from the base class but can override base class functionality to

perform specialized processing.

To try this, let's use the Customer class as the base class. Add another

method to the Customer class to calculate a discount:

Visual Basic Unit 11

Sikkim Manipal University Page No.: 227

This method uses the Overridable keyword. This keyword means that any

derived classes can override this method and define their own

implementation.

Note: If you build a class that may be used as a base class, be sure to use

the Overridable keyword on any function that a derived class may wish to

override.

The derived class is very simple:

The Inherits keyword defines the parent or base class. All of the public

properties and methods of the base class are accessible to this derived

class.

The first method in this derived class is the constructor. This constructor

uses the MyBase keyword to call the constructor in the base class. The

default constructor for the parent class is automatically called when the child

is constructed, but you can manually specify the parent's constructor.

The Overrides keyword on the second function denotes that this is

overriding the function defined within the base class. This allows a derived

class to provide its own implementation of a particular function.

Public Overridable Function CalculateDiscount(ByVal dAmt As Decimal) As Decimal ' Standard discount is no discount ' Return the passed in amount Return dAmt End Function

Public Class CEdCustomer: Inherits CCustomer Public Sub New() MyBase.New() End Sub Public Overrides Function CalculateDiscount(ByVal dAmt As Decimal) As Decimal Dim newAmt As Decimal newAmt = dAmt * CDec(0.9) Return newAmt End Function End Class

Visual Basic Unit 11

Sikkim Manipal University Page No.: 228

Note: If you do not put the Overrides keyword on the function in the derived

class, the function is assumed to shadow the original function. A shadowed

function is a function in the derived class that has the same name as a

function in the base class but is not intended to override the base class

function.

There are several ways to create an instance of the derived class:

Declare an object variable as the derived class and then create the

instance of the derived class:

Declare an object variable as the base class and then create the

instance of the derived class:

The first technique declares the object to be of type CEdCustomer, thereby

defining the object to be of a specific type. The derived object has access to

any public properties and methods of the Customer base class, any

properties and methods overridden in the EdCustomer class, any

properties and methods shadowed in the EdCustomer class, and any

public properties and methods of the EdCustomer class.

The second technique declares the object to be of type CCustomer,

allowing any type of Customer object to be defined and to leverage

polymorphism. This allows reuse of the object variable for any type of

Customer object. However, by declaring the derived object using the parent

class the derived object only has access to any public properties and

methods of the Customer base class and any properties and methods

overridden in the EdCustomer class. It does not have access to any public

properties and methods of the EdCustomer class, nor to any shadowed

properties and methods.

When working with inheritance, there are a few things to remember. First,

you are not limited to just one level of inheritance. The inheritance hierarchy

can be as deep as needed. The properties and methods are inherited down

Private m_oEdCustomer As CEdCustomer m_oEdCustomer = New CEdCustomer()

Private m_oCustomer As CCustomer m_oCustomer = New CEdCustomer()

Visual Basic Unit 11

Sikkim Manipal University Page No.: 229

through the levels. In general, the farther down in the hierarchy a class

appears, the more specialized its behavior. For example, you could define a

HighSchoolEdCustomer class that inherits from the EdCustomer class

that in turn inherits from the Customer class.

Note: To minimize complexity and simplify maintenance, limit your

inheritance hierarchies to no more than about four levels.

Each class, however, can inherit from only one parent class. So an

EdCustomer class cannot inherit from both a Customer class and an

Education class. This is a good thing in that multiple inheritance can get

rather complex and make application maintenance very difficult.

There are two primary uses for inheritance in the applications that you

develop:

You have objects of different types that have similar functionality. For

example: Educational Customer class and Government Customer

class inherit from Customer class.

You have general processing to be done for sets of objects. For

example: every type of business object inherits from a Business Object

(BO) class.

You should not use inheritance when:

You only need one function from the base class. If this is the case, you

should delegate to the class instead of inheriting from it.

If you would need to override all of the functions. If this is the case, you

should use an interface instead of implementation inheritance.

The semantics of the hierarchy are not clear. If there is no clear "is a"

type of relationship, such as an educational customer "is a" customer,

then delegation or an interface may be a better solution. For example, a

vendor has a name like a customer. So the Vendor class could inherit

from the Customer class to get the name.

However, it is not accurate to say that a vendor "is a" customer. So the

semantics are not clear and inheritance should not be used in this case.

11.7 Building Constructors and Destructors

In Visual Basic 6, when you create an instance of a class the Initialize event

is generated. You can put code into the Initialize event to initialize the

object. For example, you may want to define default object data, open

Visual Basic Unit 11

Sikkim Manipal University Page No.: 230

database connections, or create related objects. However, you cannot pass

anything to the Initialize event. This makes it difficult to initialize the object

with specific parameters.

Visual Basic .NET introduces true constructors that are executed whenever

a new instance of the class is created. These constructors are defined with

a subroutine named New:

You can pass data to a constructor for more flexibility and power in

initializing the object. Constructors with parameters are called

parameterized constructors. For example:

In this example, the customer name is passed in to the constructor. That

name is then used to initialize the Name property defined with the Property

procedure.

Both of these constructors can be define for one class. Actually, any number

of constructors can be defined for a class as long as they each have

different parameters. This feature is called overloading. The appropriate

constructor is called based on the data passed to the constructor.

You do not have to define a constructor. If you don't create one, a default

constructor is used.

Instead of a Terminate event, Visual Basic .NET provides a Finalize

destructor. This destructor is called when the .NET garbage collector

determines that the object is not longer needed. There may be a delay

between the time an object is terminated and the time the garbage collector

actually destroys the object.

Public Sub New() ' Perform initialization Debug.WriteLine("I am alive") End Sub

Public Sub New(ByVal sName As String) ' Assign the name Name = sName 'Other initialization Debug.WriteLine(Name & " is alive") End Sub

Visual Basic Unit 11

Sikkim Manipal University Page No.: 231

Note: You should not normally use a Finalize destructor because of this

delay and the additional processing required by the system to manage

objects with a Finalize destructor. Use the Dispose destructor instead.

In order to better manage the resources used by your class, implement the

IDisposable interface and the Dispose destructor:

This destructor is not called automatically, so it must be explicitly called as

shown in the next section.

Note: The Dispose destructor is not required, but it is recommended. By

implementing the Dispose destructor in every class, even if it does not do

anything, developers can routinely can call the Dispose method on any

object.

Self Assessment Questions

9. To build a class that may be used as a base class, be sure to use the

________ keyword on any function that a derived class may wish to

override.

10. The ______ keyword defines the parent or base class.

11.8 Creating and Destroying an Object

In order to use a class, you first need to create an object from the class. In

Visual Basic 6, the recommended syntax for creating an object from a class

is:

This syntax is almost identical in Visual Basic .NET. Since everything is

basically an object in Visual Basic .NET, there is no need for two different

types of assignment, so there is no longer a need for the Set keyword:

Implements IDisposable Public Sub Dispose() Implements System.IDisposable.Dispose ' Perform termination End Sub

Private m_oCustomer as CCustomer Set m_oCustomer = New CCustomer

Private m_oCustomer as CCustomer m_oCustomer = New CCustomer()

Visual Basic Unit 11

Sikkim Manipal University Page No.: 232

Notice the parenthesis when creating the object. If you defined a

parameterized constructor for the class, you can pass the parameter(s) to

the constructor within the parentheses:

With Visual Basic .NET, you can combine the object variable declaration

and the object creation using the New keyword:

The object is created when this declaration is executed. The shorthand form

of this syntax is:

Note: You cannot put a Try... Catch block for error handling around a

module-level declaration. This restriction makes this style of object creation

less useful. In production-quality applications, you may want to stick to the

tried and true approach of first declaring the module-level variable and then

creating an instance with the New keyword in order to support full-featured

error handling.

In the declarations section:

Within a routine:

Continuing with the example, select your favorite style of object creation and

add it to the Sub Main.

m_oCustomer = New CCustomer("Acme Corporation")

Private m_oCustomer As CCustomer = New CCustomer()

Private m_oCustomer As New CCustomer()

If you need to pass parameters, this syntax becomes:

Private m_oCustomer As New CCustomer("Acme Corporation")

Private m_oCustomer as CCustomer

Try

m_oCustomer = New CCustomer()

Catch e As Exception

Debug.WriteLine(e.Message)

End Try

Visual Basic Unit 11

Sikkim Manipal University Page No.: 233

When you have finished using an object, you can call the object's Dispose

method to free the resources used by the object, assuming that a Dispose

method was implemented for the object. You can then set the object

variable to Nothing:

The object is then destroyed when the garbage collector detects that the

object is no longer used.

Note: Unlike Visual Basic 6, an object in .NET is not destroyed the moment

that the object variable is set to Nothing. Rather, it will be destroyed when

the garbage collector detects and destroys it. The garbage collector will

destroy an orphaned object, whether or not you set the object variable to

Nothing.

At this point, you should be able to execute the sample application and see

the debug messages appear in the Output window.

11.9 Using System.Object

Every object in .NET is inherited from a base class called System.Object.

This class is part of the Microsoft .NET Framework and contains the basic

properties and methods required for a .NET object.

Any public properties or methods defined in System.Object are

automatically provided in any object you create. For example,

System.Object contains a default constructor. If your object has no

constructor, it is still constructed because System.Object provides for the

construction.

Many of the public properties and methods of System.Object have a default

implementation. This means that you don't have to write any code to use

them. For example:

The ToString method provides the name of the component and class

associated with m_oCustomer. You can override the default behavior of the

m_oCustomer.Dispose() m_oCustomer = Nothing

m_oCustomer.ToString

Visual Basic Unit 11

Sikkim Manipal University Page No.: 234

ToString method with the Overrides keyword. This allows you to define

your own implementation of some System.Object properties and methods.

The ToString method now returns the name of the customer instead of the

name of the component and class.

11.10 Namespaces

The potential for conflicts between method names exists whenever you use

other people’s code. And even forgetting about these kind of conflicts, you

need some way to group thousands of methods in such a way that you have

some hope of remembering how they fit together.

Thus, there has to have a way of organizing information in as rich a

framework as is supplied with .NET. In .NET this is done with namespaces.

(You can create your own namespaces, and we show you how to do so later

in this chapter.)

The idea is that, just as every town seems to have its own Main Street,

every library of networking code might have its own Open method.

Namespaces give you a way to distinguish between them. For example, the

System.IO namespace is where you find methods to handle files and, as

you might expect, there is a class called File in it for handling files and it has

an Open method. Its full name is:

System.IO.File.Open

because the File class is part of the System.IO namespace and will not

conflict with another File class that might be part of the

Cornell.Morrison.NiftyClasses namespace, which could have its own Open

method.

11.11 The Imports Keyword

Just as we normally do not use a person's full name when referring to

people familiar to us, .NET also has a way of avoiding a lot of superfluous

verbiage. This is done through the use of the Imports statement. With the

right Imports statement, we can replace all those uses of:

System.Text.StringBuilder

Public Overrides Function ToString() As String Return Name End Function

Visual Basic Unit 11

Sikkim Manipal University Page No.: 235

with just a simple:

StringBuilder

Note that the System class is automatically imported into every solution you

build with Visual Studio. This is why you can use:

Console.WriteLine()

rather than

System.Console.WriteLine()

You can get or change the list of the namespaces that are automatically

imported for a solution by looking at the Imports page in the solution’s

property pages, as you can see in Figure 11.3:

Figure11.3: The Imports page in the solution’s property pages

In the Object Browser, the automatically imported Microsoft.VisualBasic

namespace contains the functions (such as the financial functions) that were

part of Visual Basic and were kept in VB .NET as shown in Figure 11.4.

If you import the Microsoft.VisualBasic.Constants, you can reuse most of the

VB constants that you have used before, such as vbCRLF. Note that the

.NET versions of many of these constants do not use a VB prefix (for

example, CrLf) and are stored in the Microsoft.VisualBasic.ControlChars

namespace.

The Imports statement goes before any other declarations, such as the ones

defining the name of a module, but after any Option directives, such as

Option Strict On or Option Compare Text.

Visual Basic Unit 11

Sikkim Manipal University Page No.: 236

Figure 11.4: The Microsoft.VisualBasic namespace in the Object Browser

Using Imports does not bloat your code, because it does not make all the

code in the namespace part of your project – it merely simplifies the typing

of the names of members of the classes in the namespace in your code. It

does not affect the speed of the resulting program either. Also, you can only

import namespaces that are part of a referenced assembly, which are what

you get by working with the Project|Add Reference dialog box.

Note: If two imported namespaces contain classes with identical names,

you have to give the full name of the class, including its namespace, to

distinguish them. (VB .NET will not allow you to create two classes with the

same name in the same namespace.)

Next, you can use a special version of Imports to simplify typing when you

have the potential for name conflicts with classes you have already

imported. For example, if you really wanted to use the VB6 compatibility

layer (not that we recommend it), you have to be aware that it will almost

certainly introduce namespace conflicts. You can add a reference to the VB

compatibility layer and then use a line like this:

Imports VB6Stuff = Microsoft.VisualBasic.Compatibility.VB6

and start writing VB6Stuff followed by a “.” whenever you need a member of

the compatibility layer, without having to worry about name conflicts.

You cannot import an individual class to avoid typing the class name for its

members. A statement such as:

Imports System.IO.DirectoryInfo

to simply get at the members of the DirectoryInfo class is not allowed.

Visual Basic Unit 11

Sikkim Manipal University Page No.: 237

11.12 Summary

This unit has covered the following topics:

OOP in Visual Basic .NET

Visual Basic .NET is not Visual Basic 6 with inheritance tacked onto it.

Rather, Visual Basic .NET has been entirely rewritten to be fully object-

oriented. In fact, everything in Visual Basic .NET can be treated as an

object. Yes, even your strings and integers can be accessed as objects in

Visual Basic .NET.

How to Objectify Your Programs

A good rule of thumb is that classes are the nouns in your analysis of the

problem. The properties are the adjectives that describe the noun. Of

course, the noun-verb-adjective correspondence to classes, methods, and

properties is only a first step. Only experience can help you decide which

nouns, verbs, and adjectives are the important ones.

Defining a Class

You still create classes for your business objects and for any supporting

objects that you may need for your application. You can create any number

of classes within a single code file. You can even create classes within

classes.

Relationships between Classes in Your Programs

Traditional OOP provides three possible relationships between classes:

• Use: dependency

• Containment: “has a” – this is sometimes called aggregation

• Inheritance: “is a”

The use relationship is both the most obvious and the most common,

because it is just a fancy way of saying one class depends on another.

Whenever an object sends a message to another object, the two obviously

depend on each other.

Inheritance in VB.Net

With inheritance, you can define a common class that is the basis of other

classes. This class is called a base or parent class. You then create any

specialized classes that inherit from the base class. These classes are

called derived or child classes. These classes inherit functionality from the

Visual Basic Unit 11

Sikkim Manipal University Page No.: 238

base class but can override base class functionality to perform specialized

processing.

Building Constructors and Destructors

Visual Basic .NET introduces true constructors that are executed whenever

a new instance of the class is created. These constructors are defined with

a subroutine named New. You can pass data to a constructor for more

flexibility and power in initializing the object. Instead of a Terminate event,

Visual Basic .NET provides a Finalize destructor. This destructor is called

when the .NET garbage collector determines that the object is not longer

needed.

Creating and Destroying an Object

In order to use a class, you first need to create an object from the class.

Everything is basically an object in Visual Basic .NET. When you have

finished using an object, you can call the object's Dispose method to free

the resources used by the object, assuming that a Dispose method was

implemented for the object. You can then set the object variable to Nothing

Using System.Object

Every object in .NET is inherited from a base class called System.Object.

This class is part of the Microsoft .NET Framework and contains the basic

properties and methods required for a .NET object. Any public properties or

methods defined in System.Object are automatically provided in any object

you create.

Namespaces

The potential for conflicts between method names exists whenever you use

other people’s code. And even forgetting about these kind of conflicts, you

need some way to group thousands of methods in such a way that you have

some hope of remembering how they fit together. Thus, there has to have a

way of organizing information in as rich a framework as is supplied with

.NET. In .NET this is done with namespaces.

The Imports Keyword

.NET has a way of avoiding a lot of superfluous verbiage. This is done

through the use of the Imports statement.

Visual Basic Unit 11

Sikkim Manipal University Page No.: 239

11.13 Terminal Questions

1. Explain the process of objectifying programs in VB.Net.

2. Describe the usage of relationships between classes.

3. Explain the usage of constructors and destructors in VB.Net programs

11.14 Answers

Self Assessment Questions

1. UDT

2. CBD

3. Abstraction

4. Classes

5. UML-based

6. Visual Basic .NET

7. Two

8. Containment

9. Overridable

10. Inherits

Terminal Questions

1. In the really old days we practiced what we called structured, procedure-

oriented programming. We identified what needed to be done and then

did one of two things, either:

Broke the task to be accomplished into subtasks, and these into smaller

subtasks, until the subtasks were simple enough to be implemented

directly (in other words, the top-down approach). (Refer Section 11.3)

2. Traditional OOP provides three possible relationships between classes:

• Use: dependency

• Containment: “has a” – this is sometimes called aggregation

• Inheritance: “is a”

The use relationship is both the most obvious and the most common,

because it is just a fancy way of saying one class depends on another.

(Refer Section 11.5)

3. Visual Basic .NET introduces true constructors that are executed

whenever a new instance of the class is created. These constructors are

defined with a subroutine named New. (Refer Section 11.7)

Visual Basic Unit 12

Sikkim Manipal University Page No.: 240

Unit 12 Inheritance and Interfaces – I

Structure:

12.1 Introduction

Objectives

12.2 Inheritance Basics

Getting started with Inheritance

Accessing the Parent Class's functionality

12.3 Overriding Properties and Methods

Viewing an Inheritance chain

Conversion and Member access rules

Polymorphism at Work

Shadowing

12.4 Abstract Base Classes

12.5 Summary

12.6 Terminal Questions

12.7 Answers

12.1 Introduction

In the previous unit, we discussed about application of OOP concepts in

VB.Net programming. In this unit, we start by showing you how to do

implementation inheritance in VB .NET.

Unfortunately, learning only the mechanics for doing implementation

inheritance is a very bad idea. We therefore spend a fair amount of time in

this unit showing you how to avoid these dangers through good design of

your inheritance chains.

Objectives:

After studying this unit, you should be able to:

describe the importance of inheritance in programming

apply the concept of overriding properties and methods of parent

classes in the child classes

describe inheritance chaining

explain the conversion and member access rules

illustrate the usage of polymorphism

explain the importance of shadowing in inheritance

describe the importance and applications of Abstract base classes

Visual Basic Unit 12

Sikkim Manipal University Page No.: 241

12.2 Inheritance Basics

Although inheritance is hardly the be-all, end-all of OOP, and interfaces are

often a better choice, you absolutely should not get the idea that you should

avoid using inheritance. Inheritance is a powerful tool that saves you a lot of

work if you use it correctly.

“Correctly” simply means that you should not use inheritance if it is not

absolutely clear that the “is a” relationship holds:

Class A should inherit from a class B only when it is absolutely clear

that, now and forever, you can always use an A object in place of a B

object without getting yourself into trouble.

You may see this fundamental rule in a more abstract form. This kind of

abstraction is necessary when you try to express the rule in a code-oriented

way:

An instance of a child class A that inherits from a parent class B must

be usable in every piece of code that would take an instance of its

parent type as a parameter. In other words if you have a function whose

header is

UseIt(bThing As B)

and aThing is an instance of the child class A, then the following code

must make sense:

UseIt(aThing)

If this seems too abstract, here is a made up (and hopefully humorous)

version of where it fails. Suppose you have a class called Manager and you

want to decide whether a person who manages programmers should inherit

from the Manager class rather than inherit from the Programmer class.

Because managers need big hair, as any Dilbert reader knows, you decide

you will have a property called SetHairStyle in your Manager class. Now

close your eyes and imagine a typical programmer (say his name is Tom)

who is suddenly made a manager of other programmers.

What does he look like hairstyle-wise? Can you imagine a call to:

tom.SetHairStyle(“sharp razor cut’)

always making sense? Sure, some programmers care about hairstyles but

we think it is fair to say that not every programmer does. The moral is a

ManagerOfProgrammers class should inherit from Programmer not

Manager.

Visual Basic Unit 12

Sikkim Manipal University Page No.: 242

Note: Some languages would permit a ManagerOfProgrammers class to

inherit from both a Manager and a Programmer class. Though quite logical

and appealing in principle, languages that support multiple inheritance (as

this ability is called), tend to be incredibly complicated to use in practice. VB

.NET uses its ability to implement multiple interfaces to deal with the

situations when multiple inheritance would otherwise be needed. As you will

soon see, using multiple interfaces it is a much cleaner approach to this kind

of situation than classic multiple inheritance.

Next, you have to be aware that there is no escaping inheritance in your VB

.NET programs. Even if you are completely comfortable with the interface

style of programming used in VB5 and VB6, and think containment and

delegation along with interfaces are the ways to go, you cannot use

interfaces exclusively in VB .NET. This is because it is impossible to use the

.NET Framework without explicitly using inheritance. For example, any .NET

GUI application depends on inheritance to work, as do many of the built-in

collection classes – even using the FolderBrowser object requires

inheritance!

In fact, the way inheritance is used in the .NET Framework is a perfect

example of why inheritance should not be completely replaced by interfaces

in object oriented programming. What happened in the .NET Framework

may well occur in your own projects:

When you build frameworks that other programmers will depend on,

well-designed, thoroughly debugged base classes can be used over and

over again via inheritance as the base on which they build their classes.

12.2.1 Getting Started with Inheritance

Let us start by recalling some terminology. The class you inherit from is

called the base or parent class. The class that inherits from it is called the

child or derived class. The child class automatically has all the public

functionality of the parent class, but you can modify the behavior of the

parent class in the child class. Inheritance is about specializing parent class

behavior and possible adding new behavior as well.

Here is an example of this process at work: suppose you have a company

with an enlightened raise policy. Whenever there is an across-the-board

raise of, say, 5 percent, programmers automatically get 6 percent (a 20

percent bonus). You are responsible for the design of the employee

Visual Basic Unit 12

Sikkim Manipal University Page No.: 243

management system for this company. You decide to make a class called

Programmer that inherits from Employee, and you want to change the

behavior of the RaiseSalary method in the Programmer class to reflect the

automatic (and well-deserved!) 20 percent bonus.

To build the code for this Employee⇒Programmer inheritance chain, let us

first assume that you have already written the code for a Public Employee

class that is either part of your solution or is already referenced via

Project|References. Assuming this is so, then the code for the Programmer

class starts out like this (the key line indicating inheritance is in bold):

Public Class Programmer

Inherits Employee

End Class

The Inherits keyword must be the first nonblank, non-comment line after the

name of the child class. (IntelliSense will automatically show you what

classes you can inherit from, by the way.) Note that a derived class cannot

use the Public access modifier if its parent class is marked Friend or Private.

The reason is that the access modifier you use for the derived class cannot

be less restrictive than the one used for its parent class.

But it can be more restrictive, so a class marked Friend class may inherit

from one marked Public, for example.

The next step in building a child class is to make sure that you give it the

correct kind of constructor. Because the child class must have at least the

same amount of functionality as its parent class, constructors for child

classes usually call the constructor of the parent class to correctly initialize

the instance fields of their parent class. This is done using the special

keyword MyBase, which accesses the parent class (as shown in the

following line in bold), passing in the right values for the constructor:

Public Sub New(ByVal theName As String, ByVal curSalary As

Decimal)

MyBase.New(Name, curSalary)

End Sub

The key line

MyBase.New(theName, curSalary)

Visual Basic Unit 12

Sikkim Manipal University Page No.: 244

calls the constructor of the base Employee class and correctly initializes its

instance fields. If you fail to have a call to MyBase.New when a parent class

requires arguments in its constructor, then VB .NET issues an error

message like this:

C:\vb net book\chapter 5\Example1\Example1\Module1.vb(55):

'Example1.Programmer', the base class of 'Example1.Employee',

does not have an accessible constructor that can be called with

no arguments.

Therefore, the first statement of this constructor must be a call to a

constructor of the base class via 'MyBase.New' or another constructor of

this class via 'MyClass.New' or 'Me.New' which is about as informative an

error message as one could hope to get and clearly reminds you that you

must call MyBase.New at least once if your parent class does not have a

no-argument constructor! After you add the call to MyBase.New, things get

very interesting: how do you access the instance fields of the parent class?

Here is the (we think surprising at first) rule:

A derived class has no privileged access to the instance fields of its

parent class.

This rule means that the derived Programmer class has no privileged

access to the private instance fields of its parent Employee class. For

example, suppose you store the salary in the parent class in a private

instance field called m_Salary and you try to sneak this code into the

Programmer class’s RaiseSalary method:

Public Sub New(ByVal theName As String, ByVal curSalary As

Decimal)

MyBase.New(theName, curSalary)

MyBase.m_salary = 1.2 * curSalary

End Sub

You would get this error message:

'Example1.Employee.m_Salary' is Private, and is not

accessible in this context.

So what do you do? If you want a child class to have access to specific

functionality in the parent class, it is up to the code in the parent class to

allow such access. We will show you how to do this in the next section.

Visual Basic Unit 12

Sikkim Manipal University Page No.: 245

12.2.2 Accessing the Parent Class’s functionality

VB .NET comes with a Protected access modifier that automatically gives

child classes access to the item specified with this modifier. This is true

whether the item is a member function or an instance field. You may be

tempted to use this modifier to make all instance fields of the parent class

Protected, to give derived classes a quick and dirty way to gain access to

the parent class’s instance fields. Do not give in to this temptation. Good

design principles dictate that the Protected access modifier should be used

only for member functions, not for instance fields.

Doing anything else violates encapsulation and prevents you from doing

validation in the place it belongs – the parent class. You need to rely on the

parent class to validate the data. As in real life, “trust but verify” is the

default behavior for good parenting!

For example, our original definition of the Employee class had members

with these signatures:

Public ReadOnly Property TheName() As String

Public ReadOnly Property Salary() As Decimal

so all classes could access these members. To make them accessible only

by derived classes of the parent, change the Public access modifier to

Protected.

You can use these access modifiers (Table 12.1) for the members of a class

in an inheritance chain.

Table 12.1: Access Modifiers for Inheritance

Access Modifier Meaning

Friend Access is limited to code in the current assembly.

Private Only objects of the parent’s type have access to these members.

Protected Access is limited to objects of the parent class type and objects of the type of any of its descendents.

Protected Friend Access is limited to the current assembly or types derived from the parent class.

Public All code that can access an object based on this class can access this member.

Visual Basic Unit 12

Sikkim Manipal University Page No.: 246

As we have said, having Protected and Protected Friend member functions

(but not instance fields) is quite common, because they let you prevent

outside code from accessing protected members.

However, there is a rather interesting gotcha to using Protected.

Fortunately, the compiler is quite good about giving you a clear warning you

when you fall into this hole. Here is a specific example: suppose you have a

class called GeekFest which contains a bunch of programmers with a

method called Boast that wants to access the Salary property in the

Programmer class. (Which means it is accessing the Salary property in the

parent Employee class ultimately). Here is how the code may look:

Now suppose the code in your Employee class had the read-only Salary

property marked Protected instead of Public:

This results in an error message:

C:\vb net book\chapter

5\Example1\Example1\Module1d.vb(19):

'Example1.Module1.Employee.Protected ReadOnly Property

Salary() As Decimal' is Protected, and is not accessible in this

context.

The point is that even though the Programmer class has access to the

protected Salary property in its code, Programmer objects do not have

Public Class GeekFest Private m_Programmers() As Programmer Sub New(ByVal Programmers() As Programmer) m_Programmers = Programmers End Sub Public Function Boast(ByVal aGeek As Programmer) As String Return "Hey my salary is " & aGeek.Salary End Function End Class

Protected ReadOnly Property Salary() As Decimal Get Return MyClass.m_Salary End Get End Property

Visual Basic Unit 12

Sikkim Manipal University Page No.: 247

access to this method when outside the code for the Programmer class. To

sum up:

Code can access protected methods of the parent class only when

inside objects of the derived class and not from objects of the child type

referred to in code outside the derived class.

Self Assessment Questions

1. Inheritance should not be used if it is not absolutely clear that the ____

relationship holds.

2. An instance of a child class A that inherits from a parent class B must be

usable in every piece of code that would take an ____ of its parent type

as a parameter.

3. The _____ keyword must be the first nonblank, non-comment line after

the name of the child class.

12.3 Overriding Properties and Methods

In our example of inheritance in which programmers automatically get a 6

percent raise when everyone else gets 5 percent, you need to change the

behavior of the RaiseSalary method to reflect the automatic 20 percent

bonus. This is called overriding a member function.

Note: You cannot override shared members.

Unlike many OOP languages, the syntax used in VB .NET makes it clear

that you want to override a method in the parent class by a method from the

child class. The clarity comes from the two required keywords:

Overridable: It is used in the parent class to indicate that a method can

be overridden.

Overrides: It is used in the child class to indicate that you are overriding

a method.

To have our basic Employee class override the special method of raising

salaries for an eventual Programmer or Manager class, you use code like

this:

Option Strict On

Public Class Employee

Private m_Name As String

Private m_Salary As Decimal

Visual Basic Unit 12

Sikkim Manipal University Page No.: 248

Private Const LIMIT As Decimal = 0.1D

Public Sub New(ByVal theName As String, ByVal curSalary As

Decimal)

m_Name = theName

m_Salary = curSalary

End Sub

Public ReadOnly Property TheName() As String

Get

Return m_Name

End Get

End Property

Public ReadOnly Property Salary() As Decimal

Get

Return MyClass.m_Salary

End Get

End Property

Public Overridable Overloads Sub RaiseSalary(ByVal Percent

As Decimal)

If Percent > LIMIT Then

'not allowed

Console.WriteLine("NEED PASSWORD TO RAISE SALARY

MORE " & _

"THAN LIMIT!!!!")

Else

m_Salary = (1 + Percent) * m_Salary

End If

End Sub

Public Overridable Overloads Sub RaiseSalary(ByVal Percent

As _

Decimal, ByVal Password As String)

If Password = "special" Then

m_Salary = (1 + Percent) * m_Salary

End If

End Sub

End Class

Visual Basic Unit 12

Sikkim Manipal University Page No.: 249

We use the optional Overloads keyword to make it clear that we have two

versions of RaiseSalary in this class.

Now assume that every programmer’s salary raise should be treated via a

call to the special RaiseSalary method. The child Programmer class looks

like this:

Notice how little code is needed in this child class – most of the functionality

remains unchanged, so we simply inherit it! If you add this code to the Sub

Main, the correct call to the RaiseSalary method (the one with the 20

percent bonus) is made by the compiler for any object that is an instance of

the Programmer class:

Sally will get her 20 percent bonus.

To summarize:

You can override only parent members marked with the Overridable

keyword.

If, at any point in the chain you want to stop the possibility of further

overriding of a method, mark it with the NotOverridable keyword.

VB .NET’s NotInheritable keyword prevents inheritance from a class (these

kinds of classes are sometimes called sealed or final classes). The main

reason to mark an entire class as NotInheritable is if the class has such vital

Public Class Programmer Inherits Employee Public Sub New(ByVal theName As String, ByVal curSalary As Decimal) MyBase.New(theName, curSalary) End Sub Public Overloads Overrides Sub RaiseSalary(ByVal Percent As Decimal) MyBase.RaiseSalary(1.2D * Percent, "special") End Sub End Class

Sub Main() Dim sally As New Programmer("Sally", 150000D) sally.RaiseSalary(0.1D) 'will actually give a 12% raise Console.WriteLine(sally.TheName & " salary is now " & sally.Salary()) Console.ReadLine() End Sub

Visual Basic Unit 12

Sikkim Manipal University Page No.: 250

behavior that you cannot risk changes to it. Many framework classes such

as String are marked as NotInheritable for this reason. However, you do not

have to mark a whole class as NotInheritable if all you want to do is place a

single member of the class off limits to overriding it: you can mark a member

you do not want overridden as NotOverridable.

Note: Members are not overridable by default. Still, we can use the

NotOverridable keyword to make our intentions clear.

You may occasionally want to access the parent class version of a method

that you have overridden. For example, suppose you want to add an

honorific like “Code Guru” to the name of every programmer. MyBase lets

you access the public TheName property of the parent class inside the child

class:

Limitations of MyBase keyword:

You cannot chain it to move to the “grandparent” if your inheritance

chain is that deep; MyBase.MyBase.MemberFunction is illegal.

MyBase is a keyword, and unlike Me, MyBase cannot be used with Is,

assigned to an object variable, or passed to a procedure.

Similarly, the MyClass keyword lets you be sure that even overridden

methods get called as defined in the current class whose code is running,

rather than as defined in some overridden method in a derived class.

Limitations of MyClass:

MyClass is also a keyword, not a real object. Therefore, as with MyBase,

MyClass cannot be used with Is, assigned to an object variable, or

passed to a procedure. (Use Me to refer to the actual instance.)

MyClass cannot be used to access Private members in the class (but

Me can).

Public Overrides ReadOnly Property TheName() As String Get Return "Code Guru " & MyBase.TheName() End Get End Property

Visual Basic Unit 12

Sikkim Manipal University Page No.: 251

12.3.1 Viewing an Inheritance Chain

The Class View and the Object Browser are useful when your inheritance

chain grows in complexity. For example, in Figure 12.1 you can see that the

Class View window shows you how the Programmer class inherits from the

Employee class and only overrides the constructor and the RaiseSalary

method.

Fig. 12.1: Viewing an Inheritance Chain

12.3.2 Conversion and Member Access Rules

You can store a variable of the child class in a variable of the parent class:

If Option Strict is on (as it should be), then once tom is stored in the

employeeOfTheMonth variable, you need to use the CType function to store

employeeOfTheMonth in a Programmer variable:

Dim tom As New Programmer("Tom", 65000) Dim employeeOfTheMonth As Employee employeeOfTheMonth = tom

Dim programmerOnCall As Programmer programmerOnCall = CType(employeeOfTheMonth, Programmer)

Visual Basic Unit 12

Sikkim Manipal University Page No.: 252

Since the compiler has no way of knowing this is acceptable beforehand. Of

course, storing tom in the programmerOnCall variable can be done with a

simple assignment:

Note: When you access the functionality of the tom object variable through

the employeeOfTheMonth Employee variable, you do not have access to

any of the unique members defined in the Programmer class. However, as

you will see in the next section, you would have access to all the members

of the Programmer class that override members of the Employee class.

12.3.3 Polymorphism at Work

One of the main goals of inheritance is to avoid the difficult-to-maintain

Select Case or If-Then-Else If statements by having the compiler and

polymorphism do all the work. For instance, this code works with both the

Employee and Programmer class:

When you run the code, you see Figure 12.2, which shows that the correct

RaiseSalary method is called even though we stored both employees and

programmers in an array of objects of the Employee type.

Figure 12.2: Polymorphism at Work

Sub Main() Dim tom As New Employee("Tom", 50000) Dim sally As New Programmer("Sally", 150000) Dim ourEmployees(1) As Employee ourEmployees(0) = tom ourEmployees(1) = Sally Dim anEmployee As Employee For Each anEmployee In ourEmployees anEmployee.RaiseSalary(0.1D) Console.WriteLine(anEmployee.TheName & " salary now is " & _ anEmployee.Salary()) Next Console.ReadLine() End Sub

Visual Basic Unit 12

Sikkim Manipal University Page No.: 253

Note: This is sometimes described by saying that in VB .NET the default is

that members of classes are virtual. (Virtual technically means that when the

compiler calls a member of an object, it should look at the true type of the

object, not just at what sort of container or reference it is used in.)

In the previous example, what “virtual” means is that even though the

references are to Employee objects (because everything is stored in an

Employee array), the compiler looks at the true type of Sally (she is a

Programmer) in order to call the correct RaiseSalary method (the one that

gives the better raise).

As you can imagine, the use of virtual methods when storing both parent

class objects (employees) and derived class objects (programmers) in a

container marked for by the type of the parent – is quite common. However,

there are some pitfalls in the simple approach we take to using virtual

methods here. To see these pitfalls for yourself, modify the Programmer

class to include a unique member, so that polymorphism will not be

involved. For example, add an instance field and property member as

shown here in the lines in bold:

Public Class Programmer Inherits Employee Private m_gadget As String Public Sub New(ByVal theName As String, ByVal curSalary As Decimal) MyBase.New(theName, curSalary) End Sub Public Overloads Overrides Sub RaiseSalary(ByVal Percent As Decimal) MyBase.RaiseSalary(1.2D * Percent, "special") End Sub Public Property ComputerGadget() As String Get Return m_Gadget End Get Set(ByVal Value As String) m_Gadget = Value End Set End Property End Class

Visual Basic Unit 12

Sikkim Manipal University Page No.: 254

and then change Sub Main by adding the lines in bold:

The modified code results in this error message:

C:\book to comp\chapter

5\VirtualProblems\VirtualProblems\Module1.vb(17):

The name 'Gadget' is not a member of 'VirtualProblems.Employee'.

The problem is that although Sally is a Programmer object and is stored in

the ourEmployees(1) array element, the compiler has no way of knowing

that and thus cannot find the ComputerGadget property. What is more,

unless you turn Option Strict off (which is a dangerous practice, in our

opinion), you must explicitly convert this array entry to the Programmer type

to use these unique members of the Programmer class:

Console.WriteLine(ourEmployees(1).TheName & " gadget is an " &

_

CType(ourEmployees(1), Programmer).ComputerGadget)

The process of converting a reference stored in a parent class object

variable to a child class object is usually called down casting. (Converting

from a child class to the parent class is thus called up casting) Although it is

a common practice, down casting should be avoided whenever possible,

because it often requires you to check the type of an object variable via

code like this:

Sub Main() Dim tom As New Employee("Tom", 50000) Dim sally As New Programmer("Sally", 150000) sally.ComputerGadget = "Ipaq" Dim ourEmployees(1) As Employee ourEmployees(0) = tom ourEmployees(1) = sally Dim anEmployee As Employee For Each anEmployee In ourEmployees anEmployee.RaiseSalary(0.1D) Console.WriteLine(anEmployee.TheName & " salary now is " _ & anEmployee.Salary()) Next Console.WriteLine(ourEmployees(1).TheName & " gadget is an " _ & ourEmployees(1).Gadget) Console.ReadLine() End Sub

Visual Basic Unit 12

Sikkim Manipal University Page No.: 255

If TypeOf ourEmployees(1) Is Programmer Then

'

Else If TypeOf ourEmployees(1) Is Employee Then

'

End If

which, as you can see, requires bringing back the kind of selection

statements that you used polymorphism to banish in the first place! (Up

casting, of course, never causes problems because the fundamental rule of

inheritance is that child objects can be used any place parent objects are

used.)

12.3.4 Shadowing

In earlier versions of VB, as in most programming languages, shadowing

meant that a local variable with the same name as a variable of larger scope

hid the variable with larger scope. (This is one reason the convention arose

to use m_ as a prefix for module-level variables and g_ for global variables.

Using a good naming convention helps prevent shadowing bugs.) You can

think of overriding an inherited method as a special kind of shadowing. For

better or for worse, VB .NET allows another extraordinarily powerful kind of

shadowing:

If you mark a member of a derived class with the Shadows keyword

(which was introduced in beta 2), it hides any members of the parent

class with the same name.

The Shadows keyword can even be used to have a sub in the parent class

and a function with the same name in a child class. For all practical

purposes, shadowing makes a totally new member in the derived class with

that name, and thus makes any inherited members with the name being

shadowed unavailable in the derived class.

This, in turn, means overriding inherited members that have been shadowed

is no longer possible and polymorphism cannot work. Shadowing gets tricky

and can cause subtle bugs when you want to use polymorphism on a

container of, say, Employee objects and you have shadowed a member.

To see this kind of problem at work, modify the Programmer class with the

lines in bold:

Public Class Programmer

Inherits Employee

Visual Basic Unit 12

Sikkim Manipal University Page No.: 256

Private m_gadget As String

Private m_HowToCallMe As String = "Code guru "

Public Sub New(ByVal theName As String, ByVal curSalary As Decimal)

MyBase.New(theName, curSalary)

m_HowToCallMe = m_HowToCallMe & theName

End Sub

Public Overloads Overrides Sub RaiseSalary(ByVal Percent As Decimal)

MyBase.RaiseSalary(1.2D * Percent, "special")

End Sub

Public Shadows ReadOnly Property TheName() As String

Get

Return m_HowToCallMe

End Get

End Property

End Class

Sub Main()

Dim tom As New Employee("Tom", 50000)

Dim sally As New Programmer("Sally", 150000)

Console.WriteLine(sally.TheName)

Dim ourEmployees(1) As Employee

ourEmployees(0) = tom

ourEmployees(1) = sally

Dim anEmployee As Employee

For Each anEmployee In ourEmployees

anEmployee.RaiseSalary(0.1D)

Console.WriteLine(anEmployee.TheName & " salary now is " & _

anEmployee.Salary())

Next

Console.ReadLine()

End Sub

Figure 12.3 below shows the output:

Figure 12.3: Shadowing causes polymorphism to fail.

Visual Basic Unit 12

Sikkim Manipal University Page No.: 257

As you can see, polymorphism has stopped working. The first bold line in

the code correctly gives Sally the honorific of “Code Guru” before her name.

Unfortunately, the second bold line no longer works polymorphically, so it no

longer uses the correct TheName method in the Programmer derived class.

The result is that you do not see the honorific. In other words, if you use the

Shadows keyword, members of objects get called by the kind of container

the object is stored in, not by what their ultimate types are. (You could also

say that using the Shadows keyword in a derived class makes a member

nonvirtual.)

Self Assessment Questions

4. Shared members cannot be overridden. (True / False)

5. The ____ keyword lets you be sure that even overridden methods get

called as defined in the current class whose code is running, rather than

as defined in some overridden method in a derived class.

6. The process of converting a reference stored in a parent class object

variable to a child class object is usually called _______.

12.4 Abstract Base Classes

Once you start designing inheritance into your programs, you soon realize

that you often can take advantage of a great deal of common functionality.

For example, contractors are not employees, but they still have information

in common with employees, such as having a name, an address, a tax ID

number, and so on. It might make sense to push common code back as far

as possible into a base class called PayableEntity which has an address

and a tax ID number as properties.

The process of searching for common functionality that you can put into a

common base class, usually called Factoring, is a useful design practice

that lets you take abstraction to its logical conclusion.

However, the factoring process sometimes leads you to a class where some

of the methods are not really implementable, even though they clearly are

common to all the classes in the inheritance chain.

For example, with a class called PayableEntity as the common base class

for both contractors and employees, you might decide that this foundational

class should have a property called TaxID. Now, as should be the case, you

Visual Basic Unit 12

Sikkim Manipal University Page No.: 258

want to check that the format for the tax ID number is correct, by using code

inside a property procedure.

Well, here you are faced with a problem:

Social Security numbers take a different form from the tax ID used by

certain kinds of contractors. This means the verification code for this

property cannot be built into the PayableEntity base class, but must be in

the child classes, because only they can know what form the tax ID must

take.

For these kinds of situations, you build an abstract base class. This is a

class that has at least one member function marked with the MustOverride

keyword, and the class itself is marked with the MustInherit keyword. Here is

an example of what an abstract PayableEntity, MustInherit class looks like:

Notice that the member marked with the MustOverride keyword consists of

just the Property statement with no code inside of it. In general, a member

marked with the MustOverride keyword has only a header and cannot use

an End Property, End Sub, or End Function statement.

Also notice that we were able to use a concrete implementation of the read-

only property TheName, which shows abstract classes can combine

nonabstract members with abstract members. An Employee class that

inherits from the abstract PayableEntity class might look like this, with the

key new lines in bold:

Public Class Employee

Inherits PayableEntity

Private m_Salary As Decimal

Public MustInherit Class PayableEntity Private m_Name As String Public Sub New(ByVal itsName As String) m_Name = itsName End Sub ReadOnly Property TheName() As String Get Return m_Name End Get End Property Public MustOverride Property TaxID() As String End Class

Visual Basic Unit 12

Sikkim Manipal University Page No.: 259

Private m_TaxID As String

Private Const LIMIT As Decimal = 0.1D

Public Sub New(ByVal theName As String, ByVal curSalary As Decimal, _

ByVal TaxID As String)

MyBase.New(theName)

m_Salary = curSalary

m_TaxID = TaxID

End Sub

Public Overrides Property TaxID() As String

Get

Return m_TaxID

End Get

Set(ByVal Value As String)

If Value.Length <> 11 then

'need to do something here - see Chapter 7

Else

m_TaxID = Value

End If

End Set

End Property

ReadOnly Property Salary() As Decimal

Get

Return MyClass.m_Salary

End Get

End Property

Public Overridable Overloads Sub RaiseSalary(ByVal Percent As Decimal)

If Percent > LIMIT Then

'not allowed

Console.WriteLine("NEED PASSWORD TO RAISE SALARY MORE " & _

"THAN LIMIT!!!!")

Else

m_Salary = (1D + Percent) * m_Salary

End If

End Sub

Public Overridable Overloads Sub RaiseSalary(ByVal Percent As _

Visual Basic Unit 12

Sikkim Manipal University Page No.: 260

Decimal, ByVal Password As String)

If Password = "special" Then

m_Salary = (1D + Percent) * m_Salary

End If

End Sub

End Class

The first of the key lines is in the constructor, which now has to call the

constructor of the abstract base class in order to set the name properly. The

second group of key lines adds the most trivial concrete implementation of

the MustOverRide TaxId property. (Note that this code does not do the

needed verification of tax ID numbers here, as you would in a more robust

example.)

Here is a Sub Main you can use to test this program:

Sub Main()

Dim tom As New Employee("Tom", 50000, "111-11-1234")

Dim sally As New Programmer("Sally", 150000, "111-11-2234")

Console.WriteLine(sally.TheName)

Dim ourEmployees(1) As Employee

ourEmployees(0) = tom

ourEmployees(1) = sally

Dim anEmployee As Employee

For Each anEmployee In ourEmployees

anEmployee.RaiseSalary(0.1D)

Console.WriteLine(anEmployee.TheName & " has tax id " & _

anEmployee.TaxID & ", salary now is " & anEmployee.Salary())

Next

Console.ReadLine()

End Sub

Finally, you cannot create a MustInherit class directly. A line like this:

Dim NoGood As New PayableEntity("can't do")

gives this error message:

Class 'PayableEntity' is not creatable because it contains at least one

member marked as 'MustOverride' that hasn't been overridden.

Visual Basic Unit 12

Sikkim Manipal University Page No.: 261

You can, however, assign an object from a derived class to a variable of an

abstract base class type or a container for it (which allows polymorphism to

work its magic):

Example: The CollectionBase Class

The trouble with .NET Framework classes such as ArrayList or HashTable is

that they contain objects, so you always have to use the CType function to

get back to the correct type after you place something in such a collection.

You also run the risk that somebody will put the wrong type of object in the

container and the call to CType will fail. A strongly typed collection is a

container that can only hold objects of a single type or its derived types.

A good example of an abstract base class in the .NET Framework is

CollectionBase, whose derived classes allow you to build strongly typed

collections (Before you embark on creating your own collection class

inheriting from CollectionBase, make sure that the framework does not

already contain the class you need, in the System.Collections.Specialized

Namespace.)

Such type-safe collections rely on an abstract base class called

System.Collections.CollectionBase, and all you have to do is implement

concrete Add and Remove methods and an Item property. This is because

the System.Collections.CollectionBase already has an internal list that holds

the data – you need only delegate the other tasks to this internal list.

Here is an example that builds this kind of specialized collection (which

assumes the Employee class is either referenced or part of this project):

1 Public Class Employees

2 Inherits System.Collections.CollectionBase

3 ' Restricts to adding only Employee items

4 ' delegating to the internal List object's Add method

5 Public Sub Add(ByVal aEmployee As Employee)

6 List.Add(aEmployee)

7 End Sub

8 Public Sub Remove(ByVal index As Integer)

Dim tom As New Employee("Tom", 50000, "123-45-6789") Dim whoToPay(13) As PayableEntity whoToPay(0) = tom

Visual Basic Unit 12

Sikkim Manipal University Page No.: 262

9 If index > Count - 1 Or index < 0 Then

10 ' outside the range, should throw an exception (Chapter 7)

11 MsgBox("Can't add this item") 'MsgBox as a marker for an exception

12 Else

13 List.RemoveAt(index)

14 End If

15 End Sub

16

17 Default Public ReadOnly Property Item(ByVal index As Integer) As

Employee

18 Get

19 Return CType(List.Item(index), Employee)

20 End Get

21 End Property

22 End Class

Lines 5–7 implement the abstract Add method in the base class by

delegating it to the internal List object, so that it will accept only Employee

objects. Lines 8–10 implement the Remove method. Here we are delegated

to the internal List object’s Count and Index properties to make sure we are

not at the end or beginning of the list. Finally, lines 17–21 implement the

Item property. We make this the default property because this is what users

expect for a collection. We make it read-only to prevent someone from

adding an item except via the Add method. It would certainly be acceptable

to make it a read-write property, but that would require some extra code to

verify that the index you add the item to is acceptable. Assuming you have

the basic Employee class, here is some code to test this specialized

collection with an illegal addition (a string) commented out (but in bold):

Visual Basic Unit 12

Sikkim Manipal University Page No.: 263

As an experiment, try uncommenting the myEmployees.Add("Tom") line.

You will see that the code will not even compile and you end up with this

error message:

C:\book to comp\chapter

5\EmployeesClass\EmployeesClass\Module1.vb(9):

A value of type 'String' cannot be converted to

'EmployeesClass.Employee'.

12.5 Summary

This unit has covered the following topics:

Inheritance Basics

Inheritance is a powerful tool that saves you a lot of work if you use it

correctly. “Correctly” simply means that you should not use inheritance if it is

not absolutely clear that the “is a” relationship holds:

• Class A should inherit from a class B only when it is absolutely clear

that, now and forever, you can always use an A object in place of a B

object without getting yourself into trouble.

Overriding Properties and Methods

The syntax used in VB .NET makes it clear that you want to override a

method in the parent class by a method from the child class. The clarity

comes from the two required keywords:

Overridable: It is used in the parent class to indicate that a method can

be overridden.

Sub Main() Dim tom As New Employee("Tom", 50000) Dim sally As New Employee("Sally", 60000) Dim myEmployees As New Employees() myEmployees.Add(tom) myEmployees.Add(sally) ' myEmployees.Add("Tom") Dim aEmployee As Employee For Each aEmployee In myEmployees Console.WriteLine(aEmployee.TheName) Next Console.ReadLine() End Sub

Visual Basic Unit 12

Sikkim Manipal University Page No.: 264

Overrides: It is used in the child class to indicate that you are overriding

a method.

Abstract Base Classes

Once you start designing inheritance into your programs, you soon realize

that you often can take advantage of a great deal of common functionality.

The process of searching for common functionality that you can put into a

common base class, usually called Factoring, is a useful design practice

that lets you take abstraction to its logical conclusion. An abstract base

class is a class that has at least one member function marked with the

MustOverride keyword, and the class itself is marked with the MustInherit

keyword.

12.6 Terminal Questions

1. Explain the concept of Inheritance in VB.Net.

2. Describe the theory behind Overriding Properties and Methods.

3. Describe the usage of Abstract Base Classes.

12.7 Answers

Self Assessment Questions

1. “is a”

2. instance

3. Inherits

4. True

5. MyClass

6. down casting

Terminal Questions

1. Although inheritance is hardly the be-all, end-all of OOP, and interfaces

are often a better choice, you absolutely should not get the idea that you

should avoid using inheritance. Inheritance is a powerful tool that saves

you a lot of work if you use it correctly. (Refer Section 12.2)

2. Unlike many OOP languages, the syntax used in VB .NET makes it clear

that you want to override a method in the parent class by a method from

the child class. The clarity comes from the two required keywords:

Visual Basic Unit 12

Sikkim Manipal University Page No.: 265

Overridable: It is used in the parent class to indicate that a method

can be overridden.

Overrides: It is used in the child class to indicate that you are

overriding a method. (Refer Section 12.3)

3. The process of searching for common functionality that you can put into

a common base class, usually called Factoring, is a useful design

practice that lets you take abstraction to its logical conclusion. However,

the factoring process sometimes leads you to a class where some of the

methods are not really implementable, even though they clearly are

common to all the classes in the inheritance chain. (Refer Section 12.4)

Visual Basic Unit 13

Sikkim Manipal University Page No.: 266

Unit 13 Inheritance and Interfaces – II

Structure:

13.1 Introduction

Objectives

13.2 Object: The Ultimate Base Class

The most useful Members of Object

Equals and ReferenceEquals

The ToString method

GetType and Reflection

MemberWiseClone

The Fragile Base Class Problem: Versioning

13.3 Overview of Interfaces

Mechanics of implementing an Interface

When to use Interfaces, when to use Inheritance?

Important Interfaces in the .NET Framework

13.4 Summary

13.5 Terminal Questions

13.6 Answers

13.1 Introduction

In the previous unit, we discussed about the basics of inheritance, overriding

properties and methods.

In this unit we would show you the ins and outs of the Object class. This is

the class that all .NET objects ultimately inherit from. We finish the

discussion of implementation inheritance by showing what .NET does to

help solve the fragile base class problem that is at the root of many of the

implementation inheritance problems in other OOP languages such as Java

or C++. (The fragile base class problem is a fancy way of saying that the

wrong change to a parent class can cause a disaster in the child classes

that inherit from it.)

After discussing inheritance, we will move on to implementing interfaces in

VB .NET. We end this unit by showing you how to use some of the

important interfaces in the .NET Framework, such as IComparable,

ICloneable, and IDisposable.

Visual Basic Unit 13

Sikkim Manipal University Page No.: 267

Objectives

After studying this unit, you should be able to:

describe the Object class which is a parent of all the classes

describe various useful members of Object class

explain and illustrate the Equals and ReferenceEquals method

explain the methods: TOString, GetType, and Reflection

illustrate the usage of MemberWise cloning

describe the Versioning problem

describe the importance and implementation of interfaces

differentiate and apply the usage of inheritance and interfaces

discuss important interfaces in .Net Framework

13.2 Object: The Ultimate Base Class

The .NET Framework (and hence VB .NET) depends on every type

inheriting from the common Object type, this is the ultimate ancestor of all

classes. (OOP speak often calls such a class the cosmic base class.) This

includes both reference types (instances of a class) and value types

(instance of a struct, enum, dates or numeric types). This means, for

example, that any function that takes a parameter of Object type can be

passed a parameter of any type (since the fundamental rules of inheritance

that we mentioned earlier require that child class variables be usable in any

context that parent class variables can be used).

For example, there are a few useful built-in Boolean functions that

determine whether the kind of data you are working with take an object

variable:

• IsArray: Tells you if an object variable is an array

• IsDate: Tells you if an object can be interpreted as a date and time

value

• IsNumeric: Tells you if the object can be interpreted as a number

The Object class itself splits up into two streams of descendants: those that

inherit from System.ValueType (the base class for all value types) and the

reference types that descend directly from Object. You can determine if a

derived type is a value type with code like this:

Visual Basic Unit 13

Sikkim Manipal University Page No.: 268

13.2.1 The Most Useful Members of Object

Because every type in VB .NET inherits from Object, it is likely that you will

often use (or more likely, override) these methods.

Important Note: You will often be tempted to override the Object class’s

protected Finalize method. In theory, you override the Finalize method in

your code to create cleanup code that runs when the garbage collector

reclaims the memory your object uses. Do not do this in practice. Because

you cannot be sure when the Finalize method will run or in what order it will

run, using it for cleanup is chancy at best. Instead, you should implement a

Dispose method as described later on in this chapter in the section on the

IDisposable interface. If you do override the Finalize method, be aware you

must call MyBase.Finalize inside the Finalize method, and you should

always duplicate any Dispose code there as well.

13.2.2 Equals and ReferenceEquals

The Object class supplies two versions of Equals, one shared and one not.

The shared version has this syntax:

Overloads Public Shared Function Equals(Object, Object) As Boolean

and is used in this form:

Equals(a, b)

The nonshared version has the syntax:

Overloads Overridable Public Function Equals(Object) As Boolean

and is used in this form:

a.Equals(b)

The two versions of the Equals method are designed to determine whether

two items have the same value, but you should be prepared to overload

equals if it makes sense in your class. Keep in mind that because shared

members of classes cannot be overridden, you can only override the

Sub Main() Dim a As Integer = 3 Console.WriteLine("a is a value type is " & IsValueType(a)) Console.ReadLine() End Sub Function IsValueType(ByVal thing As Object) As Boolean Return (TypeOf (thing) Is System.ValueType) End Function

Visual Basic Unit 13

Sikkim Manipal University Page No.: 269

nonshared version of Equals. For example if you have two ways of

representing objects in a value type, you should make sure that Equals can

handle this (The designers did this for the String class as well, although

strictly speaking, this is not a value type.)

The Object class also provides a shared (and therefore not overridable)

version of a method called ReferenceEquals. The ReferenceEquals method

determines whether two items refer to the same object; that is, whether the

specified Object instances are the same instance. For example, two strings,

a and b, can have a.Equals(b) true and ReferenceEquals(a, b) false, as this

code shows:

Fig. 13.1: The difference between Equals and ReferenceEquals

13.2.3 The ToString Method

The ToString method returns a string that represents the current object.

How successful this representation is to debugging and to the user of the

class depends on the implementer of the class. The default implementation

of ToString returns the fully qualified type name of the object. For example:

System.Object

OR

Example1.Programmer

You should get into the habit of overriding ToString for your own classes

where you can give a more meaningful string representation of the class.

Sub Main() Dim a As String = "hello" Dim b As String = "Hello" Mid(b, 1, 1) = "h" Console.WriteLine("Is a.Equals(b)true? " & a.Equals(b)) Console.WriteLine("Is ReferenceEquals(a, b) true? " & _ ReferenceEquals(a, b)) Console.ReadLine() End Sub

Visual Basic Unit 13

Sikkim Manipal University Page No.: 270

Example:

The result is:

EmployeeTest1.EmployeeTest1+Employee my name is Tom

13.2.4 GetType and Reflection

Every type in the .NET Framework is represented by a Type object. The

Type class is full of mouth-twisting members such as the GetMembers

method, which lets you get at the members of that class by name. The idea

is that the GetType method in Object returns a Type object that you can use

to query what functionality a type offers you at run time.

This extremely useful feature lets you perform reflection (which sometimes

called runtime type identification). In fact, the Reflection namespace is so

important to the smooth functioning of the .NET Framework that it is

automatically imported into every project in the VS IDE.)

To see reflection at work, add a reference to the System.Windows.Forms

assembly and then run the following program. When you start seeing a

prompt (it will take a moment) press Enter and you will eventually see

something like Figure 13.2. You can keep on pressing Enter and you will

eventually you see all of the members of the Windows.Forms.Form class

(there are many), which is the basis for GUI applications in .NET.

Public Overrides Function ToString() As String Dim temp As String temp = Me.GetType.ToString() & " my name is " & Me.TheName Return temp End Function

Visual Basic Unit 13

Sikkim Manipal University Page No.: 271

Fig. 13.2: The members of the Windows.Forms.Form class via reflection

The key lines 6 and 7 let us retrieve a Type object that represents a

Windows.Forms.Form class. Then, because the GetMembers method of the

Type class returns a collection of MemberInfo objects that describe the

member, we simply iterate through all the members of this class in lines

11–14.

You can replace this code with an instance of another class to see its

members, and you can also get a Type object by passing the fully qualified

name of the class as a string to a version of GetType that is a shared

member of Type class. Reflection allows for late binding in VB .NET via the

InvokeMember method, which takes a string that identifies the member you

want to call (which presumably you discovered by reflection).

1 Option Strict On 2 Imports System.Windows.Forms 3 Module Module1 4 Sub Main() 5 Dim aForm As New Windows.Forms.Form() 6 Dim aType As Type 7 aType = aForm.GetType() 8 Dim member As Object 9 Console.WriteLine("This displays the members of the Form class") 10 Console.WriteLine(" Press enter to see the next one.") 11 For Each member In aType.GetMembers 12 Console.ReadLine() 13 Console.Write(member.ToString) 14 Next 15 Console.WriteLine("Press enter to end") 16 Console.ReadLine() 17 End Sub 18 End Module

Visual Basic Unit 13

Sikkim Manipal University Page No.: 272

13.2.5 MemberWiseClone

First off, in programming, as in modern science:

• A clone is an identical copy of an object.

• The clone’s state can change from the original object’s state but most

important:

• Changes to the clone should not affect the object it was cloned from.

The last point is what makes cloning tricky in any OOP language and it is

why MemberWiseClone is such a potentially dangerous method. The

problem is that objects can have objects inside of them and, if you do not

clone the internal objects at the same time as you clone the object that

contains them, you end up with objects that are joined at the hip and depend

on each other as a result – not what you want in a clone.

The problem is that whenever an object has mutable objects as one of its

instance fields, the MemberWiseClone method always gives you just such

an ill-formed, half-baked kind of clone, known as a shallow copy. The

MemberWiseClone method successfully clones only objects whose

instances fields are value types.

The following example illustrates the meaning of the above stated last point.

Arrays in VB .NET, unlike in VB6 are objects. Consider this class which has

an array as an instance field that we want to try to clone:

1 Public Class EmbeddedObjects 2 Private m_Data() As String 3 Public Sub New(ByVal anArray() As String) 4 m_Data = anArray 5 End Sub 6 Public Sub DisplayData() 7 Dim temp As String 8 For Each temp In m_Data 9 Console.WriteLine(temp) 10 Next 11 End Sub 12 Public Sub ChangeData(ByVal newData As String) 13 m_Data(0) = newData 14 End Sub 15 Public Function Clone() As EmbeddedObjects 16 Return CType(Me.MemberwiseClone, EmbeddedObjects) 17 End Function 18 End Class

Visual Basic Unit 13

Sikkim Manipal University Page No.: 273

Now run this Sub Main:

The result is pretty dramatic, as you can see in Figure 13.3: the change to

the ―clone‖ affected the original object!

Fig. 13.3: Why MemberWiseClone generally will not work?

What is going on in this example? Why does MemberWiseClone fail? Why

do changes to object b affect object a? The reason is that in lines 2 and 4 of

the EmbeddedObject class, we used an array as an instance field that is set

in the constructor.

Arrays are mutable objects, this means the contents of an array can be

changed even when passed ByVal. We changed the state of the internal

array in lines 12–14 of the EmbeddedObjects class. Because the object and

its ―clone‖ are joined by the reference to the m_Data array, these changes

persist when we changed the clone, as you just saw.

Sub Main() Dim anArray() As String = {"HELLO"} Dim a As New EmbeddedObjects(anArray) Console.WriteLine("Am going to display the data in object a now!") a.DisplayData() Dim b As EmbeddedObjects b = a.Clone() Dim newData As String = "GOODBYE" b.ChangeData(newData) Console.WriteLine("Am going to display the data in object b now!") b.DisplayData() Console.WriteLine("Am going to re-display the data in a" & _ " after making a change to object b!!!") a.DisplayData() Console.ReadLine() End Sub

Visual Basic Unit 13

Sikkim Manipal University Page No.: 274

You will see how to fix this example in the section on ICloneable later in this

unit. For now, we merely point out that a true clone (sometimes called a

deep copy) creates clones of all the instance fields of the object, and

continues doing it recursively if necessary. For example, if a class has an

object instance field that in turn has another object instance field, the cloning

process must go two layers down.

Finally, as a way of dealing with its potential problems, the designers of the

.NET Framework made MemberWiseClone a protected member of Object.

This means, as you saw earlier, that only the derived class itself can call

MemberWiseClone. Code from outside the derived class cannot call this

dangerous method in order to clone an object. Also note that

MemberWiseClone returns an Object, which is why we had to use the

CType function in line 16 of the EmbeddedObjects class.

13.2.6 The Fragile Base Class Problem: Versioning

The versioning problem occurred all too often in programming for earlier

versions of Windows, usually in the form of DLL hell – you used a version of

a DLL and a new version came along that broke your code. Why did it break

your code?

The reasons were as obvious as someone inadvertently removing a function

you depended on in the second version, or as subtle as changing the return

type of a function. In any case, all the sources of DLL hell amount to

variations on a theme: someone changes the public interface of code you

depend on, your program is no longer able to use the newer DLL in place of

the older one, and the older one is overwritten.

Whenever you used inheritance in most other OOP languages, you greatly

increased the risk of your code breaking because of versioning issues. You

had to depend on all of the public and protected members of classes higher

up in the food chain not changing in a way that would break your code.

This situation is called the Fragile Base Class Problem: because

inheritance often seems to make our programs resemble a house of cards,

and any disturbance to the bottom layer (the base class) causes the whole

house to fall down. The best way to see this problem in action is to work

with some code. Start by coding the following PayableEntity class into a

Visual Basic Unit 13

Sikkim Manipal University Page No.: 275

separate class library and then compile it into an assembly called

PayableEntityExample by choosing Build.

Close the solution after you have built this DLL.

Now suppose you decide to add a way of getting an address into an

Employee class that depends on the PayableEntity base class,

remembering that we are only going to use the class in its compiled form. To

do this you will need to add a reference to the assembly that contains this

project by going into the \bin subdirectory where you built the

PayableEntityExample DLL. The code for our Employee class might look

like the following; note the line in bold where we inherit from the abstract

class defined in the PayableEntityExample assembly:

Public Class Employee

'since the namespace is PayableEntityExample, the full name of the class

'is PayableEntityExample.PayableEntity!

Inherits PayableEntityExample.Employee

Private m_Name As String

Private m_Salary As Decimal

Private m_Address As String

Private m_TaxID As String

Private Const LIMIT As Decimal = 0.1D

Public MustInherit Class PayableEntity Private m_Name As String Public Sub New(ByVal theName As String) m_Name = theName End Sub Public ReadOnly Property TheName() As String Get Return m_Name End Get End Property Public MustOverride Property TaxID() As String End Class

Visual Basic Unit 13

Sikkim Manipal University Page No.: 276

Public Sub New(ByVal theName As String, ByVal curSalary As

Decimal,_

ByVal TaxID As String)

MyBase.New(theName)

m_Name = theName

m_Salary = curSalary

m_TaxID = TaxID

End Sub

Public Property Address() As String

Get

Return m_Address

End Get

Set(ByVal Value As String)

m_Address = Value

End Set

End Property

Public ReadOnly Property Salary() As Decimal

Get

Return m_Salary

End Get

End Property

Public Overrides Property TaxID() As String

Get

Return m_TaxID

End Get

Set(ByVal Value As String)

If Value.Length <> 11 Then

'need to do something here

Else

m_TaxID = Value

End If

End Set

End Property

End Class

Visual Basic Unit 13

Sikkim Manipal University Page No.: 277

The Sub Main might look like this:

The output is shown in Figure 13.4 below:

Fig. 13.4: A simple program with no versioning yet

You compile this into Versioning1.exe and everyone is happy!

Now, let us imagine the PayableEntity class is actually supplied by a third

party. The brilliant designers of the PayableEntity class are not sitting on

their laurels, so they decide to do what they actually should have done in the

first place: they add an address object to their class, then recompile and

send you the new DLL.

Although they might not send you the source code, we give it to you here.

Notice the change to the constructor (in bold):

Imports Microsoft.VisualBasic.ControlChars

Public Class PayableEntity

Private m_Name As String

Private m_Address As Address

Public Sub New(ByVal theName As String, ByVal theAddress As

Address)

m_Name = theName

m_Address = theAddress

End Sub

Public ReadOnly Property TheName() As String

Get

Return m_Name

End Get

End Property

Public ReadOnly Property TheAddress()

Get

Sub Main() Dim tom As New Employee("Tom", 50000) tom.Address = "901 Grayson" Console.Write(tom.TheName & " lives at " & tom.Address) Console.ReadLine() End Sub

Visual Basic Unit 13

Sikkim Manipal University Page No.: 278

Return m_Address.DisplayAddress

End Get

End Property

End Class

Public Class Address

Private m_Address As String

Private m_City As String

Private m_State As String

Private m_Zip As String

Public Sub New(ByVal theAddress As String, ByVal theCity As String, _

ByVal theState As String, ByVal theZip As String)

m_Address = theAddress

m_City = theCity

m_State = theState

m_Zip = theZip

End Sub

Public Function DisplayAddress() As String

Return m_Address & CrLf & m_City & ", " & m_State _

& crLF & m_Zip

End Function

End Class

This is, of course, an example of truly lousy programming at work. The

developers who coded this managed to lose the original constructor in the

process of ―improving‖ the original version, something that should never be

done. Still, horrors like this did happen and, in the olden days, you probably

would have the old DLL installed on a user’s hard disk, usually in

Windows/System.

Then the new DLL would come along, overwrite the previous version, and

your previously happily running Versioning1 program would break.

Granted, designers of base classes should not do this, but we all know they

did. Try this under .NET, however, and something wonderful happens: your

old program continues to run just fine, because it uses the original

PayableEntity DLL which is automatically stored in the \bin directory of the

Versioning1 solution.

Note: Ultimately, the .NET Framework solves the versioning problem by

making sure your class knows which version of a DLL it depends on and

Visual Basic Unit 13

Sikkim Manipal University Page No.: 279

refuses to run if the correct version is not present. This process is

successful because of the magic of assemblies. However, you can still

circumvent the help .NET’s versioning scheme gives you by copying the

new DLL to the location of the older DLL under the scenario we just

sketched.

.NET’s versioning scheme allows the vendor of a .NET component to add

new members to the next version of their base class (even though the

practice should not be encouraged). Vendors can do this even if the new

member happens to have the same name as a member that you

inadvertently added to a child class that depended on their base class. The

old executable created from the derived class continues to work, because it

will not use the new DLL.

Actually, this is not quite true: it does run fine—until you reopen the source

code for the Versioning1 code in VS .NET, reference the new

PayableEntityExample DLL and try to rebuild the Versioning1 code. At that

point, you will see an like error message like this:

C:\book to comp\chapter 5\Versioning1\Versioning1\Module1.vb(21):

No argument specified or non-optional parameter 'theAddress' of

'Public Sub New(theName As String, theAddress

As PayableEntityExample.Address)'.

The point is once you load up the old source code for the derived class and

reference the new DLL, you will not be able to recompile the code until you

fix the incompatibility that the vendor of the parent class stuck you with.

Before we end this section, we want to make sure that you are not thinking

that eliminating a constructor in favor of a different constructor is a pretty

drastic mistake. Does .NET versioning protect you from more subtle

problems? The answer is yes.

Consider the most common, if subtle, source of versioning problems when

you use inheritance: a Derived class depends on a Parent base class. You

introduce a ParseIt method in the Derived class (as in the following code

where we merely add carriage return/line feed combinations in the parts of

the string we want to display):

Imports Microsoft.VisualBasic.ControlChars

Module Module1

Sub Main()

Visual Basic Unit 13

Sikkim Manipal University Page No.: 280

Dim myDerived As New Derived()

myDerived.DisplayIt()

Console.ReadLine()

End Sub

End Module

Public Class Parent

Public Const MY_STRING As String = "this is a test"

Public Overridable Sub DisplayIt()

Console.WriteLine(MY_STRING)

End Sub

End Class

Public Class Derived

Inherits Parent

Public Overrides Sub DisplayIt()

Console.WriteLine(ParseIt(MyBase.MY_STRING))

End Sub

Public Function ParseIt(ByVal aString As String)

Dim tokens() As String

'actually split defaults to splitting on spaces

tokens = aString.Split(Chr(32))

Dim temp As String

'rejoin them into one string adding a CR/LF betweeen the words

temp = Join(tokens, CrLf)

Return temp

End Function

End Class

End Module

The output is shown in Figure 13.5 below:

Fig. 13.5: A simple parsing program at work

Now imagine you are supplied the Parent class in compiled form instead of

in source form. And, when you are shipped Version 2 of the Parent class, it

comes with its own version of ParseIt that it uses extensively in its code.

Visual Basic Unit 13

Sikkim Manipal University Page No.: 281

Because functions in VB .NET are virtual, polymorphism dictates that calls

to DisplayIt when an object of type Derived is stored in an object variable of

type Parent, will always use the ParseIt method of the Derived class and not

the ParseIt method in the parent class. However, we now have a potential, if

very subtle, versioning problem.

In this scenario, the code in the Parent class that uses its version of ParseIt

function does not know how the Derived class implemented ParseIt. Using

the derived class version of ParseIt, as polymorphism requires, could break

what is needed for the parent class’s functioning.

Self Assessment Questions

1. The ________ boolean function tells you if an object variable is an array.

2. We override the _______ method in your code to create cleanup code

that runs when the garbage collector reclaims the memory your object

uses.

3. The _______ method determines whether two items refer to the same

object; that is, whether the specified Object instances are the same

instance.

4. The default implementation of _______ method returns the fully qualified

type name of the object.

13.3 Overview of Interfaces

We hope we have convinced you that inheritance has its place in VB .NET,

but you need to also master interfaces to take full advantage of VB .NET’s

OOP features. We take this powerful feature up in the next few sections.

First off, think of implementing an interface as making a binding contract

with any class that uses your class. Interface-style programming is the

foundation of what is called object composition or black box reuse in OOP

theory. Interfaces, of course, were also at the heart of COM programming,

and how OOP was done in earlier versions of VB.) With interfaces, you rely

on the class you depend on to expose certain functionality defined by the

signature of the header of the member, now and forever.

Unlike inheritance, there are no dependencies involved with interfaces –

each implementation of an interface can stand on its own.

Visual Basic Unit 13

Sikkim Manipal University Page No.: 282

When you implement an interface, you:

• Assert that your code will have methods with certain signatures

• Have code (possibly even empty code) with those signatures inside the

class

The actual implementation of these members can vary and, as we just said,

they can even do nothing. All you do is make a promise to have certain code

with certain signatures. This simple promise has a lot of nice consequences.

Some of the best ones are:

• It lets a smart compiler replace calls into your code with a fast table

lookup and a jump.

• From the programmer’s point of view, it lets developers call code in your

classes by signature, without fear that the member does not exist.

• The binding contract also lets a compiler use polymorphism just as well

as inheritance chains do.

13.3.1 Mechanics of Implementing an Interface

Many programming shops (Microsoft, for example) subscribe to the notion of

a lead programmer or lead tester on a team. Suppose you want to extend

your employee management program to allow for the idea of a Lead

Programmer or Lead Tester with certain special properties such as having a

morale fund to cheer up people when they have been working too hard.

In building this possibility into an Employee Management system program,

you cannot use inheritance in VB .NET, because the Programmer class and

the Tester class already inherit from the Employee class and only single

inheritance is allowed in .NET. This is a perfect example of where an

interface comes to your rescue.

The first step is to define the interface. Unlike VB6, in which an interface

was merely a class, VB .NET has an Interface keyword. For example, let us

suppose leads have to rate team members and they get to spend the

morale fund. The interface definition would look like this:

Public Interface ILead Sub SpendMoraleFund(ByVal amount As Decimal) Function Rate(ByVal aPerson As Employee) As String Property MyTeam() As Employee() Property MoraleFund() As Decimal End Interface

Visual Basic Unit 13

Sikkim Manipal University Page No.: 283

There are no access modifiers such as Public or Private in an interface

definition; the only valid modifiers for Sub, Function, or Property statements

are Overloads and Default. Defining an interface is thus pretty easy. Any

class implementing our ILead interface makes a contract to have:

• A sub that takes a decimal as a parameter

• A function that takes an Employee object and returns a string

• A read-write property that returns an array of Employee objects

• A read-write property that returns a decimal

And, as you will soon see, the names of members in the implementing

methods do not matter – the key point is that they have the promised

signature.

To implement an interface in a class, the first step is to make sure the

interface is referenced or already part of the solution. Next, you include the

Implements keyword in the line following the class name and any Inherits

statement.

Example:

At this point, you will see that the keyword ILead is underscored by a blue

squiggly line indicating a problem. This is because the compiler is insisting

that you fulfill your contract, even if only by using empty methods.

How do you do this? Unlike earlier versions of VB, which used a specific

form of the signature to indicate a member implemented an interface, VB

.NET indicates this directly, as you can see in the bold second line in this

code:

Public Class LeadProgrammer Inherits Programmer Implements ILead End Class

Public Function Rate(ByVal aPerson As Employee) As String _ Implements ILead.Rate End Function

Visual Basic Unit 13

Sikkim Manipal University Page No.: 284

Although it is certainly common to match up the names of the interface

member and the member that implements it, it is not necessary. For

example, this is perfectly acceptable:

The key point is that the parameter and return types match the signature

used for that part of the interface. You can use any legal attributes on that

kind of method – Overloads, Overrides, Overridable, Public, Private,

Protected, Friend, Protected Friend, MustOverride, Default, and Static

modifiers – and still fulfill the contract. The Shared attribute is the only one

you cannot use, because interface methods must be instance members, not

class members.

If you use a Private member of a class to implement an interface member,

then the only way to get at that member is through a variable of that

interface’s type. Otherwise, unlike earlier versions of VB, you can always

access interface members through an object of the class type. You no

longer have to assign it to a variable of the interfaces type.

Example:

To go the other way, however, you must use CType:

but a line like this is not possible:

aName = tom.TheName 'NOT ALLOWED

Public Property OurMoraleFund() As Decimal Implements ILead.MoraleFund Get Return m_MoraleFund End Get Set(ByVal Value As Decimal) m_MoraleFund = Value End Set End Property

Dim tom As New LeadProgrammer("Tom", 65000) tom.SpendMoraleFund(500)

Dim tom As New LeadProgrammer("Tom", 65000) Dim aLead As ILead, aName As String aLead = tom aName = Ctype(aLead, Programmer).TheName ' OK

Visual Basic Unit 13

Sikkim Manipal University Page No.: 285

In general, here are the rules for converting between an object type and an

interface it implements:

• You can always assign a variable declared to be of the class type to the

variable declared to be of any interface type that the class implements.

In particular, if a method takes as a parameter a variable of an interface

type, you can pass into it a variable of any type that implements the

interface. (This rule is analogous to the fundamental inheritance rule that

derived types can always be used in place of their parent types.) However:

You must use CType to go from a variable of the interface type to a variable

of a type that implements the interface. To determine if an object

implements an interface, use TypeOf with Is.

Example:

Here is the full version of our LeadProgrammer class. Of course, we have

not done much in the implementation of the interface members, but this

code gives you an idea of what you can do:

Public Class LeadProgrammer

Inherits Programmer

Implements ILead

Private m_MoraleFund As Decimal

Private m_MyTeam As Employee()

Public Function Rate(ByVal aPerson As Employee) As String _

Implements ILead.Rate

Return aPerson.TheName & " rating to be done"

End Function

Public Property MyTeam() As Employee() _

Implements ILead.MyTeam

Get

Return m_MyTeam

End Get

Set(ByVal Value As Employee())

m_MyTeam = Value

Dim tom As New LeadProgrammer("tom", 50000) Console.WriteLine((TypeOf (tom) Is ILead)) returns True.

Visual Basic Unit 13

Sikkim Manipal University Page No.: 286

End Set

End Property

Public Sub SpendMoraleFund(ByVal amount As Decimal) _

Implements ILead.SpendMoraleFund

'spend some money

Console.WriteLine("Spent " & amount.ToString())

End Sub

Public Property OurMoraleFund() As Decimal Implements

ILead.MoraleFund

Get

Return m_MoraleFund

End Get

Set(ByVal Value As Decimal)

m_MoraleFund = Value

End Set

End Property

Public Sub New(ByVal theName As String, ByVal curSalary As Decimal)

MyBase.New(theName, curSalary)

End Sub

End Class

13.3.2 When to Use Interfaces, When to Use Inheritance?

Although an interface seems a lot like an abstract class, this analogy can be

more trouble than it is worth to follow. An abstract class can have many

concrete members, but an interface can have none. You should create

abstract base classes only after a thoughtful process of factoring common

behavior out to the most primitive ancestor possible, and for no other

reason.

An interface exists outside an inheritance chain – that is its virtue. You lose

the ability to automatically reuse code, but you gain the flexibility of choosing

your own implementation of the contract. Use an interface when you want to

indicate that certain behavior is required, but you are willing to leave the

actual implementation of the behavior to the implementing class.

In .NET, structures cannot inherit from anything except Object, but they can

implement interfaces. Interfaces are the only choice available to you in .NET

Visual Basic Unit 13

Sikkim Manipal University Page No.: 287

when two classes have some common behavior but there is no ancestor

they are both examples of.

13.3.3 Important Interfaces in the .NET Framework

We obviously cannot cover all the interfaces in the .NET Framework in

these few pages, but we want to mention a few of the most important ones.

Two are in some sense marker interfaces, because you implement them to

advertise that your classes have a certain type of functionality that many

classes may want to exhibit.

These marker interfaces are:

• ICloneable: Indicates a Clone method that provides a deep copy

• IDisposable: Tells the user that your class consumes resources that the

garbage collectors will not be able to reclaim

ICloneable

.NET’s designers decided to let you indicate that you are providing this

feature through a marker interface called ICloneable, which contains one

member Clone:

Implement this interface (and hence the Clone method) if you want to offer

users of your class the opportunity to clone instances of that class. It is then

up to you to decide if using MemberWiseClone is enough when you actually

implement the Clone method in your class. As we said previously,

MemberWiseClone is enough if the instance fields are value types or

immutable types like String.

IDisposable

We have mentioned that you should not rely on the Finalize method to clean

up after resources that the automatic garbage collector cannot know about.

The convention in .NET programming is to implement the IDisposable

interface instead, because it has a single member Dispose, which should

contain the code to reclaim resources.

Public Interface ICloneable Function Clone() As Object End Interface

Public Interface IDisposable Sub Dispose() End Interface

Visual Basic Unit 13

Sikkim Manipal University Page No.: 288

Self Assessment Questions

5. The _____ style programming is the foundation of what is called object

composition or black box reuse in OOP theory.

6. To determine if an object implements an interface, use TypeOf with

_________.

7. The __________ marker interface tells the user that your class

consumes resources that the garbage collectors will not be able to

reclaim.

13.4 Summary

This unit has covered the following topics:

Object: The Ultimate Base Class

The .NET Framework (and hence VB .NET) depend on every type inheriting

from the common Object type, this is the ultimate ancestor of all classes.

This includes both reference types (instances of a class) and value types

(instance of a struct, enum, dates or numeric types). This means, for

example, that any function that takes a parameter of Object type can be

passed a parameter of any type.

Overview of Interfaces

Implementing an interface is making a binding contract with any class that

uses your class. Interface-style programming is the foundation of what is

called object composition or black box reuse in OOP theory. With interfaces,

you rely on the class you depend on to expose certain functionality defined

by the signature of the header of the member, now and forever. Unlike

inheritance, there are no dependencies involved with interfaces – each

implementation of an interface can stand on its own.

13.5 Terminal Questions

1. Describe the following methods of the Object class in VB.Net:

a. Equals and ReferenceEquals

b. MemberWiseClone

2. Explain the Mechanics of Implementing an Interface.

Rule: If your class uses a class that implements IDisposable you must call the

Dispose method.

Visual Basic Unit 13

Sikkim Manipal University Page No.: 289

13.6 Answers

Self Assessment Questions

1. IsArray

2. Finalize

3. ReferenceEquals

4. ToString

5. Interface

6. Is

7. IDisposable

Terminal Questions

1. The Object class supplies two versions of Equals, one shared and one

not. The shared version has this syntax:

Overloads Public Shared Function Equals(Object, Object) As

Boolean

and is used in this form:

Equals(a, b)

The nonshared version has the syntax:

Overloads Overridable Public Function Equals(Object) As

Boolean

and is used in this form:

a.Equals(b) (Refer Section 13.2)

2. Many programming shops (Microsoft, for example) subscribe to the

notion of a lead programmer or lead tester on a team. Suppose you

want to extend your employee management program to allow for the

idea of a Lead Programmer or Lead Tester with certain special

properties such as having a morale fund to cheer up people when they

have been working too hard. (Refer Section 13.3)

Visual Basic Unit 14

Sikkim Manipal University Page No.: 290

Unit 14 Multithreading in Visual Basic

Structure:

14.1 Introduction

Objectives

14.2 Getting Started with Multithreading

14.3 The Mechanics of Thread Creation

14.4 Joining Threads

14.5 Thread Names, CurrentThread, and ThreadState

14.6 The Threads Window

14.7 Sleep Method

14.8 Ending or Interrupting a Thread

14.9 Suspending or Killing a Thread

14.10 Daemon (Background) Threads

14.11 Summary

14.12 Terminal Questions

14.13 Answers

14.1 Introduction

In the previous units, we have studied different applications of VB.Net using

different objects, and controls. In this unit, we would be studying the concept

of running various applications simultaneously in VB.Net. using

multithreading.

Multitasking is a feature of modern operating systems that we all take for

granted. After all, we expect to be able to run a word processor and an

e-mail program at the same time and not have them be in conflict, or have

the word processor stop working if e-mail needs to be downloaded. Of

course, what actually happens is that the operating system rapidly switches

between the programs that are running on the CPU (unless you have

multiple CPUs of course).

This gives the impression that multiple programs are running at the same

time, because even the fastest typist (or for that matter, the fastest Internet

connection) cannot keep up with the speed of even one modern CPU.

Multithreading, in a way, is the next level of multitasking: instead of having

the operating system switch between different programs, multithreading

Visual Basic Unit 14

Sikkim Manipal University Page No.: 291

asks the operating system to switch between different parts of the same

program. Multithreading allows an e-mail program to download new

messages while you are reading or composing another message.

Multithreading, too, is a feature we all seem to take for granted.

VB has never really done multithreading. It is true that, starting with VB5, it

did get a form of multithreading, called apartment threading. As you will

soon see, apartment threading is multithreading on training wheels. And,

like training wheels, apartment threading gives you some of the benefits of

multithreading, but prevents you from accessing its full power in an attempt

to keep you safe. We all need to remove the training wheels sooner or later,

and VB .NET is the first version of VB that does so.

However, multithreading is not an easy feature to fully implement in a

programming language or for programmers to master. Why?

Because multithreading can cause extraordinarily subtle bugs in your

code that seem to occur randomly (the most frustrating kind of bugs!).

Objectives:

After studying this unit, you should be able to:

define and describe the concept of multithreading

explain various mechanisms of Thread creation

illustrate the usage of Join concept in combining one or more threads

describe the thread properties: Thread Names, CurrentThread, and

ThreadState

describe the ThreadWindow

illustrate the process of making a thread sleep by using Sleep method

illustrate the mechanism of ending or interrupting a thread

explain the importance of Daemon(Background) threads

14.2 Getting Started with Multithreading

Multithreading is the most sophisticated form of programming. If you are not

exceedingly careful, you can create bugs that are almost impossible to find

and cost a fortune to fix.

For this reason, some of the programs in this chapter are bad programs - we

purposefully designed them in order to show you how things can go wrong.

We think the safest approach to learning multithreaded programming is to

Visual Basic Unit 14

Sikkim Manipal University Page No.: 292

see what can go wrong even when, on the surface, a program looks like it

should work. You must become more aware of potential problems and ways

of avoiding them if you want to use multithreaded programming techniques.

Still, as dangerous as it can be, multithreading is required if you are to solve

certain programming problems in a professional way. If your programs do

not use multithreading when it is called for, users will be seriously

disappointed and will choose someone else’s program. For example, it was

not until Eudora’s fourth version that the popular e-mail program had the

multithreaded features that modern e-mail programs must have if they are

not to seriously frustrate users. By the time Eudora implemented

multithreading, many people had moved on to other products.

(One of us who was using Eudora as his primary e-mail program stopped

using it because a multithreaded version was not available then.)

Finally, there is no escaping multithreading in .NET: all .NET programs are

multithreaded, since the garbage collector runs as a low priority thread in

the background. And as you will soon learn, serious GUI programming in

.NET depends on using threads correctly in order to keep GUI programs

responsive when parts of your code are running time-consuming processes.

The term thread comes from “thread of execution,” which is used to mean

that every program is running in a certain context. The context describes

how the thread is using memory for storing its code and data. If you store

the context, you essentially store a thread of execution within your program.

Taking a snapshot of the thread’s context takes time. The operating system

has to freeze the thread’s context and store it somewhere when it passes

control to another thread. When the program wants to restart the stopped

thread, it has to restore the thread’s context, which takes more time. You

should use multithreading only when the benefit outweighs the cost. Here

are some typical examples of when this is true:

When there is a natural division of the users handling the program, as in the

example of downloading e-mail while composing new e-mail

When you need to do a complicated calculation in a GUI-intensive

program and do not want your GUI to become unresponsive

When you need to take full advantage of a multiprocessor computer

running an operating system that can use multiple processors (in this

Visual Basic Unit 14

Sikkim Manipal University Page No.: 293

case, as long as you keep the number of active threads to be less than

the number of CPUs, you should incur little or no thread overhead)

Before we delve into the mechanics of writing multithreaded programs, we

want to clear up one common source of confusion amongst people new to

multithreaded programming:

A thread runs a procedure, not an object.

We are not sure what “running an object” means, but one of us often

teaches multithreading programming, and this question seems to be the

uppermost in many people’s minds. Perhaps they are thinking that a thread

should start only by calling the New method of a class, and then that thread

then runs any messages sent to that object. This is completely wrong. A

single object can have multiple threads running different (or even the same)

methods, so different threads are sending and responding to specific

messages sent to the object.

Because a thread is created from a method of an object, you usually must

have previously created the object. After you build the object, you create the

thread by passing it the address of the method inside the object, and then

you tell the thread to start running that method. Of course, a procedure that

a thread was created to run, like all procedures, can create new objects or

manipulate existing objects. It can also call other procedures or functions

that are visible to it. The other vital point to keep in mind is:

• A thread ends when the procedure that you used to create it ends and

will not end normally until this procedure ends.

.NET keeps most of the functionality you call upon to use threads with in the

Threading namespace. Most programs that use threads therefore begin

with:

Imports System.Threading

to simplify typing and to make IntelliSense most useful.

Next, as you might expect, delegates figure prominently into the picture,

since threads run procedures. In particular, the .NET Framework comes with

a ThreadStart delegate in the Threading namespace that you usually use to

start a thread. Here is the syntax for using this delegate:

Public Delegate Sub ThreadStart()

Visual Basic Unit 14

Sikkim Manipal University Page No.: 294

The procedure a ThreadStart delegate calls must be a parameterless

subprocedure. Thus, you cannot build a thread using a function (since this

returns a value) or a procedure that takes parameters. What is more, you

must have alternative methods to get information out of a thread, because

the methods they run do not have return values, nor can they use ByRef

parameters.

For example, if ThreadMethod sits inside a class called WillUseThread, then

you can have the ThreadMethod affect the properties of instances of the

WillUseThread class to pass information out of the ThreadMethod

procedure.

We will introduce the various concepts of multithreading in subsequent

sections.

14.3 The Mechanics of Thread Creation

Let us start with a trivial example: suppose you want to run, in a separate

thread, a procedure that simply decrements a counter forever. Here is the

class that contains the procedure:

Because the test Do Loop is always true, you would think that the

SubtractFromCounter sub would run without interruption. However, through

the magic of threads, this will not quite happen.

Public Class WillUseThreads Public Sub SubtractFromCounter() Dim count As Integer Do While True count -= 1 Console.WriteLine("Am in another thread and counter =" _ & count) Loop End Sub End Class

Visual Basic Unit 14

Sikkim Manipal University Page No.: 295

Here is the Sub Main and the Imports statement we need to get the thread

to run:

Let us go over the key points one by one. First, Sub Main always runs in

what is called the main thread. A .NET program always has at least two

threads running: the main thread and the garbage collection thread. In line 1

we make a new instance of the test class. In line 2 we create a ThreadStart

delegate by passing to it the address of the parameterless sub named

SubtractFromCounter in the instance of the test class we created in line 1.

Because we import the Threading namespace, we do not need to use the

long form ThreadMethod.

We actually create the thread in line 3. Notice that the constructor for the

Thread class requires a ThreadStart delegate. Some people like to combine

the two lines into one (logical) line:

Dim bThread As New Thread(New ThreadStart(AddressOf _

myTest.SubtractFromCounter))

Finally, line 4 “starts” the thread by calling the Start method on the instance

of the Thread class you created with a ThreadStart delegate. This tells the

system to run the Subtract function on its own thread.

Option Strict On Imports System.Threading Module Module1 Sub Main() 1 Dim myTest As New WillUseThreads() 2 Dim bThreadStart As New ThreadStart(AddressOf _ myTest.SubtractFromCounter) 3 Dim bThread As New Thread(bThreadStart) 4 bThread.Start() Dim i As Integer 5 Do While True Console.WriteLine("In main thread and count is " & i) i += 1 Loop End Sub End Module

Visual Basic Unit 14

Sikkim Manipal University Page No.: 296

Figure 14.1 is an example of what might happen after you run this program

for a while and then stop it with Ctrl+Break. In our case, the counter got up

to 341 in the main thread before it decided to actually run the new thread!

Figure 14.1: A simple mutithreaded program stopped while running

If you run the program a little longer, you will see something like Figure 14.2,

which shows that the separate thread was put on hold while the main thread

got to run again. What happens is called preemptive multithreading through

time slicing and we take up what this mouthful means next.

Figure 14.2: Switching between threads in a simple multithreaded program

Visual Basic Unit 14

Sikkim Manipal University Page No.: 297

The operating system uses what is known as preemptive multithreading

through time slicing, to interrupt threads and give other threads time to run.

Certain ways of doing time slicing also solve one of the more common

troubles with multithreading programs – a phenomenon called starvation,

which occurs when you have one thread that takes up all the CPU cycles

and never releases control to the other threads. (Typically, this is the result

of using tight loops like the ones in our example program).

To prevent starvation, make sure your threads give up some time to the

other threads. The next best solution is to have an operating system that

always preempts running threads, no matter how high their priority, so that

every thread gets at least a small slice of time to work in.

By adding this line to the example thread program, right before the call to

start the thread, even low priority threads get a chance at some CPU time:

bThread.Priority=ThreadPriority.Highest

This tells Windows to run the new thread with its highest priority and makes

the main thread a lower priority.

Figure 14.3 shows that the new thread starts running sooner than it did

previously, but Figure 14.4 shows that the main thread still gets some time

(admittedly, only a very small amount of time, and only after the subtracting

thread ran for a long while).

The results you get when you run the program will be similar to those shown

in Figures 14.3 and 14.4, but because of differences between your system

and ours, they will not be identical.

Visual Basic Unit 14

Sikkim Manipal University Page No.: 298

Figure 14.3: Highest priority thread (usually) starts up quicker

Fig. 14.4: Lower priority thread is still not starved

Visual Basic Unit 14

Sikkim Manipal University Page No.: 299

The ThreadPriority enumeration has five levels:

1. ThreadPriority.Highest

2. ThreadPriority.AboveNormal

3. ThreadPriority.Normal

4. ThreadPriority.BelowNormal

5. ThreadPriority.Lowest

Self Assessment Questions

1. Instead of having the operating system switch between different

programs, _____ asks the operating system to switch between different

parts of the same program.

2. A thread runs a ____, not an object.

14.4 Joining Threads

You sometimes need to stop a thread until another thread has finished

doing some work. For example, you may want thread 1 to wait until

computations in thread 2 are finished. You set this up by calling the Join

method on thread 2 while running thread 1. In other words, code like this:

thread2.Join()

puts the current thread to sleep and it waits until thread 2 is over. Thread 1

is now a blocked thread.

If you join thread 1 to thread 2, the operating system will (eventually) start

thread 1 once thread 2 ends. (The jargon says it is now unblocked.)Keep in

mind that this process is nondeterministic: you cannot know exactly how

soon after thread 2 finishes will thread 1 start up again.

There is another version of Join that returns a Boolean value:

thread2.Join(Integer)

This method either waits for the thread 2 to die or waits for a specified time

in milliseconds to expire before thread 2 is unblocked, so that it will be

scheduled to run again by the operating system. This method returns true if

thread 2 dies before the timeout specified, and false if it does not.

Visual Basic Unit 14

Sikkim Manipal University Page No.: 300

14.5 Thread Names, CurrentThread, and ThreadState

Get into the habit of giving each of your threads a name before you start

them. This helps a great deal when debugging programs involving threads.

You do this via the Name property of thread objects with code like this:

bThread.Name = "Subtracting thread"

Also, you can always get a reference to the thread that is running a piece of

code by using Thread.CurrentThread, which returns a reference to the

currently running thread.

Again, saying that threads are scheduled in a nondeterministic manner is a

fancy way of saying you have very little control over what scheduling the

operating system is doing. For this reason, you will occasionally want to

make a call to the ThreadState property, which returns a value that indicates

the current state of a thread.

14.6 The Threads Window

Visual Studio .NET’s Threads window is a great help in dealing with

threaded programs. You make this window active when you are in break

mode by going to the Debug|Windows submenu. Suppose, for example, you

name bThread via a call to:

bThread.Name = "Subtracting thread"

After you use Ctrl+Break (or some other method) to stop the program, your

Threads window will look something like Figure 14.5.

Figure 14.5: The Threads window

Visual Basic Unit 14

Sikkim Manipal University Page No.: 301

The arrow in the first column marks the active thread, the same thread you

get by calling Thread.CurrentThread. The ID column merely lists a number

that identifies each thread. The next column gives the name of the thread (if

you assigned it one).

The next column identifies the code currently running. (For example, the

WriteLine procedure in the Console class, as shown in Figure 10-5). The

remaining columns indicate the priority level and whether the thread is

suspended.

The Threads window lets you – and not the operating system – control

threads in your program via the context menu for each item. For example,

you can freeze the current thread by right-clicking on its line and choosing

Freeze (you can later unfreeze it). Because the operating system cannot run

a frozen thread, this can be a useful in debugging when you need to isolate

a misbehaving thread. You can also make another (nonfrozen) thread active

by right-clicking on its line and choosing Switch to Thread (double-clicking

the thread also works). This is extremely useful when analyzing a program

for possible deadlocks.

14.7 Sleep Method

You may occasionally want to tell a thread to Sleep when it is not needed. A

sleeping thread is another example of a blocked thread. When you put a

thread to sleep, the other threads in the program obviously have more CPU

cycles to play with.

A common syntax for Sleep is:

Thread.Sleep(Number of milliseconds)

which tells the currently active thread to sleep for at least the specified

number of milliseconds. (It may not wake up exactly at that moment,

however.)

Notice the lack of a reference to a specific thread – you can only tell the

currently executing thread to sleep. This version of Sleep makes the current

thread relinquish the rest of its time slice:

Thread.Sleep(0)

Visual Basic Unit 14

Sikkim Manipal University Page No.: 302

This version tells the current thread to go to sleep indefinitely (only a call to

Interrupt can waken it):

Thread.Sleep(Timeout.Infinite)

Because you can interrupt a sleeping thread (even if it is sleeping

indefinitely) with a call to the Interrupt method, which throws a

ThreadInterruptedException, you should use Sleep only in a Try-Catch

block, as in this framework:

Self Assessment Questions

3. The .NET Framework comes with a _____ delegate in the Threading

namespace that you usually use to start a thread.

4. The phenomenon of _____ occurs when you have one thread that takes

up all the CPU cycles and never releases control to the other threads.

5. The ______________ statement tells Windows to run the new thread

with its highest priority and makes the main thread a lower priority.

14.8 Ending or Interrupting a Thread

A thread ends when you get to the end of the method used to create it in the

ThreadStart delegate, but you may need a way to end the method (and thus

the thread) when certain events occur. It is occasionally useful to direct a

thread to check a condition variable to decide if it should end abnormally.

Creating a framework for using a condition variable involves placing code

that tests the condition variable and then exits the Sub if the condition

variable exists. The most common way to do this is to have an enclosing

Do-While loop in your Sub:

Try Thread.Sleep(200) Catch tIe As ThreadInterruptedException 'thread interrupted Catch e As Exception 'other exception End Try

Visual Basic Unit 14

Sikkim Manipal University Page No.: 303

If you need to check the condition variable at a special place, use an If-Then

with the Exit Sub keywords inside an infinite loop.

Unfortunately, code in a sleeping thread (or one that is otherwise blocked) is

not running, so polling the condition variable will not work. In this case, you

need to:

Call the Interrupt method on an object variable that references the

thread.

You can call Interrupt only on a thread in a Wait, Sleep, or Join thread state.

If you do call interrupt on a thread in one of these states, then (eventually)

the thread will start up again, and the runtime will trigger a Thread

Interrupted Exception in the thread. This happens even if the thread has

been put to sleep indefinitely via a call to Thread. Sleep (Timeout .Infinite).

(We say eventually, because of the nondeterministic nature of thread

scheduling.)

In this case, you Catch the ThreadInterruptedException and write cleanup

code in the Catch clause. However, the Catch clause is not required to end

the thread in response to an interruption – that is up to the thread itself!

14.9 Suspending or Killing a Thread

Two other methods in the threading namespace interrupt the normal

functioning of a thread:

Suspend

Abort

We are not sure why these methods were included in .NET, because using

either Suspend or Abort is likely to leave your programs in an unstable state.

Neither method gives a thread a reasonable chance to do any cleanup. If

Sub ThreadedMethod() 'you need to have a way to poll the condition variable 'for example, it can be a property of a class that you have a reference to Do While conditionVariable = False And MoreWorkToDo 'all the code goes here Loop End Sub

Visual Basic Unit 14

Sikkim Manipal University Page No.: 304

you call Suspend or Abort, you have no way of knowing the state the thread

leaves objects in when it suspends itself or when it is aborted.

Calling Abort throws a ThreadAbortException, but, to stress how bad an

idea relying on this rather strange exception is, we quote the documentation

for the .NET SDK:

When a call is made to Abort to destroy a thread, the common language

runtime throws a ThreadAbortException.

ThreadAbortException is a special exception that is not catchable. When

this exception is raised, the runtime executes all the finally blocks before

killing the thread. Since the thread can do an unbounded computation in the

finally blocks, you must call Join to guarantee that the thread has died.

The moral is: do not use Abort or Suspend. (If you do use Suspend, you

must use Resume to wake up the suspended thread.)

Hence:

The only safe method to use to end a thread is to poll a (synchronized)

condition variable or use the Interrupt method we just showed you.

14.10 Daemon (Background) Threads

Some threads that run in the background automatically stop when nothing

else in the program is running. The garbage collector, for instance, runs in

one of these background threads. You usually create a background thread if

you want to have a thread that listens for data, but you want this to happen

only as long as there is some code that can process the data running in

other threads.

The syntax is:

NameOfThread.IsBackground = True

Self Assessment Questions

6. The ____ code puts the current thread (Thread 1) to sleep and waits

until Thread 2 is over.

7. To get a reference to the thread that is running a piece of code we use

_____ method.

8. The _____ version of Sleep makes the current thread relinquish the rest

of its time slice.

Visual Basic Unit 14

Sikkim Manipal University Page No.: 305

14.11 Summary

This unit has covered the following topics:

Getting Started with Multithreading

Multithreading, in a way, is the next level of multitasking: instead of having

the operating system switch between different programs, multithreading

asks the operating system to switch between different parts of the same

program.

Multithreading is required if you are to solve certain programming problems

in a professional way. If your programs do not use multithreading when it is

called for, users will be seriously disappointed and will choose someone

else’s program.

Joining Threads

You sometimes need to stop a thread until another thread has finished

doing some work. For example, you may want thread 1 to wait until

computations in thread 2 are finished. You set this up by calling the Join

method on thread 2 while running thread 1.

Sleep Method

You may occasionally want to tell a thread to Sleep when it is not needed. A

sleeping thread is another example of a blocked thread. When you put a

thread to sleep, the other threads in the program obviously have more CPU

cycles to play with.

Ending or Interrupting a Thread

A thread ends when you get to the end of the method used to create it in the

ThreadStart delegate, but you may need a way to end the method (and thus

the thread) when certain events occur. It is occasionally useful to direct a

thread to check a condition variable to decide if it should end abnormally.

Suspending or Killing a Thread

Using either Suspend or Abort is likely to leave your programs in an

unstable state. Neither method gives a thread a reasonable chance to do

any cleanup. If you call Suspend or Abort, you have no way of knowing the

state the thread leaves objects in when it suspends itself or when it is

aborted.

Visual Basic Unit 14

Sikkim Manipal University Page No.: 306

Daemon (Background) Threads

You usually create a background thread if you want to have a thread that

listens for data, but you want this to happen only as long as there is some

code that can process the data running in other threads.

14.12 Terminal Questions

1. Explain various methods of creating threads in VB.Net.

2. Illustrate the process of making a thread to sleep.

3. Describe how to end or interrupt a thread.

14.13 Answers

Self Assessment Questions

1. multithreading

2. procedure

3. ThreadStart

4. Starvation

5. bThread.Priority=ThreadPriority.Highest

6. thread2.Join()

7. Thread.CurrentThread

8. Thread.Sleep(0)

Terminal Questions

1. Sub Main always runs in what is called the main thread. A .NET program

always has at least two threads running: the main thread and the

garbage collection thread. In line 1 we make a new instance of the test

class. (Refer Section 14.3)

2. You may occasionally want to tell a thread to Sleep when it is not

needed. A sleeping thread is another example of a blocked thread.

When you put a thread to sleep, the other threads in the program

obviously have more CPU cycles to play with. (Refer Section 14.7)

3. A thread ends when you get to the end of the method used to create it in

the ThreadStart delegate, but you may need a way to end the method

(and thus the thread) when certain events occur. It is occasionally useful

to direct a thread to check a condition variable to decide if it should end

abnormally.

(Refer Section 14.8)

Visual Basic Unit 14

Sikkim Manipal University Page No.: 307

Acknowledgements, References and Suggested Readings:

1. .NET Framework Essentials, O’Reilly Series by Thuan L. Thai, Hoang

Lam, 2nd Edition, February 2002.

2. Sceppa, David, 1972-Programming ADO, Microsoft Press

3. Programming VB.NET: A Guide for Experienced Programmers by GARY

CORNELL AND JONATHAN MORRISON, Edition 2002, Apress

Web Sites:

1. http://me.emu.edu.tr/cmpe106/vb/Lectures.htm

2. http://www.learnvisualstudio.net/120.html

3. http://www.vb6.us/

4. http://www.informit.com/

5. http://www.hitmill.com/programming/vb.htm

6. http://www.programmingtutorials.com/vbnet.aspx

7. http://www.worldofdotnet.net/

8. http://www.microsoft.com