Article Options
Premium Sponsor
Premium Sponsor

 »  Home  »  .NET Newbie  »  Simple Steps in VB.NET. Part 4 - Finishing Touches - The Ugly Duckling's Striking Back
Simple Steps in VB.NET. Part 4 - Finishing Touches - The Ugly Duckling's Striking Back
by George Poth | Published  07/08/2003 | .NET Newbie | Rating:
George Poth

I have been teaching English in Brazil since 1994 and always wanted to do more for learners than common textbooks can offer. This started with web sites that couldn't reach most students as computers and the Internet are not standard for most people in this country.

Computer tools to help Brazilian students learn a complex language like English are practically non-existent and so I sent some suggestions to software companies. Since Brazil is neither a target market for English textbooks nor for software of this kind, the rejection seemed natural.

As a result, I tried some free developer tools such as Borland's free C++ compiler, Free Pascal, and Envelope's Visual Basic. Envelope's Visual Basic, which is a Microsoft Visual Basic 1.0 clone and still available, suited my taste but I knew it was obsolete technology. In March 2003, I bought a copy of Microsoft Visual Basic .NET Standard and have been hopelessly contaminated with the programming virus ever since.

I mostly write programs for educational purposes. Having discovered the wonderful world of DirectX recently, I am diving into the most entertaining part of programming: games. One can connect teaching with pure entertainment, learning, and culture.

 

View all articles by George Poth...
Simple Steps in VB.NET. Part 4 - Finishing Touches - The Ugly Duckling's Striking Back

Article source code: ssteps4_addressbook.zip

Before our address book becomes a useful application, it has to undergo some fine-tuning. Fine-tuning is not merely changing the appearance. It is also adjusting, and hopefully improving, the functionality of the application.

Less is often more, and our program is no exception. The simpler our program is, the less it is prone to errors. The less it is prone to errors, the less you have to work on it. So let's think how we can simplify our program, or make things redundant.

One thing that really blows my fuse is the Load button. To me it seems as necessary as headaches. Why can't the program simply load the database at startup? There's good news: it can. Double-click the form and edit the code so that it looks like code1. You can also copy and paste the code from the Load button, as I did. The code continues with the tool tips, but I won't display them here because it would take up more space without any need.

code1:

Private Sub DataForm1_Load(ByVal sender As System.Object_
    ByVal e As System.EventArgsHandles MyBase.Load
    '[load the database]
    Try
        'Attempt to load the dataset.
        Me.LoadDataSet()
    Catch eLoad As System.Exception
        'Add your error handling code here.
        'Display error message, if any.
        System.Windows.Forms.MessageBox.Show(eLoad.Message)
    End Try
    Me.objMyAddresses_PositionChanged()
    '[/load the database]

Our Load button has become redundant, and should be treated as such. Double-click the Load button and delete code2:

code2:

Private Sub btnLoad_Click(ByVal sender As System.Object_
    ByVal e As System.EventArgsHandles btnLoad.Click
    Try
        'Attempt to load the dataset.
        Me.LoadDataSet()
    Catch eLoad As System.Exception
        'Add your error handling code here.
        'Display error message, if any.
        System.Windows.Forms.MessageBox.Show(eLoad.Message)
    End Try
    Me.objMyAddresses_PositionChanged()
End Sub

Now, we still have a useless Load button that we should delete. In design view, click it once and press the Delete button on your keyboard.

The Load button was, up to now, the only thing that I found little useful. You might have other ideas, and if you do, let me know.

The Tough Part of Programming

The way I introduced you to error handling in part 3 was meant to give you an idea about what it is and how it can work. We did that in a very light way, just for fun. Now, the truth is, error handling is anything but fun. Some programmers, however, think it is the most interesting and rewarding part of all. It is probably the toughest part, depending on how many and which errors you want/have to eliminate. Many programmers can tell you tales of eliminating one problem which produced another one, and with this I want to welcome you to the club. When you finish today, you will know what I mean. Yes, it can drive you crazy, and it can take much longer than making the program. Handling errors needs a lot of logical thinking and testing, although sometimes you might believe that there was nothing logical about the error. Okay, some good books on the subject would also come in handy. But still, it is almost impossible to produce a real-world program which is totally error-free.

Our program will not be totally error-free, I know that. What we are going to do today will merely give you a glimpse at what the upcoming programmer has to deal with. And our error correction is likely to produce new errors, I know that, too. So, why the heck do it at all? The common user doesn't know how your program works and doesn't know how to deal with errors. You can avoid some common problems, but the common user can't. They just complain when the error occurs. Not to talk about the experience it gives you, and the pride of being the winner of this challenge. How you eliminate the errors is simply your problem; it's the result that counts, not how you got there.

This is also a good point to write some words to more advanced programmers because I know that some of them read newbie-articles. I'm sure that when some more advanced programmers sees this article, they might think "Well, that can be done easier" or "Man, is that guy messy!" Guess what! I know that, but let's stay at our level. You advanced guys are very much invited to teach us better, so don't grumble and put pen to paper. After all, my idea is to do something for those who most need it: beginners. I'm a beginner myself without access to books on the topic since I'm living in Brazil. So what you see here is what I taught myself since March this year by trial and error, reading tutorials, forums, and asking fellow programmers. And before March this year, I didn't even have the slightest idea on programming. But I'm a determined person; the project I start will be finished - at all costs. So let's carry on.

From now on, not only do we have to think as common users, but we also have to think for them. It doesn't bring anything to think "But that won't happen." If the possibility is there, then it is going to happen in the long run.

When the program opens, what could a user do? The user could type in data without having clicked the Add button. He/she might then update and close the program without having actually saved the data. We can avoid this problem by making all textboxes read-only. You can do so by setting the read-only property of each textbox accordingly in the properties window. You can also do that faster when you double-click the form and place code3 between the load instructions and the tool tips. The tool tips are not shown here to save some space.

code3:

Private Sub DataForm1_Load(ByVal sender As System.Object_
    ByVal e As System.EventArgsHandles MyBase.Load

    '[load the database]
    Try
        'Attempt to load the dataset.
        Me.LoadDataSet()
    Catch eLoad As System.Exception
        'Add your error handling code here.
        'Display error message, if any.
        System.Windows.Forms.MessageBox.Show(eLoad.Message)
    End Try
    Me.objMyAddresses_PositionChanged()
    '[/load the database]

    '[make the textboxes read-only]
    editName.ReadOnly = True
    editSurname.ReadOnly = True
    editStreetAddress.ReadOnly = True
    editZipCode.ReadOnly = True
    editState.ReadOnly = True
    editPhoneNumber.ReadOnly = True
    editEmail.ReadOnly = True
    '[/make the textboxes read-only]

Go into design view and set the back color property for all textboxes to highlight text to have all textboxes appearing white, or live with the different color in read-only mode.

When you now run the program, the user can't type anymore. We could now hope that he/she clicks the Add button, but hoping is nothing for programmers. Insert a label above the textboxes and rename it to lblReadOnlyMsg. In the text property, type this sentence: "Read-only protection is ON", and resize the label accordingly. Run the program and check that everything is as intended.

This little error correction caused another problem. When the user clicks the Add button, he/she can't write because everything is read-only. We have to add code for the Add button, so that it cancels the read-only protection when a user clicks the button. The click must also change the text of our label to tell the user that the read-only protection is canceled. The first textbox in which a user is supposed to type should be focused so that the user doesn't have to click the textbox or use the tab-key. To do all this, edit the code for the Add button so that it looks like code4:

code4:

Private Sub btnAdd_Click(ByVal sender As System.Object_
    ByVal e As System.EventArgsHandles btnAdd.Click

    '[cancel the read-only protection]
    editName.ReadOnly = False
    editSurname.ReadOnly = False
    editStreetAddress.ReadOnly = False
    editZipCode.ReadOnly = False
    editState.ReadOnly = False
    editPhoneNumber.ReadOnly = False
    editEmail.ReadOnly = False
    '[/cancel the read-only protection]

    '[change the text of our label]
    lblReadOnlyMsg.Text = "Read-only protection is OFF."
    '[/change the text of our label]

    '[focus the textbox Name]
    editName.Focus()
    '[/focus the textbox Name]

    Try
        'Clear out the current edits
        Me.BindingContext(objMyAddresses"AddressBooktb").EndCurrentEdit()
        Me.BindingContext(objMyAddresses"AddressBooktb").AddNew()
    Catch eEndEdit As System.Exception
        System.Windows.Forms.MessageBox.Show(eEndEdit.Message)
    End Try
    Me.objMyAddresses_PositionChanged()
End Sub

A user could now type an address and save it. If the user forgets an item, we have to remind him/her. code5 does exactly this and more. You can edit the code now and read detailed explanations in the following. Just be careful that you type one instruction as one line. The instruction for a message box, for example, can easily count several lines on the page you're viewing, but one instruction should be one line. If you get into trouble with this, download the updated sample and have a look at that.

code5:

Private Sub btnUpdate_Click(ByVal sender As System.Object_
    ByVal e As System.EventArgsHandles btnUpdate.Click

    '[declare the variable for the person's first name] 
    Dim n As String
    n = editName.Text
    '[/declare the variable for the person's first name]

    '[declare the variable for the person's surname]
    Dim sn As String
    sn = editSurname.Text
    '[/declare the variable for the person's surname]

    '[set the conditions and make decisions]
    If Me.editName.Text = "" Then
        MessageBox.Show("Please enter a name.""My Address Book"_
            MessageBoxButtons.OKMessageBoxIcon.Information)
        editName.Focus()
        Exit Sub

    ElseIf editSurname.Text = "" Then
        MessageBox.Show("Please enter " & n & "'s surname."_
            "My Address Book"MessageBoxButtons.OK_
            MessageBoxIcon.Information)
        editSurname.Focus()
        Exit Sub

    ElseIf editStreetAddress.Text = "" Then
        MessageBox.Show_
            "Please enter the street address for " & n & " " & sn & "."_
            "My Address Book"MessageBoxButtons.OK_
            MessageBoxIcon.Information)
        editStreetAddress.Focus()
        Exit Sub

    ElseIf editZipCode.Text = "" Then
        MessageBox.Show_
            "Please enter the zip code for " & n & " " & sn & "."_
            "My Address Book"MessageBoxButtons.OK_
            MessageBoxIcon.Information)
        editZipCode.Focus()
        Exit Sub

    ElseIf editState.Text = "" Then
        MessageBox.Show_
            "Please enter the state for " & n & " " & sn & "."_
            "My Address Book"MessageBoxButtons.OK_
            MessageBoxIcon.Information)
        editState.Focus()
        Exit Sub

    ElseIf editPhoneNumber.Text = "" Then
        MessageBox.Show_
            "Please enter the phone number for " & n & " " & sn & "."_
            "My Address Book"MessageBoxButtons.OK_
            MessageBoxIcon.Information)
        editPhoneNumber.Focus()
        Exit Sub

    ElseIf editEmail.Text = "" Then
        MessageBox.Show_
            "Please enter the e-mail address for " & n & " " & sn & "."_
            "My Address Book"MessageBoxButtons.OK_
            MessageBoxIcon.Information)
        editEmail.Focus()
        Exit Sub
    End If
    '[/set the conditions and make decisions]

    Try
        'Attempt to update the datasource.
        Me.UpdateDataSet()
    Catch eUpdate As System.Exception
        'Add your error handling code here.
        'Display error message, if any.
        System.Windows.Forms.MessageBox.Show(eUpdate.Message)
    End Try
    Me.objMyAddresses_PositionChanged()

    '[display the person's full name in the messagebox]
    MessageBox.Show_
        n & " " & sn & " has been added to your database." & _
        Microsoft.VisualBasic.ControlChars.CrLf & "The read-only " _
        & "protection will now be reactivated.""My Address Book"_
        MessageBoxButtons.OKMessageBoxIcon.Information)
    '[/display the person's full name in the messagebox]

    '[reactivate the read-only mode]
    editName.ReadOnly = True
    editSurname.ReadOnly = True
    editStreetAddress.ReadOnly = True
    editZipCode.ReadOnly = True
    editState.ReadOnly = True
    editPhoneNumber.ReadOnly = True
    editEmail.ReadOnly = True
    '[/reactivate the read-only mode]

    '[Change the text for our label]
    lblReadOnlyMsg.Text = "Read-only protection is ON."
    '[/Change the text for our label]
End Sub

Understanding the Instructions

    '[declare the variable for the person's first name] 
    Dim n As String
    n = editName.Text
    '[/declare the variable for the person's first name]

    '[declare the variable for the person's surname]
    Dim sn As String
    sn = editSurname.Text
    '[/declare the variable for the person's surname]

The line Dim n As String instructs the program to take the text from "n". The second line n = editName.Text tells the program that "n" is the text from the textbox for the person's name. The same happens for the person's surname. Since it is a different location it must be declared as such. The 'n' or 'sn' could be replaced with anything you like provided you tell the program in the second line what it is. As an example, you could type the following:

    Dim BrittneySpears As String
    BrittneySpears = editName.Text

No, no, it won't bring the lady onto your screen; it merely tells the program that our Brittney Spears is nothing more and nothing less than the text in the textbox for the name. Are you disappointed now? Ah, yes, and it doesn't work with men either, my ladies, so let's go ahead.

    If Me.editName.Text = "" Then
        MessageBox.Show("Please enter a name.""My Address Book"_
            MessageBoxButtons.OKMessageBoxIcon.Information)
        editName.Focus()
        Exit Sub

The line If Me.editName.Text = "" Then is very close to spoken English and means: "If a user clicks the Update button and the textbox for the name is empty, then..."

        MessageBox.Show("Please enter a name.""My Address Book"_
            MessageBoxButtons.OKMessageBoxIcon.Information)

"...show him/her a message box with the text 'Please enter a name', the title is 'My Address Book', there is only an OK button and an information icon (question mark).

        editName.Focus()

"When the user clicks the OK button, focus the textbox for the name."

        Exit Sub

"Get out o' here!"

    ElseIf

It is practically the continuation of "if". In a later article, I will shed a light on this and other forms of setting conditions and making decisions.

        MessageBox.Show("Please enter " & n & "'s surname.")

"Show a message box with the text 'Please enter + the name of the person +'s surname." This could look like 'Please enter Peter's surname.'

        MessageBox.Show_
            "Please enter the street address for " & n & " " & sn & ".")

"Show a message box with the text 'Please enter the street address for + the person's name + the person's surname+.'"
This could look like 'Please enter the street address for Peter Pan.'

When you type the code, pay close attention to empty spaces. Otherwise you might find a message like "Please enterPeter's surname." or Please enter the street address forPeterPan." Neither would look very nice.

    End If

"Stop the job."

I'll skip the explanation for the code which updates our database since it is an automatically generated code. We should inform the user, with a message box, what kind of data has been added to the database. Otherwise the user might click the Update button 154,768 times to make sure it's updated. Let's take advantage of the situation and tell the user that we will reactivate the read-only mode to avoid trouble similar to what we talked about a while ago. And, of course, we have to change the text of our label because it should show that we are in read-only mode again.

    '[display the person's full name in the messagebox]
    MessageBox.Show_
        n & " " & sn & " has been added to your database." & _
        Microsoft.VisualBasic.ControlChars.CrLf & "The read-only " _
        & "protection will now be reactivated.""My Address Book"_
        MessageBoxButtons.OKMessageBoxIcon.Information)
    '[/display the person's full name in the messagebox]

    '[reactivate the read-only mode]
    editName.ReadOnly = True
    editSurname.ReadOnly = True
    editStreetAddress.ReadOnly = True
    editZipCode.ReadOnly = True
    editState.ReadOnly = True
    editPhoneNumber.ReadOnly = True
    editEmail.ReadOnly = True
    '[/reactivate the read-only mode]

    '[Change the text for our label]
    lblReadOnlyMsg.Text = "Read-only protection is ON."
    '[/Change the text for our label]
End Sub

The next two buttons (Cancel and Cancel All) are doing a fine job. The user should have a message box to confirm or cancel the action. Edit the codes for the Cancel button (code6) and the Cancel All button (code7).

code6:

Private Sub btnCancel_Click(ByVal sender As System.Object_
    ByVal e As System.EventArgsHandles btnCancel.Click
    If MessageBox.Show("Do you want to cancel the current entry?"_
        "My Address Book"MessageBoxButtons.YesNo_
        MessageBoxIcon.Question= DialogResult.Yes Then
        Me.BindingContext(objMyAddresses_
            "AddressBooktb").CancelCurrentEdit()
    Me.objMyAddresses_PositionChanged()
    End If
End Sub

code7:

Private Sub btnCancelAll_Click(ByVal sender As System.Object_
    ByVal e As System.EventArgsHandles btnCancelAll.Click
    If MessageBox.Show("Do you want to cancel all changes?"_
        "My Address Book"MessageBoxButtons.YesNo_
        MessageBoxIcon.Question= DialogResult.Yes Then
        Me.objMyAddresses.RejectChanges()
    End If
End Sub

The Delete button is also fine. However, we should tell the person what data is being deleted, and the user should have a chance to cancel the action, using code8.

code8:

Private Sub btnDelete_Click(ByVal sender As System.Object_
    ByVal e As System.EventArgsHandles btnDelete.Click
    '[declare the variable for the person's first name] 
    Dim n As String
    n = editName.Text
    '[/declare the variable for the person's first name]

    '[declare the variable for the person's surname]
    Dim sn As String
    sn = editSurname.Text
    '[/declare the variable for the person's surname]

    If MessageBox.Show_
        "This will delete the entry for " & n & " " & sn & "." & _
        Microsoft.VisualBasic.ControlChars.CrLf & "Do you want to " _
        & "continue?""My Address Book"MessageBoxButtons.YesNo_
        MessageBoxIcon.Question= DialogResult.Yes Then
        If (Me.BindingContext(objMyAddresses_
            "AddressBooktb").Count > 0Then
            Me.BindingContext(objMyAddresses_
                "AddressBooktb").RemoveAt(Me.BindingContext_
                objMyAddresses"AddressBooktb").Position)
            Me.objMyAddresses_PositionChanged()
        End If
    End If
End Sub

Let's come to our Close button. When a user clicks this button, he/she should be informed about what is going to happen. Still, some happy clickers don't care and just click. So we should save the data before we close the program, even if the data is not complete. Later on, the user might decide to complete or delete the entry. code9 does this.

code9:

Private Sub btnClose_Click(ByVal sender As System.Object_
    ByVal e As System.EventArgsHandles btnClose.Click
    If MessageBox.Show_
        "This will save any unsaved data and exit." & _
        Microsoft.VisualBasic.ControlChars.CrLf & "Do want to continue?"_
        "My Address Book"MessageBoxButtons.YesNo_
        MessageBoxIcon.Question= DialogResult.Yes Then
        Try
            Me.UpdateDataSet()
        Catch eUpdate As System.Exception
            System.Windows.Forms.MessageBox.Show(eUpdate.Message)
        End Try
        Me.objMyAddresses_PositionChanged()
        End
    End If
End Sub

Let's run the program and test it. Insert two or three addresses, save the thing and exit. Run it again and check that everything's there. Now try to edit existing data. Oops! We can't. How now, brown cow?

Take it easy. It's quite some work, but we'll get that straight. Insert a checkbox and change the text property to "Read-only protection for existing data is ON." Double-click the checkbox and edit code10. The code will cancel the read-only protection when checked, and it will reactivate the read-only protection when unchecked. It will also change the text of our label and the checkbox depending on whether the read-only protection is on or off.

code10:

Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object_
    ByVal e As System.EventArgsHandles CheckBox1.CheckedChanged

    '[cancel the read-only protection]
    If CheckBox1.Checked = True Then
        editName.ReadOnly = False
        editSurname.ReadOnly = False
        editStreetAddress.ReadOnly = False
        editZipCode.ReadOnly = False
        editState.ReadOnly = False
        editPhoneNumber.ReadOnly = False
        editEmail.ReadOnly = False
        '[/cancel the read-only protection]

        '[display the corresponding text]
        CheckBox1.Text = "Read-only protection for existing data is OFF."
        lblReadOnlyMsg.Text = "Read-only protection is OFF."
        '[/display the corresponding text]

        '[make the textboxes read-only]
    ElseIf CheckBox1.Checked = False Then
        editName.ReadOnly = True
        editSurname.ReadOnly = True
        editStreetAddress.ReadOnly = True
        editZipCode.ReadOnly = True
        editState.ReadOnly = True
        editPhoneNumber.ReadOnly = True
        editEmail.ReadOnly = True
        '[/make the textboxes read-only]

        '[display the corresponding text]
        CheckBox1.Text = "Read-only protection for existing data is ON."
        lblReadOnlyMsg.Text = "Read-only protection is ON."
        '[/display the corresponding text]
    End If
End Sub

Let's run the program again and check that we have what we intended. Edit an address and then update it. You will see that our checkbox doesn't agree with our label, so let's convince it. In design view, double click the update button and put code11 between the code for our label text and End Sub, then check the result.

code11:

    '[Change the text for our label]
    lblReadOnlyMsg.Text = "Read-only protection is ON."
    '[/Change the text for our label]

    '[change the text and state of our checkbox]
    CheckBox1.Checked = False
    CheckBox1.Text = "Read-only protection for existing data is ON."
    '[/change the text and state of our checkbox]
End Sub

Let's take the Add button and check it. When you click Add, our checkbox doesn't agree with our label again. So let's change that with code12 between the code to focus the textbox and the code that clears the textboxes.

code12:

    '[focus the textbox Name]
    editName.Focus()
    '[/focus the textbox Name]

    '[change the settings of our checkbox]
    CheckBox1.Checked = False
    CheckBox1.Text = "Read-only protection for existing data is OFF."
    '[/change the settings of our checkbox]
    Try
        'Clear out the current edits
        Me.BindingContext(objMyAddresses"AddressBooktb").EndCurrentEdit()
        Me.BindingContext(objMyAddresses"AddressBooktb").AddNew()
    Catch eEndEdit As System.Exception
        System.Windows.Forms.MessageBox.Show(eEndEdit.Message)
    End Try
    Me.objMyAddresses_PositionChanged()
End Sub

Right now, we have solved the problem with our Add button and with our Update button. Let's test the Cancel button to see if everything will be all right. When you add a new address and then cancel the entry, the last entry will be displayed and could accidentally be edited. That's why we have to make everything read-only after an entry was canceled. Double-click the Cancel button and edit code13. Then check the result.

code13:

Private Sub btnCancel_Click(ByVal sender As System.Object_
    ByVal e As System.EventArgsHandles btnCancel.Click
    If MessageBox.Show("Do you want to cancel the current entry?"_
        "My Address Book"MessageBoxButtons.YesNo_
        MessageBoxIcon.Question= DialogResult.Yes Then
        Me.BindingContext(objMyAddresses_
            "AddressBooktb").CancelCurrentEdit()
        Me.objMyAddresses_PositionChanged()
        '[make the textboxes read-only]
        editName.ReadOnly = True
        editSurname.ReadOnly = True
        editStreetAddress.ReadOnly = True
        editZipCode.ReadOnly = True
        editState.ReadOnly = True
        editPhoneNumber.ReadOnly = True
        editEmail.ReadOnly = True
        '[/make the textboxes read-only]
    End If
End Sub

We should do the same thing with the Cancel All button. If you have added more than one entry, this button will normally not display the last entry. However, I tested with clicking the Cancel button and Cancel All button alternatively, and I eventually came to an address. To play it save, put it there.

Now, such an address book is a fine thing. But why do we put the e-mail address there if we have to type it all over again to send an e-mail? There must be a way to send an e-mail right from the program. That's quite simple.

Add a button and rename it to btnmail or something like that. Change the text to something appropriate, like "E - mail this person". Double-click the button and edit the code so that it looks like code14. By the way, if you prefer, you can use a link label. This even works with a normal label.

Instead of an address, we're using the textbox where we should have an e-mail address. We just have to click the button, and an empty e-mail opens with the person's address.

code14:

Private Sub btnMail_Click(ByVal sender As System.Object_
    ByVal e As System.EventArgsHandles btnmail.Click

    '[e-mail the person displayed]
    System.Diagnostics.Process.Start("mailto:" & editEmail.Text)
    '[/e-mail the person displayed]

End Sub

Our project is almost coming to an end. I said almost because we still need an installer, which we will do in the next part.

Related devCity.NET articles:

How would you rate the quality of this article?
1 2 3 4 5
Poor Excellent
Tell us why you rated this way (optional):

Article Rating
The average rating is: No-one else has rated this article yet.

Article rating:2.06666666666668 out of 5
 165 people have rated this page
Article Score33171
Sponsored Links