
Beginning Visual Basic 2005 Express Edition - From Novice To Professional (2006)
.pdf200 |
C H A P T E R 8 ■ B U I L D I N G W I N D O W S A P P L I C A T I O N S |
As you can see, you can take a look at the SelectionLength property of a text box to see whether the user has selected anything inside the box. If the user hasn’t, in this code you display a message box pointing out the error to the user.
Next, you need to do something with any information entered into the text box. What you are going to display is the text itself, the selected text, and information about how long the selection is and where it starts. That’s a lot of data to display, so obviously you are going to have to split it over a number of lines in the message box. In addition, it makes sense to build the message string to display over a number of lines.
Although you could simply create a string variable and keep adding to it, that’s not really a good habit to get into. Instead, you’ll use a StringBuilder object (for a detailed explanation of just why you need to be careful of how you work with strings, see the “Never Keep Adding to a String” sidebar following this exercise). Go ahead and add an Else block to the code and kick it off by declaring a StringBuilder object:
Private Sub showButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles showButton.Click
If inputBox.SelectionLength = 0 Then
MessageBox.Show("Select some text in the textbox")
Else
Dim builder As New System.Text.StringBuilder()
End If
End Sub
With that done, you can start to add stuff into the string. Personally, I really like the way Console.WriteLine() works, where you can put parameters into the string itself with braces ( {1}, {2}, and so on) and then dump a bunch of parameters at the end of the call to replace those in the string. The same thing can be achieved with the String.Format() command. Take a look:
Else
Dim builder As New System.Text.StringBuilder() builder.Append( _
String.Format("The textbox contains {0}" + vbCrLf, _ inputBox.Text))
End If
Here you are adding some text onto your string that says, “The input box contains,” followed by the text inside the input box, followed by a new line symbol (vbCrLf) to start a new line of text in the message.

C H A P T E R 8 ■ B U I L D I N G W I N D O W S A P P L I C A T I O N S |
201 |
NEVER KEEP ADDING TO A STRING
Strings are immutable, which is really a posh word meaning they can’t be changed, ever. But hang on a minute, we’ve seen code that changes a string variable from one value to another, and we’ve seen code that extends a string by adding new text onto the end of it. If strings are immutable, how does that work?
Well, that’s the problem. Whenever you try to change something in a string variable, either by reassigning text to the string, or by adding stuff to it, what actually happens is that the string that was in the variable gets thrown away. Behind the scenes, the .NET common language runtime creates a new chunk of memory to hold the new string. The new string gets dumped into the new block of memory, and the variable is updated to point to this new memory location. The net result, of course, is that this is slow, very slow. You’d hardly notice how slow if you did it now and then without thinking. If you did it inside a big loop, though, you’d soon start to notice the application slowing down.
If you want to do things to strings (add to them, change them, and so on), use a StringBuilder—as the name suggests, this is an object designed to build strings efficiently.
Add the rest of the code so that the message is built in full and displayed:
Else
Dim builder As New System.Text.StringBuilder()
builder.Append( _
String.Format("The textbox contains {0}" + vbCrLf, _ inputBox.Text))
builder.Append( _
String.Format("You selected {0} characters starting at {1}" + _ vbCrLf, _
inputBox.SelectionLength, inputBox.SelectionStart))
builder.Append( _
String.Format("The selected text is {0}", _ inputBox.SelectedText))
MessageBox.Show(builder.ToString())
End If

202 |
C H A P T E R 8 ■ B U I L D I N G W I N D O W S A P P L I C A T I O N S |
This should all be straightforward enough. The second line shows the number of characters that have been selected in the string, by interrogating the inputBox.SelectionLength and inputBox.SelectionStart properties. The third line displays the actual selected text by interrogating inputBox.SelectedText.
Go ahead and run the program. Enter some text, select a part of it, and then click the Show button and you’ll see a message box appear much like mine in Figure 8-8.
Figure 8-8. Enter some text, select a part of it, and then click the button, and your application will look much like this screen shot.
Just as you coded it, the message that appears tells you a bunch of stuff about the text in the text box, and what was selected inside of it.
So far, you’ve looked at simple text boxes with a single line of data. However, the text box is more than capable of holding a mass of text spread across multiple lines of data. Think of it as a very simple text editor. Let’s take a look.
Try It Out: Working with Multiline Text Boxes
Start up a new Windows project again and drop a text box onto the form.
If you try to resize the text box so that it takes up the majority of the form, you’ll find that you can’t. To fix this, take a look at the text box’s properties and change the Multiline property to True.
Now resize the text box so that it takes up the majority of the form.
Rename the text box multiLineBox and then drop a button underneath it called showLinesButton. Set the caption on the button to Show Lines. Your form should now look like the one in Figure 8-9.

C H A P T E R 8 ■ B U I L D I N G W I N D O W S A P P L I C A T I O N S |
203 |
Figure 8-9. Arrange the text box and button on the form, like this.
You can work with a multiline text box just as you would with a standard text box. In addition, there is a Lines property that is a string array. You can use this property to get at the physical lines of text inside the text box. Let’s add some code to the button’s Click event to take a look.
Double-click the Show Lines button to open the editor at the button’s Click event code, and add the following highlighted lines:
Private Sub showLinesButton_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles showLinesButton.Click
Dim lineInfo As New System.Text.StringBuilder() lineInfo.Append(String.Format("There are {0} lines..." + vbCrLf, _
multiLineBox.Lines.Length))
For Each line As String In multiLineBox.Lines lineInfo.Append(line + vbCrLf)
Next
MessageBox.Show(lineInfo.ToString())
End Sub

204 |
C H A P T E R 8 ■ B U I L D I N G W I N D O W S A P P L I C A T I O N S |
Just as in the earlier example, the code first creates a StringBuilder object, because that’s the most efficient way to build a string on the fly. Text is then added to StringBuilder to show the number of lines in the text box. Because the Lines property of the text box is just an array, you can find out the number of lines in the text box with a call to multiLineBox.Lines.Length.
The loop simply adds each line from the Lines array to StringBuilder. The net result, of course, is that StringBuilder contains a long string that displays a summary of the number of lines in the text box, and then each line itself. This is displayed in a message box.
Run the application now, enter a few lines of text, and click the Show Lines button. You’ll see a result like that in Figure 8-10.
Figure 8-10. With a multiline text box, you can work with each line of text through the text box’s Lines property.

C H A P T E R 8 ■ B U I L D I N G W I N D O W S A P P L I C A T I O N S |
205 |
You’ll frequently need to check that the data entered by your users into a text box is valid. That’s just what the Validated and Validating events of a text box are for. The Validating event fires after the user moves the focus away from the text box. So, selecting a different control on a form, or even closing the form, will cause the Validating event to fire. The Validated event occurs after the Validating event completes without being cancelled. Let’s take a look.
Try It Out: Validating Text Box Contents
Start up another Windows application project in Visual Basic 2005 Express and lay out some controls on the form so that it looks like Figure 8-11.
Figure 8-11. Lay out controls on your form so that it looks like this.
What you want to do in this application is just check that the user enters a number (not text) between 1 and 10. In other languages, one approach to doing this would be to code up the OK button so that when it’s clicked, code runs that can check what was entered into the text box. With .NET, you don’t need to do that. Instead, you’ll just close the form down when the button is clicked.
Set the name of the button to okButton and then double-click the button to drop into the code editor for its Click event. Just add a single line of code to close the form down, as here:
Private Sub okButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles okButton.Click
Me.Close()
End Sub
Let’s set up the validation on the text box now. Set the Name property of the text box to numberBox, and then use the Properties window to find the Validating event. You can see it in Figure 8-12.

206 |
C H A P T E R 8 ■ B U I L D I N G W I N D O W S A P P L I C A T I O N S |
Figure 8-12. The Validating and Validated events let us check that the data entered into a text box is as we expect it to be.
Double-click the Validating event in the list to drop into the code editor for the event. Add the highlighted code from the following source listing:
Private Sub numberBox_Validating(ByVal sender As System.Object, _
ByVal e As System.ComponentModel.CancelEventArgs) _
Handles numberBox.Validating
Dim numberEntered As Integer
If Integer.TryParse(numberBox.Text, numberEntered) Then If numberEntered < 1 Or numberEntered > 10 Then
e.Cancel = True
MessageBox.Show("You have to enter a number from 1 to 10") End If
Else
e.Cancel = True
MessageBox.Show("You must enter an integer") End If
End Sub
Walking through the code line by line, you can see that the first thing that happens is whatever is inside the text box is parsed into an integer. You could have used the Parse() method to do this, but then you’d need to write an exception handler; Integer.Parse() will throw an exception if the data you hand it is not a number. TryParse(), on the other hand, will place the number it finds into the second parameter (in this

C H A P T E R 8 ■ B U I L D I N G W I N D O W S A P P L I C A T I O N S |
207 |
case, numberEntered). If the data it’s handed is not a number, TryParse() will return False, making it ideal for use in an If statement like this.
Assuming all goes to plan, and the user entered a valid integer into the text box, the value is compared. If it’s less than 1 or greater than 10, you know you have an invalid value.
Take a look back up at the event signature for a moment:
Private Sub numberBox_Validating(ByVal sender As System.Object, _
ByVal e As System.ComponentModel.CancelEventArgs) _
Handles numberBox.Validating
You get passed a CancelEventArgs object named e. This has a property inside it called Cancel. This is a simple Boolean (True/False) value and is set to False by default. Inside the Validating event handler, it’s up to your code to set this value to True if validation fails. What you are saying here is not that you are cancelling the validation event, but instead that you want to cancel whatever event triggered the validation. For example, if the user moves the focus to another control on the form or tries to close the form down, the Validating event will fire. If there isn’t any valid data inside the text box, you want to cancel the event that caused the validation to occur.
In our case, if the value entered is less than 1 or greater than 10, you set Cancel to True and display an error message to the user inside a message box. You do the same thing if the user didn’t enter a number at all but instead entered text: you set Cancel to True and display a different, appropriate message (see Figure 8-13).
Figure 8-13. The Validating event catches errors in your text box and displays an appropriate message.
If the Validating event exits with e.Cancel set to False, it’s safe to assume that any validation code in the event handler passed. .NET then fires the Validated event, to run code in the event of validation passing. Go back to the form editor, click on the text box again, and find the Validated event in the Properties window.
Double-click it to drop into the code editor for it:
Private Sub numberBox_Validated(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles numberBox.Validated
MessageBox.Show("Well done! Valid number entered.")
End Sub

208 |
C H A P T E R 8 ■ B U I L D I N G W I N D O W S A P P L I C A T I O N S |
All you want to do here is fire out a message letting the user know that all the validation completed successfully. If you run the program and enter a valid integer into the text box, you’ll see this working (see Figure 8-14).
Figure 8-14. Enter a valid value in the text box and the Validated event will fire, enabling you to display a congratulatory message.
I should point out that this is just a trivial example. There are much better ways of handling validation, as you’ll see later.
The MaskedTextBox Control
Visual Basic 2005 Express includes two types of text boxes: the one you just took a look at and the MaskedTextBox control. The MaskedTextBox control is a special kind of text box that can limit the data a user enters and also format it on the fly. For example, you could use a masked edit control to get a large number from the user and automatically format it with thousands separators. Another typical use would be to grab a zip code from the user and make sure that what the user enters is only digits and the correct length.
AN ALTERNATE VIEW OF THE MASKEDTEXTBOX
To be frank, the MaskedTextBox is a bit of a party crasher among controls. It’s a control that was originally in Visual Basic, and the .NET version is functionally identical to that control and was included to ease VB developers’ migration to .NET.
That’s certainly a great and worthy reason to include a control, but I don’t like this control at all. Since the time the control was first conceived, user interface standards have marched on, taking development tools with them. Today there are far better, less user-jarring ways to achieve the same thing. If you want to validate data in a control, use the Validating and Validated events. If on the other hand you want a specific kind of data (and by far the most common is a date), check out the date pickers that I’ll cover shortly.

C H A P T E R 8 ■ B U I L D I N G W I N D O W S A P P L I C A T I O N S |
209 |
Just what the user can and cannot enter into the control is governed by the Mask property. In here you enter a series of characters that denote just what is expected from the user at that position in the text. For example, entering 00/00/00 tells the control to expect two digits, followed by a slash, then two more digits, followed by a slash, and then two more digits—just like a date, in fact. The full list of characters that can be used to set up the mask can be found in the online help under MaskedTextBox.Mask property, as you can see in Figure 8-15.
Figure 8-15. The online help for the MaskedTextBox control shows the full list of values to enter into the Mask property to set up the control.
Thankfully, Microsoft doesn’t expect you to commit the list to memory and has supplied a number of built-in masks that you can get to from the control’s smart tag when it’s on a form. When you click the MaskedTextBox control’s smart tag and then choose Set Mask from the menu that appears, a dialog box is displayed that lets you select from any of the built-in mask formats (see Figure 8-16).