The TextBox Control


Text boxes should be used when you want users to enter text that you have no knowledge of at design time (for example, the user's name). The primary function of a text box is for users to enter text, but any characters can be entered, and it is quite possible to force users to enter numeric values only.

the .NET Framework comes with two basic controls to take text input from users: TextBox and RichTextBox. Both controls are derived from a base class called TextBoxBase which itself is derived from Control.

TextBoxBase provides the base functionality for text manipulation in a text box, such as selecting text, cutting to and pasting from the Clipboard, and a wide range of events. Right now you will not focus so much on what is derived from where, but instead look at the simpler of the two controls first — TextBox. You build one example that demonstrates the TextBox properties and build on that to demonstrate the RichTextBox control later.

TextBox Properties

As was the case with the controls earlier in this chapter, there are simply too many properties to describe them all, and so this listing includes only the most common ones.

Name

Description

CausesValidation

When a control with this property set to true is about to receive focus, two events are fired: Validating and Validated. You can handle these events in order to validate data in the control that is losing focus. This may cause the control never to receive focus. The related events are discussed below.

CharacterCasing

A value indicating if the TextBox changes the case of the text entered. The possible values are Lower: All text entered is converted lowercase. Normal: No changes are made to the text. Upper: All text entered is converted to uppercase.

MaxLength

A value that specifies the maximum length in characters of any text, entered into the TextBox. Set this value to zero if the maximum limit is limited only by available memory.

Multiline

Indicates if this is a multiline control, which means that it is able to show multiple lines of text. When Multiline property is set to true, you'll usually want to set WordWrap to true as well.

PasswordChar

Specifies if a password character should replace the actual characters entered into a single-line TextBox. If the Multiline property is true, then this has no effect.

ReadOnly

A Boolean indicating if the text is read-only.

ScrollBars

Specifies if a multiline TextBox should display scrollbars.

SelectedText

The text that is selected in the TextBox.

SelectionLength

The number of characters selected in the text. If this value is set to be larger than the total number of characters in the text, it is reset by the control to be the total number of characters minus the value of SelectionStart.

SelectionStart

The start of the selected text in a TextBox.

WordWrap

Specifies if a multiline TextBox should automatically wrap words if a line exceeds the width of the control.

TextBox Events

Careful validation of the text in the TextBox controls on a form can make the difference between happy users and angry ones.

You have probably experienced how annoying it is when a dialog only validates its contents when you click OK. This approach to validating the data usually results in a message box being displayed informing you that the data in "TextBox number three" is incorrect. You can then continue to click OK until all the data is correct. Clearly, this is not a good approach to validating data, so what can you do instead?

The answer lies in handling the validation events a TextBox control provides. If you want to make sure that invalid characters are not entered in the text box or only values within a certain range are allowed, then you will want to indicate to the user of the control whether the value entered is valid.

The TextBox control provides these events (all of which are inherited from Control).

Name

Description

Enter Leave Validating Validated

These four events occur in the order in which they are listed here. They are known as focus events and are fired whenever a control's focus changes, with two exceptions. Validating and Validated are only fired if the control that receives focus has the CausesValidation property set to true. The reason why it's the receiving control that fires the event is that there are times where you do not want to validate the control, even if focus changes. An example of this is when a user clicks a Help button.

KeyDown KeyPress KeyUp

These three events are known as key events. They allow you to monitor and change what is entered into your controls.

KeyDown and KeyUp receive the key code corresponding to the key that was pressed. This allows you to determine if special keys such as Shift or Control and F1 were pressed.

KeyPress, on the other hand, receives the character corresponding to a keyboard key. This means that the value for the letter a is not the same as the letter A. It is useful if you want to exclude a range of characters, for example, only allowing numeric values to be entered.

TextChanged

This event occurs whenever the text in the TextBox is changed, no matter what the change.

In the following Try It Out, you create a dialog on which you can enter your name, address, occupation, and age. The purpose of this example is to give you a good grounding in manipulating properties and using events, not to create something that is incredibly useful.

Try It Out – TextBoxTest

image from book

You build the user interface first.

  1. Create a new Windows application called TextBoxTest in the directory C:\BegVCSharp\ Chapter14.

  2. Create the form shown below by dragging some Label, TextBox, and Button controls onto the design surface. Before you can resize the two TextBox controls txtAddress and txtOutput as shown you must set their Multiline property to true. Do this by right-clicking the controls and select Properties.

  3. Name the controls as indicated in Figure 14-10.

    image from book
    Figure 14-10

  4. Set the Text property of each TextBox to an empty string, which means that they will contain nothing when the application is first run.

  5. Set the Text property of all the other controls to the same as the name of the control, except for the prefixes that indicate the type of the control (that is, Button, TextBox, and Label). Set the Text property of the form to TextBoxTest.

  6. Set the Scrollbars property of the two controls txtOutput and txtAddress to Vertical.

  7. Set the ReadOnly property of the txtOutput control to true.

  8. Set the CausesValidation property of the btnHelp Button to false. Remember from the discussion of the Validating and Validated events that setting this to false will allow users to click this button without having to be concerned about entering invalid data.

  9. When you have sized the form to fit snugly around the controls, it is time to anchor the controls so that they behave properly when the form is resized. Let's set the Anchor property for each type of control in one go — first, select all the TextBox controls except textBoxOutput by holding down the Ctrl key while you select each TextBox in turn. Once you've selected them all, set the Anchor property to Top, Left, Right from the Properties window, and the Anchor property for each of the selected TextBox controls will be set as well. Select just the textBoxOutput control and set the Anchor property to Top, Bottom, Left, Right. Now set the Anchor property for both Button controls to Top, Right.

    The reason txtOutput is anchored rather than docked to the bottom of the form is that you want the output text area to be resized as you pull the form. If you had docked the control to the bottom of the form, it would be moved to stay at the bottom, but it would not be resized.

  10. One final thing should be set. On the form, find the Size and MinimumSize properties. Your form has little meaning if it is sized to something smaller than it is now; therefore, you should set the MinimumSize property to the same as the Size property.

How It Works

The job of setting up the visual part of the form is now complete. If you run it nothing happens when you click the buttons or enter text, but if you maximize or pull in the dialog, the controls behave exactly as you want them to in a proper user interface, staying put and resizing to fill the whole of the dialog.

image from book

Adding the Event Handlers

From the design view, double-click the buttonOK button. Repeat this with the other button. As you saw in the button example earlier in this chapter, this causes event handlers for the Click event of the buttons to be created. When the OK button is clicked, you want to transfer the text in the input text boxes to the read-only output box.

Here is the code for the two Click event handlers:

private void buttonOK_Click(object sender, EventArgs e) { // No testing for invalid values are made, as that should // not be necessary string output; // Concatenate the text values of the four TextBoxes. output = "Name: " + this.textBoxName.Text + "\r\n"; output += "Address: " + this.textBoxAddress.Text + "\r\n"; output += "Occupation: " + this.textBoxOccupation.Text + "\r\n"; output += "Age: " + this.textBoxAge.Text; // Insert the new text. this.textBoxOutput.Text = output; }     private void buttonHelp_Click(object sender, EventArgs e) { // Write a short description of each TextBox in the Output TextBox. string output; output = "Name = Your name\r\n"; output += "Address = Your address\r\n"; output += "Occupation = Only allowed value is  output += "Age = Your age"; // Insert the new text. this.textBoxOutput.Text = output; }

In both functions, the Text property of each TextBox is used. the Text property of the textBoxAge control is used to get the value entered as the age of the person and the same property on the textBoxOutput control is used to display the concatenated text.

You insert the information the user has entered without bothering to check if it is correct. This means that you must do the checking elsewhere. In this example, there are a number of criteria to enforce to ensure that the values are correct:

  • The name of the user cannot be empty.

  • The age of the user must be a number greater than or equal to zero.

  • The occupation of the user must be "Programmer" or be left empty.

  • The address of the user cannot be empty.

From this, you can see that the check that must be done for two of the text boxes (textBoxName and textBoxAddress) is the same. You also see that you should prevent users from entering anything invalid into the Age box, and finally you must check if the user claims to be a programmer.

To prevent users from clicking OK before anything is entered, start by setting the OK button's Enabled property to false — this time you do it in the constructor of your form rather than from the Properties window. If you do set properties in the constructor, make sure not to set them until after the generated code in InitializeComponent() has been called.

public Form1() {    InitializeComponent(); this.buttonOK.Enabled = false; }

Now, you create the handler for the two text boxes that must be checked to see if they are empty. You do this by subscribing to the Validating event of the text boxes. You inform the control that the event should be handled by a method named txtBoxEmpty_Validating(), so that's a single event-handling method for two different controls.

You also need a way to know the state of your controls. For this purpose, use the Tag property of the TextBox control. Recall from the discussion of this property earlier in the chapter that only strings can be assigned to the Tag property from the forms designer. However, as you are setting the Tag value from code, you can do pretty much what you want with it, since the Tag property takes an object, and it is more appropriate to enter a Boolean value here.

To the constructor add the following statements:

      this.buttonOK.Enabled = false;     // Tag values for testing if the data is valid this.textBoxAddress.Tag = false; this.textBoxAge.Tag = false; this.textBoxName.Tag = false; this.textBoxOccupation.Tag = false;  // Subscriptions to events this.textBoxName.Validating += new System.ComponentModel.CancelEventHandler(this.textBoxEmpty_Validating); this.textBoxAddress.Validating += new System.ComponentModel.CancelEventHandler(this.textBoxEmpty_ Validating); 

Unlike the button event handler you've seen previously, the event handler for the Validating event is a specialized version of the standard handler System.EventHandler. The reason that this event needs a special handler is that should the validation fail, there must be a way to prevent any further processing. If you were to cancel further processing, that would effectively mean that it would be impossible to leave a text box until the data entered is valid.

The Validating and Validated events combined with the CausesValidation property fix a nasty problem that occurred when using the GotFocus and LostFocus events to perform validation of controls in earlier versions of Visual Studio. The problem occurred when the GotFocus and LostFocus events were continually fired because validation code was attempting to shift the focus between controls, which created an infinite loop.

Add the event handler as follows:

private void textBoxEmpty_Validating (object sender,                                      System.ComponentModel.CancelEventArgs e) { // We know the sender is a TextBox, so we cast the sender object to that. TextBox tb = (TextBox)sender; // If the text is empty we set the background color of the  // Textbox to red to indicate a problem. We use the tag value // of the control to indicate if the control contains valid // information. if (tb.Text.Length == 0) { tb.BackColor = Color.Red; tb.Tag = false; // In this case we do not want to cancel further processing, // but if we had wanted to do this, we would have added this line: // e.Cancel = true; } else { tb.BackColor = System.Drawing.SystemColors.Window; tb.Tag = true; } // Finally, we call ValidateOK which will set the value of // the OK button. ValidateOK(); }

Because more than one text box is using this method to handle the event, you cannot be sure which is calling the function. You do know, however, that the effect of calling the method should be the same no matter who is calling, so you can simply cast the sender parameter to a TextBox and work on that:

TextBox tb = (TextBox)sender;

If the length of the text in the text box is zero, set the background color to red and the Tag to false. If it is not, set the background color to the standard Windows color for a window.

Note

You should always use the colors found in the System.Drawing.SystemColors enumeration when you want to set a standard color in a control. If you simply set the color to white, your application will look strange if the user has changed the default color settings.

I'll postpone the description of the ValidateOK() function until the end of this example.

Keeping with the Validating event, the next handler you'll add is for the Occupation text box. The procedure is exactly the same as for the two previous handlers, but the validation code is different because occupation must be Programmer or an empty string to be valid. You, therefore, add a new line to the constructor.

 this.textBoxOccupation.Validating += new  System.ComponentModel.CancelEventHandler(this.textBoxOccupation_Validating); 

And then the handler itself:

private void textBoxOccupation_Validating(object sender,                                       System.ComponentModel.CancelEventArgs e) { // Cast the sender object to a textbox. TextBox tb = (TextBox)sender; // Check if the values are correct. if (tb.Text.CompareTo("Programmer") == 0 || tb.Text.Length == 0) { tb.Tag = true; tb.BackColor = System.Drawing.SystemColors.Window; } else { tb.Tag = false; tb.BackColor = Color.Red; } // Set the state of the OK button. ValidateOK(); } 

Your second to last challenge is the Age text box. You don't want users to type anything but positive numbers (including 0 to make the test simpler). To achieve this, you use the KeyPress event to remove any unwanted characters before they are shown in the text box. You'll also limit the number of characters that can be entered into the control to three.

First, set the MaxLength of the textBoxAge control to 3. Then subscribe to the KeyPress event by double-clicking the KeyPress event in the Events list of the Properties window. the KeyPress event handler is specialized as well. the System.Windows.Forms.KeyPressEventHandler is supplied because the event needs information about the key that was pressed.

Add the following code to the event handler itself:

private void textBoxAge_KeyPress(object sender, KeyPressEventArgs e) { if ((e.KeyChar < 48 || e.KeyChar > 57) && e.KeyChar != 8) e.Handled = true; // Remove the character }

The ASCII values for the characters between 0 and 9 lie between 48 and 57, so you make sure that the character is within this range. You make one exception though. The ASCII value 8 is the Backspace key, and for editing reasons, you allow this to slip through.

Setting the Handled property of KeyPressEventArgs to true tells the control that it shouldn't do anything else with the character, and so if the key pressed isn't a digit or a backspace, it is not shown.

As it is now, the control is not marked as invalid or valid. This is because you need another check to see if anything was entered at all. This is a simple thing as you've already written the method to perform this check, and you simply subscribe to the Validating event for the Age control as well by adding this line to the constructor:

 this.textBoxAge.Validating += new System.ComponentModel.CancelEventHandler(this.textBoxEmpty_Validating); 

One last case must be handled for all the controls. If the user has entered valid text in all the text boxes and then changes something, making the text invalid, the OK button remains enabled. So, you have to handle one last event handler for all of the text boxes: the Change event, which will disable the OK button should any text field contain invalid data.

The TextChanged event is fired whenever the text in the control changes. You subscribe to the event by adding the following lines to the constructor:

 this.textBoxName.TextChanged += new System.EventHandler(this.textBox_TextChanged); this.textBoxAddress.TextChanged += new System.EventHandler(this.textBox_TextChanged); this.textBoxAge.TextChanged += new System.EventHandler(this.textBox_TextChanged); this.textBoxOccupation.TextChanged += new System.EventHandler(this.textBox_TextChanged); 

The TextChanged event uses the standard event handler you know from the Click event. Finally, add the event itself.

private void textBox_TextChanged(object sender, System.EventArgs e) { // Cast the sender object to a Textbox TextBox tb = (TextBox)sender; // Test if the data is valid and set the tag and background // color accordingly. if (tb.Text.Length == 0 && tb != textBoxOccupation) { tb.Tag = false; tb.BackColor = Color.Red; } else if (tb == textBoxOccupation && (tb.Text.Length != 0 && tb.Text.CompareTo("Programmer") != 0)) { // Don't set the color here, as it // is typing. tb.Tag = false; } else { tb.Tag = true; tb.BackColor = SystemColors.Window; } // Call ValidateOK to set the OK button. ValidateOK(); }

This time, you must find out exactly which control is calling the event handler, because you don't want the background color of the Occupation text box to change to red when the user starts typing. You do this by checking the Name property of the text box that was passed to you in the sender parameter.

Only one thing remains: the ValidateOK method that enables or disables the OK button.

private void ValidateOK() { // Set the OK button to enabled if all the Tags are true. this.buttonOK.Enabled = ((bool)(this.textBoxAddress.Tag) && (bool)(this.textBoxAge.Tag) && (bool)(this.textBoxName.Tag) && (bool)(this.textBoxOccupation.Tag)); }

The method simply sets the value of the Enabled property of the OK button to true if all of the Tag properties are true. You need to cast the value of the Tag properties to a Boolean because it is stored as an object type.

If you test the program now, you should see something like what is shown in Figure 14-11.

image from book
Figure 14-11

Notice that you can click the Help button while in a text box with invalid data without the background color changing to red.

The example you just completed is quite long compared to the others you will see in this chapter — this is because you build on this example rather than starting from scratch with each example.

Note

Remember that you can download the source code for all the examples in this book from http://www.wrox.com.




Beginning Visual C# 2005
Beginning Visual C#supAND#174;/sup 2005
ISBN: B000N7ETVG
EAN: N/A
Year: 2005
Pages: 278

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net