Testing the Building Class
Figure 17.1 shows a form that you can use to test the Building class and its derived classes. The form includes a series of text boxes that are used to collect the base class member information (for example, street address, purchase price). The following sections discuss various aspects of the test program that need further explanation.
Figure 17.1. A form for testing the Building class.
Using Combo Boxes
The last property member of the base class is the property type. Figure 17.1 shows this data being presented to the user in a combo box. You have not used a combo box before, so this section provides a few details on how to use combo boxes. (Additional details about using combo boxes and other Visual Basic .NET control objects are presented in Chapter 21, "Creating Your Own Controls.") The following code fragment shows how you add the list of choices to a combo box:
cmbPropertyType.Items.Add("Apartment") cmbPropertyType.I tems.Add("Commercial") cmbPropertyType.Items.Add("Home") cmbPropertyType.SelectedIndex = 0
You add the combo box from the toolbar to the form by double-clicking the combo box object in the normal manner and supplying it with the name cmbPropertyType .
The first three lines show how you can use the Add() method to add an item to the list in the combo box. If the Sort property for the combo box is set to logic False , the Add() method results in a list that appears in the order in which the methods are entered. In this case, you enter them into the combo box in sorted order anyway, so they appear in sorted order, even though you do not have the Sort property set to True .
The SelectedIndex property determines which item in the combo box list is displayed. Because you set the SelectedIndex property to , the first item in the list (that is, Apartment ) is displayed.
Derived Class Member Data
Near the bottom of the form shown in Figure 17.1 are three group boxes, which are used to rope off the member data inputs for each derived class. What is not obvious from Figure 17.1 is that you do not display these group boxes when the program begins execution. Figure 17.2 shows how the program looks just before you select the derived class building type.
Figure 17.2. A form for testing the Building class before the building type is selected.
Notice that none of the group boxes are displayed at this point in the program. This is because you have set the Visibility property for each group box to logic False . After the user selects the type of building he or she is entering, the form displays the group box for that building type.
Figure 17.3 shows the form after the Commercial building type is selected from the combo box. Notice that only the group box for the Commercial building type is displayed. The user interface displays only the group box for the building type that is selected. This user interface design forces the user to consider the base class information before moving on to the specifics of the derived class data. If you compare Figure 17.1 and 17.3, you should see that the user interface is less complex and less confusing if the input text boxes for the other building classes are hidden.
Figure 17.3. A form for testing the Building class after the Commercial building type is selected.
Of course, you could use other designs. The current design has one bad feature. If you never place the cursor in the combo box, you can never fire the Leave() event of the combo box. This means the Apartment group box would never be displayed because if you are happy with the Apartment selection displayed in the combo box, you have no reason to place your cursor in the box, which means the Leave() event would never fire. This is not good.
A solution might be to display the group box for the Apartment selection when the program starts. If the user selects a building type other than Apartment , you could use the combo box's Leave() event to hide the Apartment group box and then display the group box the user selects. I encourage you to add the code for this improved version to the test program.
After all the input data has been entered, you can click the Add Property button to show the class data. Figure 17.4 shows the output from the program in the Debug window.
Figure 17.4. A form for testing the Building class after the Add Property button is clicked.
The code to test the Building Class program is presented in Listing 17.3.
Listing 17.3 Code to Test the Building Class Program
Public Class frmBuilding Inherits System.Windows.Forms.Form Dim MyApartment As New Apartment() Dim MyBuilding As New Commercial() Dim MyHome As New Home() ' " Windows Form Designer generated code " Private Sub frmBuilding_Load(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles MyBase.Load cmbPropertyType.Items.Add("Apartment") cmbPropertyType.Items.Add("Commercial") cmbPropertyType.Items.Add("Home") cmbPropertyType.SelectedIndex = 0 grbApt.Visible = False grbCom.Visible = False grbHome.Visible = False End Sub Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles btnExit.Click MyApartment = Nothing ' Release the resources MyBuilding = Nothing MyHome = Nothing Me.Dispose() End Sub Private Sub cmbPropertyType_Leave(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles cmbPropertyType.Leave Select Case cmbPropertyType.SelectedIndex Case 0 ' Apartment grbApt.Visible = True txtAUnits.Focus() Case 1 ' Commercial grbCom.Visible = True txtCSqFt.Focus() Case 2 ' Home grbHome.Visible = True txtHSqFt.Focus() End Select End Sub Private Sub cmbPropertyType_Enter(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles cmbPropertyType.Enter grbApt.Visible = False ' Hide the group boxes grbCom.Visible = False grbHome.Visible = False End Sub Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles btnAdd.Click Select Case cmbPropertyType.SelectedIndex Case 0 ' Apartment MyApartment.BuildingType = 0 MyApartment.Address = txtAddress.Text MyApartment.PurchasePrice = CDbl(txtPrice.Text) MyApartment.MonthlyPayment = CDbl(txtMonthlyPay.Text) MyApartment.Taxes = CDbl(txtTaxes.Text) MyApartment.DisplayBuilding() Case 1 ' Commercial MyBuilding.BuildingType = 1 MyBuilding.Address = txtAddress.Text MyBuilding.PurchasePrice = CDbl(txtPrice.Text) MyBuilding.MonthlyPayment = CDbl(txtMonthlyPay.Text) MyBuilding.Taxes = CDbl(txtTaxes.Text) MyBuilding.DisplayBuilding() Case 2 ' Home MyHome.BuildingType = 2 MyHome.Address = txtAddress.Text MyHome.PurchasePrice = CDbl(txtPrice.Text) MyHome.MonthlyPayment = CDbl(txtMonthlyPay.Text) MyHome.Taxes = CDbl(txtTaxes.Text) MyHome.DisplayBuilding() End Select End Sub ' ============= Apartment fields ============== Private Sub txtAUnits_Leave(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles txtAUnits.Leave MyApartment.Units = CInt(txtAUnits.Text) End Sub Private Sub txtARent_Leave(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles txtARent.Leave MyApartment.Rents = CDbl(txtARent.Text) End Sub Private Sub txtAOccup_Leave(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles txtAOccup.Leave MyApartment.OccupancyRate = CDbl(txtAOccup.Text) End Sub ' ============ Commercial fields ================== Private Sub txtCSqFt_Leave(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles txtCSqFt.Leave MyBuilding.SquareFeet = CInt(txtCSqFt.Text) End Sub Private Sub txtCRent_Leave(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles txtCRent.Leave MyBuilding.RentPerSF = CDbl(txtCRent.Text) End Sub Private Sub txtCPark_Leave(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles txtCPark.Leave MyBuilding.ParkingSpots = CInt(txtCPark.Text) End Sub ' =============== Home Fields ================= Private Sub txtHSqFt_Leave(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles txtHSqFt.Leave MyHome.SquareFeet = CInt(txtHSqFt.Text) End Sub Private Sub txtHRent_Leave(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles txtHRent.Leave MyHome.Rent = CDbl(txtHRent.Text) End Sub Private Sub txtBedrooms_Leave(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles txtBedrooms.Leave MyHome.Bedrooms = CInt(txtBedrooms.Text) End Sub Private Sub txtBaths_Leave(ByVal sender As Object, ByVal e As _ System.EventArgs) Handles txtBaths.Leave MyHome.Baths = CInt(txtBaths.Text) End Sub End Class
There are no surprises in the code in Listing 17.3. The initialization of the combo box is in the frmBuilding_Load() event. The cmbPropertyType.Leave() event for the combo box is used to display the proper group box after the building type has been selected. For each building type, a Select Case structure is used to make the appropriate group box visible and set the focus to the first text box in the group. Because the possibility exists that the cmbPropertyType.Leave() event may never fire, you place the assignments for the base class properties in the btnAdd object's Click() event procedure.
The last statement for each Case is a Focus() event call to the first text box in the appropriate group box. For example, if the user selected the Apartment building type, the last statement for Case 0 (that is, an Apartment type) would call txtAUnits.Focus() . This call has the effect of moving the cursor to the txtAUnits text box.
The btnAdd object's Click() event code assigns the member data and then calls the DisplayBuilding() method for the selected building type. Notice that the same method is called for each building type. If you used a general subroutine or function instead of a class method, you would have to pass some form of data to the routine so that it could decide which building type to display. Encapsulation and inheritance simplify this considerably. Neat stuff!
Simple Changes to Enhance the Building Test Program
If you review the output in Figure 17.4, you might notice that it would be nice if the dollar figures had commas in the appropriate places. Look at the FormatMoney() method near the bottom of Listing 17.1. You can modify the statement that begins with Return so that it looks like this:
Return Format(num, "$#,###,###,###.00")
When you rerun the program, the output changes to that shown in Figure 17.5.
Figure 17.5. A form for testing the Building class, after the FormatMoney() method is modified.
Now the dollar figures are formatted with commas in the appropriate places. Notice that because FormatMoney() is a Protected method in the base class, this change is available to all the derived classes. More importantly, the derived classes don't need to concern themselves about the details of how the change is made: The derived classes get the benefits of the change for free!