Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Export (0) Print
Expand All
Around the World with Visual Basic
Asynchronous Method Execution Using Delegates
Building a Progress Bar that Doesn't Progress
Calling All Operators
Create a Graphical Editor Using RichTextBox and GDI+
Creating A Breadcrumb Control
Creating a Five-Star Rating Control
Creating and Managing Secondary Threads
Data Binding Radio Buttons to a List
Deploying Assemblies
Designing With Custom Attributes
Digital Grandma
Doing Async the Easy Way
Extracting Data from .NET Assemblies
Implementing Callbacks with a Multicast Delegate
Naming and Building Assemblies in Visual Basic .NET
Programming Events of the Framework Class Libraries
Programming I/O with Streams in Visual Basic .NET
Reflection in Visual Basic .NET
Remembering User Information in Visual Basic .NET
Advanced Basics: Revisiting Operator Overloading
Scaling Up: The Very Busy Background Compiler
Synchronizing Multiple Windows Forms
Thread Synchronization
Updating the UI from a Secondary Thread
Using Inheritance in the .NET World
Using the ReaderWriterLock Class
Visual Basic: Simplify Common Tasks by Customizing the My Namespace
What's My IP Address?
Windows Forms Controls: Z-order and Copying Collections
Expand Minimize

Visual Basic .NET 2003: A .NET Framework Tour

Visual Studio .NET 2003
 

Bill Sempf

July 2005

Summary: Bill Sempf takes you on a guided tour of the .NET Framework via Visual Basic .NET 2003 and shows how to do numerous common tasks. (13 printed pages)

Contents

Introduction
How do I work with a string?
Where can I find the user's name and secure my code?
How can I get to a database?
What do I do to keep an action from blocking the user interface?
Where do I store INI file data?
What debugging tools are available?
How do I send e-mail?
How do I get a Web page?
What allows me to draw on the screen?
Why can't I use the DataGrid/ComboBox? (The Windows versus Web conundrum)
Conclusion

Introduction

Visual Basic is not dead.

I say this because the concepts of Visual Basic are still very much alive and kicking in Visual Basic .NET. When conceived, the idea was to make the BASIC language conceptually current by making it function within a visual development environment. Thus, the two key pieces were the BASIC language, and the visual environment.

You will find both of these in Visual Basic .NET. Please don't let anyone tell you otherwise.

You may be asking what has changed to generate discussions over Visual Basic .NET versus Visual Basic 6. The answer is simple—the library has changed. For five years, Visual Basic programmers had the Visual Basic Runtime, a library of Win32 functions. That has been replaced with the .NET Framework—a similar library with a different feel.

The biggest difference is a significant improvement: the libraries have been reorganized in a way that makes a lot more sense. However, the problem is that you can't find something right away. Finding simple things, like file copying and Web access, require you to spend time with the documentation.

I feel your pain. I learned Visual Basic .NET in two weeks in 2000, while writing for the Wrox book, Professional Visual Basic .NET. "How different can it be?" I thought. Well, as many of you know, the answer is, "Quite different," largely because of the different library.

What I would like to do is take a few minutes of your time and go over a few common tasks that you might do in your applications, and give you pointers to the Visual Basic .NET code to get you there. Feel free to click to the topic that interests you – this is as much a reference article as it is a reading article!

How do I work with a string?

A String variable is a type in Visual Basic that can be used to make a space to store text, digits, and punctuation. The .NET Framework supports strings, or course, but it might be a little different than you are used to. You still declare a variable as a string the same way:

Dim myString as String

There are a few differences in .NET. Because the .NET Framework manages strings, they are objects—both the type itself (the word String itself) and the variable that is defined as a string. Because of this, strings know what can and can't be done to them.

Give yourself a cheap thrill. In Visual Studio (any version), open a new Windows Forms project, which is similar to the Visual Basic project you have always known. Double-click on the default form to open Code View. Type the line of code above into the Form1_Load event and press Enter. On the next line, type myString and press the period key.

Figure 1. Creating a Windows Forms project in Visual Studio .NET

All of the items that appear in Visual Studio .NET in Figure 1 replace the myriad of functions that we had to memorize in previous versions in order to manipulate strings. To give yourself even a cheaper thrill, set up a static string, like myString = "this string" into Code View and press the period key. All the same items show up, because static strings are objects just as defined string variables are.

There are a bunch of great things now built into a string. These methods replace the functions like Trim and InStr.

  • To trim characters, like LTrim and RTrim, use the Trim function.
  • To get characters out of a string, like the Left, Right and Mid functions, use Substring.
  • To search for the instance of a string within the selected string like InStr, use IndexOf or IndexOfAny.
  • UCase and LCase have been replaced by the ToLower and ToUpper functions.

Beyond the old functionality provided by the Visual Basic 6 string functions, there is a bit more cool functionality provided by the String class. Yes, that's right—I said Class. The String has what are called Shared Methods that are available without declaring a new string at all. Type String and hit the period key to see what I mean.

By far the most useful of the String functions is the Format function, which allows you to concatenate together variables in exactly the format you want. Take a gander at this little piece of code to see what I mean.

Public Function MadLib() As String
    Dim verb As String = "make"
    Dim noun As String = "function"
    Dim adjective As String = "cool"

    Dim result As String
    result = String.Format("I am trying to {0} this {1} as {2} as possible!", verb, noun, adjective)
    Return result

End Function

Strings aren't the only types that are objects. Integers, Dates—all types are objects in the .NET Framework. Take the time to look through the functions available; they are different based on the needs of the type. Dates have an AddMinute function, and Integers have a MinValue and MaxValue property, for instance. There are other Shared methods and properties available to use as well.

Where can I find the user's name and secure my code?

Security in the .NET Framework is pretty cool.

Remember that Visual Basic 6 was developed during an era when computer hacking was for "uber geeks" only. While security had its place, only the rare component or application had to have truly strong security.

Today, when just a list of names and addresses must be tightly secured, the average program has to be much more stable in terms of security. The .NET Framework can really help you out there.

There is a whole set of tools in the System.Security namespace to help, and one of them in the Principal.WindowsIdentity class. This class maintains a typed object that can show you the name and authentication type of the current user, as well as a set of yes/no questions, such as whether the user is authenticated or anonymous (useful for Web applications), a system account, or a guest.

In Visual Studio, open a new Visual Basic .NET Windows forms project to try this out. Drag a Label control onto the form, and then double-click the form to launch the code view. Add the following code to the Form1_Load event handler.

Public Class Form1
    Inherits System.Windows.Forms.Form

    Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
        Dim myIdentity As System.Security.Principal.WindowsIdentity
        myIdentity = System.Security.Principal.WindowsIdentity.GetCurrent()
        Label1.Text = myIdentity.Name
    End Sub
    
End Class

Run the application, and your username will appear in the label. Pretty cool, huh? Try it with some of the other properties of the myIdentity object you just created. While you are at it, note that you can use the Imports keyword to shorten the reference to the WindowsIdentity type. Imports tells Visual Basic that you will be using the named namespaces specifically in this file. When you mention a class, like Principal, the compiler will assume that you are speaking of the Principal class in System.Security.

Imports System.Security
Imports System.Security.Principal.WindowsIdentity
Public Class Form1

    Inherits System.Windows.Forms.Form

    Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
        Dim myIdentity As Principal.WindowsIdentity
        myIdentity = GetCurrent()
        Label1.Text = myIdentity.Name
    End Sub
    
End Class

Securing your code is another matter, of course. Generally speaking, I would advise making security the most important single requirement of any system you write. It is one of those things that bring you nothing if it is right, but it is a 100% disaster if it is wrong—it is the Zero Sum game of programming. Pay attention to security.

To get more information on security and securing your code, jump to your favorite bookstore online and get Securing Your Code, Volume 2 as soon as you can. It is a great read and will help you in this department quite a lot.

How can I get to a database?

Data access is one of the more significant changes in the .NET Framework, compared to the Windows DNA model in Visual Basic 6. As Microsoft developers, we are used to a litany of acronyms for data access methodology—DAO, RDO, RDS, ADO, etc. The change from ADO to ADO.NET seems almost insignificant.

Nothing could be further from the case. In moving from ADO to ADO.NET, Microsoft has changed the very cornerstone of data access in the Microsoft Mythos by making it disconnected. When you page through a recordset in Visual Basic 6, you are looking at live data. When you look at a DataSet in ADO.NET, you are looking at a copy.

For many of us, this hardly matters. In fact, I had spent quite a long time trying to make recordsets work in ASP pages on the Web, an intrinsically disconnected medium. For those of us working with the Web, this change is actually quite beneficial. For all of us, though, the change is significant, and can be confusing.

The secret codes for data access in the .NET Framework are kept in the System.Data class. As a Visual Basic developer, you will spend the majority of time in the System.Data.SqlClient and System.Data.Odbc namespaces, with one notable exception. The DataSet—Microsoft's replacement for the RecordSet—is in the System.Data class, and is database-independent. If you want to put data in a DataSet, you have to use a database-specific DataConnection and DataAdapter. The connection connects your code to the database, and the adapter connects your code to the DataSet. Let's look at an example.

'Set up the keys to data access, the DataSet, Connection and Adapter.
Dim myDataSet As System.Data.DataSet
Dim myConnection As System.Data.SqlClient.SqlConnection
Dim myAdapter As System.Data.SqlClient.SqlDataAdapter
'The connection string should point to your local SQL Server
Dim connString As String = "Data Source=Gryphon;" & _
          "Initial Catalog=Pubs;" & _
          "Integrated Security=SSPI"
'Open the connection
myConnection = New SqlConnection(connString)
'The Adapter has the command in it.
myAdapter = New SqlDataAdapter("select * from Titles", myConnection)
'Fill the dataset with data using the adapter.
myDataSet = New DataSet
myAdapter.Fill(myDataSet, "Titles")
'Loop through the rows and write to the Output window.
Dim row As System.Data.DataRow
For Each row In myDataSet.Tables(0).Rows
    Debug.Write(row(1).ToString)
Next

If you think it seems that the DataSet looks a lot like a RecordSet, the SqlConnection is a Connection and the SqlDataAdapter is a Commend, you wouldn't be far off. Don't be fooled by appearances, the DataSet is very, very different from the RecordSet in several ways. The usage is similar enough that you can think of it that way, but don't confuse the functions.

  • DataSets are disconnected. You are looking at a copy of the data. To see the latest data, you must re-fill the dataset. To update the data, you must define and use the Update method.
  • DataSets are hierarchal. Under the covers, they are XML files. They are designed to hold many related tables, thus the reference to myDataSet.Tables(0) in the example above.
  • DataSets are an in memory representation of data, and as such take up a fair amount of resources. If you want just the equivalent of a forward-only, read-only recordset, look into a DataReader. They are great for filling drop-down lists.

Speaking of XML, I would be remiss in not mentioning the System.XML namespace. It works well with DataSets because you can read a DataSet directly in from an XML file, and vice versa. If you have a large amount of cross-platform type data work, look into using XML. You can easily get an XmlNode from an XML Document using XPath, and then use the ReadXml method of a DataSet. The ReadXml method reads the data from the XML file and fills the DataSet.

What do I do to keep an action from blocking the user interface?

Threading is one of those things that you don't want to think about that often in a simple application, but you always have that one user that doesn't want to wait while an image is generating in the background. The System.Threading namespace allows you to quickly and easily spawn a separate process to generate that image or run that complex query or search through that directory, and still allow the user to do other things inside the same application.

Threading splits your application into two or more logical 'apartments', from the Framework's perspective, and tells the processor to treat the separate actions like separate applications for time sharing. It is an incredibly complex concept that I don't even want to think about. The .NET Framework makes Managed Threading, as it is called, simple so that we don't have to.

Say for instance that you do have a method that generates a complex image, called MakeComplexImage. First, in your application, import System.Threading. Then to send that method to a new thread, and prevent blocking the user interface, the code is this simple:

Dim myThread As New Thread(AddressOf MakeComplexImage)
myThread.Start()

Believe it or not, that's it. When the MakeComplexImage method completes, you will have the output you asked for and there won't be any interruption to the user experience. If you need to pause that execution for whatever reason, check into myThread.Sleep.

There are best practices when it comes to threading. It is easy to write a bad application using System.Threading. Read the documentation carefully, and follow the advice within. Remember that you are giving a lot of extra work to the operating system when you deal with threading. It is as significant as working with the Registry. Take your time, and do it right.

Where do I store INI file data?

While you can use old-fashioned INI files with .NET, and use the System.IO namespace to parse the lists within, I recommend that you drop that model in favor of the new Config file model that Microsoft is recommending. Config files are XML-based files that are in every project anyway, so learning how to use them to your benefit is just a good idea in general.

There are two basic kinds of config files: Windows and Web. Web config files are called Web.Config and are kept at the base of the application root. IIS knows not to send them to the user even if asked for, so they are secure. Windows Configs are slightly different. They are called App.Config, but are renamed on compile to the <projectname>.config and stored in the Bin directory.

Config files have a basic root element called <configuration> and from there are very flexible. In the Web world, there are a number of elements that are in the default file. Windows Config files come without anything in them.

To add to the Config file, you can use the appSettings tag, like I did in this recent XML editor that I wrote:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <appSettings>
      <add key="XmlPath" value="C:\XML\theCurrentFile.xml"/>
      <add key="XmlBase" value="C:\XML\"/>
   </appSettings>
</configuration>

To get to this information from the code, use the System.Configuration namespace. The ConfugurationSettings class has a Shared collection called AppSettings that knows about all key/value pairs in the appSettings node. I often set up a MustInherit base class for all of the classes that need to know the data in the Config file.

Public MustInherit Class Base
    Protected Friend XmlPath As _
String = ConfigurationSettings.AppSettings("XmlPath")
End Class

What debugging tools are available?

There is more to debugging in .NET than the F5 key and breakpoints. The Debug class in the System.Diagnostics namespace is very powerful. When you use it, you will be communicating through the Output window mostly, which only shows up when you are in Debug mode—proving that F5 is still an intrinsic part of this process.

Let me just go over a bunch of the methods of the very useful Debug class. Remember, these statements will only run when you are in the Debug mode, so they are fairly safe to leave lying around in most software.

  • Write—The basic method. Writes a value to the Output window
  • WriteIf—Only writes values if the Boolean you specify is false
  • Assert—Dumps the call stack if the condition you specify is false
  • Fail—Throws a specified error message. Very helpful in testing exceptions.
  • Listeners—A collection of the objects listening to the Debug output.

You'll notice that I often use Debug.Write when outputting the values of sample code. It is very useful in that regard, much like a Response.Write in the bad old ASP days, except the user can't see them.

Speaking of ASP.NET, I would be remiss in not mentioning the Trace functionality built in there. To enable the best trace you have ever seen on a Web page, just add the Trace=True attribute and value pair to the Page directive. You don't even have to recompile, so you can do it to a production system if you have to.

<%@ Page Language="VB" Trace="True" %>

This will dump a ton of useful information right to the bottom of your Web page, like form and request variables, the order and execution time of each part of the ASP.NET lifecycle, and any custom trace variables you have set.

How do I send e-mail?

In order to send an e-mail message in Windows DNA, you needed to resort to trickery. I remember using SQL Server to do it, writing little scripts that hacked my mail server, even setting up Linux boxes just basically to handle e-mail.

Those days are over in .NET. In the 1.0 and 1.1 versions of the Framework, mail is handled by the System.Web.Mail namespace. Admittedly, this doesn't make a lot of sense, since Mail has almost nothing to do with the Web, and in 2.0 the Mail namespaces are moving to the System.Net namespace.

A good strategy for setting up any project that might have a need to send email is to add an e-mail helper function. With this Send Mail method, you can expand your communication needs as far as the project requirements go.

Public Function SendMail(ByVal recipient As String, ByVal sender As String, _
ByVal subject As String, ByVal body As String) As Boolean
    Dim Result As Boolean
    Dim CurrentMessage As New System.Web.Mail.MailMessage
    Try
   CurrentMessage.To = recipient
   CurrentMessage.From = sender
   CurrentMessage.Subject = subject
   CurrentMessage.Body = body
   SmtpMail.SmtpServer = MailServer
   SmtpMail.Send(CurrentMessage)
   Result = True
    Catch ex As Exception
   Result = False
    End Try
    Return Result
End Function

There are two keys to this function:

  • The MailMessage object, which has a collection of properties that must be set to be viable, and
  • The SmtpMail object, which has a Shared Send method that accepts the MailMessage object that gets constructed.

Generally, these properties for the MailMessage include:

  • Attachments—A collection of attachments that are sent with the e-mail
  • Bcc—The Blind Carbon Copy list, semicolon delimited
  • Body—Required. The content of the message
  • BodyEncoding—Sets if the message is ASCII or Unicode
  • BodyFormat—Sets of the message is HTML or text
  • Cc—The Carbon Copy list, semicolon delimited
  • From—Required. The e-mail address sending the message
  • Headers—Has a collection of custom SMTP headers, like X-Sender and such
  • Priority—Used to set High Normal or Low priority
  • Subject—The subject of the message
  • To—Required. A semicolon delimited list of recipients of the message

You can set the mail server address using the SmtpServer property. Keep in mind that mail servers are persnickety, and the From address often has to be a current account on that server. Sometimes, you even need to authenticate on the server in order to send, which is tricky and requires special configuration on the server side.

How do I get a Web page?

The Internet Explorer DLLs were the common way to get to the Web in Visual Basic 6. With a library called ".NET", you would guess that there would be a better way to get a Web page in the Framework, and you would be right. The class you need is in the System.Net namespace, and it is called WebClient. (Remember, this means you need the line 'Imports System.Net' at the top of your code behind.)

The WebClient class is exactly what it sounds like. It provides read and write capability to a URL, passed in on the method signatures. Additionally, you can add in QueryString and Form variables (cin for you old C hackers) to URLs so that you can get to output provided only by filling out a form. In short, you can access the Web in just a few lines of code, and get a byte array back with the whole content of a page.

The best way to explain is with an example. Put this in the OnClick event handler of a Button and set a breakpoint on the last line.

'Start with a new WebClient object
Dim myWebClient As New WebClient
'Set up the URL
Dim myURL As String = "http://www.pointweb.net/"
'The method will return a ByteArray, so we need that
Dim myHtml() As Byte
'This will hold the final string
Dim myHtmlString As String

'Get the Byte Array to start.  
'This is where the network activity will happen under the covers.
myHtml = myWebClient.DownloadData(myURL)
'Convert the Byte Array to a string
myHtmlString = Encoding.ASCII.GetString(myHtml)
'That's it!  Show it in the Debug window
Debug.Write(myHtmlString)

Really, there is only one important line of code here, the DownloadData method. It accepts the URL and returns the byte array. We use the System.Text.Encoding.ASCII object to convert the array to a string the 'easy way'.

Showing a Web page on the screen in a Windows Forms application is a little trickier. Actually, unless you buy a third-party component, you are stuck with the Internet Explorer ActiveX control like the bad old days, though I admit it works pretty well in the .NET world.

To get that control, right-click on the toolbox and select Add/Remove Items. Click on COM Components and find the Microsoft Web Browser (shdocvw.dll). Add this to the toolbox, and treat it like any other control. (There is a Web browser control in the .NET Framework 2.0, so this will get better.)

What allows me to draw on the screen?

Drawing in the .NET Framework is very much more sophisticated than drawing in Visual Basic 6. The System.Drawing namespace has all of the tools that you need to get started. As in most platforms, graphics programming with the .NET Framework consists of drawing polygons, filling them with color, and labeling them with text—all on a canvas of some sort. Unsurprisingly, this leaves us with four objects that you will find are the core code you will write: Graphics, Pens, Brushes,and Text.

  • Graphics—Generally speaking, the Graphics class creates an object that is your palette. It is the canvas.
  • Pens—These are used to draw lines as the outline of a polygon, or just as old-fashioned straight lines.
  • Brushes—To fill the polygon that you drew with your pen, or your Graphics object, you use a Brush.
  • Text—As one would expect, Text is all about fonts and placement of letters.

Don't get carried away with the System.Drawing namespace. Almost everything you will need to do in a Windows or Web form is handled through controls. One huge exception is games, where you will rarely find a BFG control that you can slip into Level 2. Another example is handling images on a Web site.

Images on a Web site are usually implemented through an Image tag, but sometimes you need to render them on the fly. A few examples might be a site where you have to generate thumbnails on the fly (like a real estate site) or render text from a database query on top of an image (like a test result, for instance). This strategy requires a slightly different object from the Graphics object, the bitmap.

One great example of this is a site that I worked on where images of seeds are scanned and then the results of the scan are printed on the image as they are requested. To do this, I used the Bitmap class to get a copy of the original image, and then turned it into a Graphics object. I then used a Font object and a Brush object to paint the text on the Graphics object. Finally I used the Save method of the original Bitmap object to make a jpeg that could be viewed from the site, and return the image name as the result of the function call. The code looked something like this:

Dim myHttpContext As System.Web.HttpContext.Current
Dim myResults As String
Dim myBitmap As New Bitmap("c:\images\labimage.jpg")
Dim myPalette As Graphics = Graphics.FromImage(myBitmap)
Dim myFont As New Font("Arial", 32)
Dim myBrush As New SolidBrush(Color.White)

myPalette.DrawString("results: " + myResults, myFont, myBrush, 10, 10)
myHttpContext.Response.ContentType = "image/gif"
myBitmap.Save(myHttpContext.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
myHttpContext.Response.Flush()

myBitmap.Dispose()
myPalette.Dispose()
myFont.Dispose()
myBrish.Dispose

All of this went in the Page_Load event handler of an ASPX page that was used as the SRC attribute of an image, and the page accepted the test id number. It worked very well, and is a great example of how to quickly and easily use System.Graphics to work with Web images. There are other ways, too, including some slick Web service tricks. Do a little research on your options before you start coding, and you'll find some great tricks out there.

Why can't I use the DataGrid/ComboBox? (The Windows versus Web conundrum)

Since Visual Studio 1.0 in 1997, Microsoft has been trying to blur the boundaries between development for Windows and the Web. With Visual Studio .NET, Microsoft has almost succeeded. Development for Windows—a familiar model—has been overlaid onto the model for the Web such that many of the familiar actions are in both places, but always keep in mind that the two models are very different.

As far as the Framework is concerned, the difference is defined by the namespaces—System.Windows.Forms for Windows Forms implementations, and System.Web.UI for Web Forms. Each of these namespaces has a distinct collection of controls that might be named similarly, but that have very different functionality at times.

The DataGrid is a very good example. In ASP.NET, using the System.Web.UI.WebControls.DataGrid, you can sort, or maintain view and edit modes, or tons of other things that we have all been doing in HTML for years. Finally, there is a control that supports the stuff we have been doing by hand.

Then there is Windows Forms. When we change to the System.Windows.Forms.DataGrid, there is suddenly less functionality. Where are the AutoFormat controls? Why can't I edit the column templates?

The answer is in the significant differences between Windows and Web. Web controls render HTML, which is a standard, and we can manipulate that end code as needed. Windows controls render binary Windows proprietary stuff that is harder to change at the developer level.

Another similar example is that of the ComboBox. Many people used to Windows Forms are always looking for the perfect ComboBox for the Web. There isn't one in the standard Web control library, because the Web is architected differently. In HTML parlance, the ComboBox is a combination between a textbox and a Select tag. There isn't any such combination in HTML, so we have to fake it by hiding one and showing another, or resorting to complex and fragile JavaScript and DHTML. It's a constraint of the platform, just like the DataGrid.

Conclusion

This task-based introduction to the .NET Framework was not designed to be a comprehensive look at what can be done. It is just a list of the most common things I have been asked over the years since the launch of .NET, and the answers I usually give. I hope that the answers you seek are here. If not, feel free to shoot me an e-mail, or post to my blog.

I think you will agree, though, that after reading this you will find Visual Basic to be alive and kicking—albeit with a more powerful engine. The language is practically the same, it's just the libraries that are different. Toss your old Visual Basic 6 components, and try and embrace the new functionality in the System.Data, System.IO and System.Net namespaces. Dig into the controls in System.Web and System.Windows. In short, play around. There is a lot to learn in the .NET Framework, and version 2.0 is right around the corner.

Show:
© 2015 Microsoft