Home

Dictionary-Based Collections

 

Introduction to Dictionaries

 

Description

A dictionary is a list of items with the following two rules:

  • Each item is a combination of a key and a value. An item can be made of three parts: a key, a value, and a correspondence between them. The correspondence can be represented by the assignment operator: Key=Value. In some environments, the = operator is used. In some others, the : operator is used. Yet in some others, there is no actual operator that joins both sides but you must know that the key and the value go in pair
  • As each item is a combination of a key and a value, each key must be unique. The list of items in the dictionary can be very huge, sometimes in the thousands or even millions. Among the items, each key must be distinct from any other key in the dictionary

In some cases, in addition to these two rules, the items should - in some cases must - be ordered. To order the items, the keys are used. Because in most cases a dictionary is made of words, the keys are ordered in alphabetical order. A dictionary can also be made of items whose keys are date values. In this case, the items would be ordered in chronological order.

There are various kinds of dictionary types of list used in daily life. The word "dictionary" here does not imply the traditional dictionary that holds the words and their meanings in the English language. The concept is applied in various scenarios.

Practical LearningPractical Learning: Introducing Dictionary Collections

  1. Start Microsoft Visual Basic and create a new Windows Forms Application named BethesdaCarRental1
  2. To add a new form to the project, in the Solution Explorer, right-click BethesdaCarRental1 -> Add -> Windows Form...
  3. Set the Name to RentalRates and press Enter
  4. Add a ListView to the form and create its Columns as follows:
     
    (Name) Text TextAlign Width
    colCategory Category   90
    colDaily Daily Right  
    colWeekly Weekly Right  
    colMonthly Monthly Right  
    colWeekend Weekend Right  
  5. Create its Items as follows:
     
    ListViewItem SubItems SubItems SubItems SubItems
      Text Text Text Text
    Economy 35.95 32.75 28.95 24.95
    Compact 39.95 35.75 32.95 28.95
    Standard 45.95 39.75 35.95 32.95
    Full Size 49.95 42.75 38.95 35.95
    Mini Van 55.95 50.75 45.95 42.95
    SUV 55.95 50.75 45.95 42.95
    Truck 42.75 38.75 35.95 32.95
    Van 69.95 62.75 55.95 52.95
  6. Complete the design of the form as follows:
     
    Rental Rates
  7. To add a new form to the application, in the Solution Explorer, right-click BethesdaCarRental1 -> Add -> Windows Form...
  8. Set the Name to Employees and click Add
  9. From the Toolbox, add a ListView to the form
  10. While the new list view is still selected, in the Properties window, click the ellipsis button of the Columns field and create the columns as follows:
     
    (Name) Text TextAlign Width
    colEmployeeNumber Empl #   45
    colFirstName First Name   65
    colLastName Last Name   65
    colFullName Full Name   140
    colTitle Title   120
    colHourlySalary Hourly Salary Right 75
  11. Design the form as follows: 
     
    Bethesda Car Rental: Employees
     
    Control Text Name Other Properties
    ListView   lvwEmployees Anchor: Top, Bottom, Left, Right
    FullRowSelect: True
    GridLines: True
    View: Details
    Button New Employee... btnNewEmployee  
    Button Close btnClose  
  12. To add another form to the application, in the Solution Explorer, right- click BethesdaCarRental1 -> Add -> Windows Form...
  13. Set the Name to EmployeeEditor and click Add
  14. Design the form as follows: 
     
    Bethesda Car Rental: Employees
     
    Control Text Name Properties
    Label &Employee #:    
    MaskedTextBox   txtEmployeeNumber Mask: 00-000
    Modifiers: public
    Label First Name:    
    TextBox   txtFirstName Modifiers: public
    Label Last Name:    
    TextBox   txtLastName Modifiers: public
    Label Full Name:    
    TextBox   txtFullName Enabled: False
    Modifiers: public
    Label Title:    
    TextBox   txtTitle Modifiers: public
    Label Hourly Salary:    
    TextBox   txtHourlySalary Modifiers: public
    TextAlign: Right
    Button OK btnOK DialogResult: OK
    Button Cancel btnCancel DialogResult: Cancel
    Form     AcceptButton: btnOK
    CancelButton: btnCancel
    FormBorderStyle: FixedDialog
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskbar: False
  15. Right-click the form and click View Code
  16. In the Class Name combo box, select txtLastName
  17. In the Method Name combo box, select Leave and implement the event as follows:
     
    REM This code is used to create and display the customer's full name
    Private Sub txtLastName_Leave(ByVal sender As Object, _
                                      ByVal e As System.EventArgs) _
                                      Handles txtLastName.Leave
            Dim strFirstName As String = txtFirstName.Text
            Dim strLastName As String = txtLastName.Text
            Dim strFullName As String
    
            If strFirstName.Length = 0 Then
                strFullName = strLastName
            Else
                strFullName = strLastName & ", " & strFirstName
            End If
    
            txtFullName.Text = strFullName
        End Sub
  18. To add a new class to the project, on the main menu, click Project -> Add Class...
  19. Set the Class Name to Employee and click Add
  20. Change the Employee.vb file as follows:
     
    <Serializable()> Public Class Employee
        Public FirstName As String
        Public LastName As String
        Public Title As String
        Public HourlySalary As Double
    
        Public ReadOnly Property FullName()
            Get
                Return LastName & ", " & FirstName
            End Get
        End Property
    
        REM This default constructor says that
        REM the employee is not defined
        Public Sub New()
            FirstName = "Unknown"
            LastName = "Unknown"
            Title = "N/A"
            HourlySalary = 0.0
        End Sub
    
        REM This constructor completely defines an employee
        Public Sub New(ByVal fname As String, ByVal lname As String, _
                            ByVal title As String, ByVal salary As Double)
            FirstName = fname
            LastName = lname
            Title = Title
            HourlySalary = salary
        End Sub
    End Class
  21. To add a new form to the application, on the main menu, click Project -> Add Windows Forms
  22. Set the Name to Customers and press Enter
  23. From the Toolbox, add a ListView to the form
  24. While the new list view is still selected, in the Properties window, click the ellipsis button of the Columns field and create the columns as follows:
     
    (Name) Text Width
    colDrvLicNbr Driver's Lic. # 100
    colFullName Full Name 100
    colAddress Address 160
    colCity City 100
    colState State 38
    colZIPCode ZIP Code  
  25. Design the form as follows: 
     
    Bethesda Car Rental: Customers
     
    Control Text Name Other Properties
    ListView   lvwCustomers View: Details
    GridLines: True
    FullRowSelect: True
    Button New Customer... btnNewCustomer  
    Button Close btnClose  
  26. To add another form to the application, on the main menu, click Project -> Add Windows Forms
  27. Set the Name to CustomerEditor and click Add
  28. Design the form as follows: 
     
    Bethesda Car Rental: Customers
     
    Control Text Name Properties
    Label Driver's Lic. #:    
    TextBox   txtDrvLicNbr Modifiers: Public
    Label State:    
    ComboBox   cbxStates Modifiers: Public
    Items: AL, AK, AZ, AR, CA, CO, CT, DE, DC, FL, GA, HI, ID, IL, IN, IA, KS, KY, LA, ME, MD, MA, MI, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VT, VA, WA, WV, WI, WY
    Label Full Name:    
    TextBox   txtFullName Modifiers: Public
    Label Address:    
    TextBox   txtAddress Modifiers: Public
    Label City:    
    TextBox   txtCity Modifiers: Public
    Label ZIP Code:    
    TextBox   txtZIPCode Modifiers: Public
    Button OK btnOK DialogResult: OK
    Button Close btnCancel DialogResult: Cancel
    Form     AcceptButton: btnOK
    CancelButton: btnCancel
    FormBorderStyle: FixedDialog
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskbar: False
  29. To add a new class to the project, on the main menu, click Project -> Add Class...
  30. Set the Class Name to Customer and click Finish
  31. Change the Customer.vb file as follows:
     
    <Serializable()> Public Class Customer
        Public FullName As String
        Public Address As String
        Public City As String
        Public State As String
        Public ZIPCode As String
    
        Public Sub New()
            FullName = ""
            Address = ""
            City = ""
            State = ""
            ZIPCode = ""
        End Sub
    
        REM This constructor defines a customer
        Public Sub New(ByVal fName As String, _
                        ByVal adr As String, ByVal ct As String, _
                        ByVal ste As String, ByVal zip As String)
            FullName = fName
            Address = adr
            City = ct
            State = ste
            ZIPCode = zip
        End Sub
    End Class
  32. Save all
  33. Copy the following pictures to any folder somewhere on your computer (this is simply an example of preparing the pictures of cars you would include in your database application):
     
    Car Chevrolet Avalanche
    BMW: 335i Chevrolet Avalanche
    Car Mazda Miata
    Honda Accord Mazda Miata
    Chevrolet Aveo Ford E150XL
    Chevrolet Aveo Ford E150XL
    Buick LaCrosse Honda Civic
    Buick Lacrosse Honda Civic
    Ford F-150 Mazda Mazda5
    Ford F-150 Mazda Mazda5
    Volvo S40 Land Rover LR3
    Volvo S40 Land Rover LR3
  34. Return to your programming environment
  35. To add a new form to the application, in the Solution Explorer, right-click BethesdaCarRental1 -> Add -> Windows Forms
  36. Set the Name to CarEditor and click Add
  37. Design the form as follows: 
     
    Bethesda Car Rental - Car Editor
    Control Text Name Other Properties
    Label Text #    
    TextBox   txtTagNumber  
    Label Make:    
    TextBox   txtMake  
    Label Model:    
    TextBox   txtModel  
    Label Year:    
    TextBox   txtYear  
    Label Category:    
    ComboBox   cboCategories DropDownStyle: DropDownList
    Items: Economy
    Compact
    Standard
    Full Size
    Mini Van
    SUV
    Truck
    Van
    PictureBox   pbxCar SizeMode: Zoom
    CheckBox CD Player chkCDPlayer CheckAlign: MiddleRight
    CheckBox DVD Player chkDVDPlayer CheckAlign: MiddleRight
    Button Select Car Picture... btnSelectPicture  
    CheckBox Available chkAvailable CheckAlign: MiddleRight
    Label Picture Name lblPictureName  
    Button Submit btnSubmit  
    Button Close btnClose DialogResult: Cancel
    OpenFileDialog (Name): dlgOpen
    Title: Select Item Picture
    DefaultExt: jpg
    Filter: JPEG Files (*.jpg,*.jpeg)|*.jpg|GIF Files (*.gif)|*.gif|Bitmap Files (*.bmp)|*.bmp|PNG Files (*.png)|*.png
    Form     FormBorderStyle: FixedDialog
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskbar: False
  38. Double-click the Select Car Picture button and implement its event as follows:
     
    Private Sub btnSelectPicture_Click(ByVal sender As System.Object, _
                                           ByVal e As System.EventArgs) _
                                           Handles btnSelectPicture.Click
            If dlgPicture.ShowDialog() = DialogResult.OK Then
                lblPictureName.Text = dlgPicture.FileName
                pbxCar.Image = Image.FromFile(lblPictureName.Text)
            End If
    End Sub
  39. To add a new class to the project, on the main menu, click Project -> Add Class...
  40. Set the Class Name to Car and click Add
  41. Change the file as follows:
     
    <Serializable()> Public Class Car
        Public Make As String
        Public Model As String
        Public Year As Integer
        Public Category As String
        Public HasCDPlayer As Boolean
        Public HasDVDPlayer As Boolean
        Public IsAvailable As Boolean
    
        Public Sub New()
            Make = ""
            Model = ""
            Year = 0
            Category = ""
            HasCDPlayer = False
            HasDVDPlayer = False
            IsAvailable = False
        End Sub
    
        Public Sub New(ByVal mk As String, ByVal mdl As String, _
                   ByVal yr As Integer, ByVal cat As String, _
                   ByVal cd As Boolean, ByVal dvd As Boolean, _
                   ByVal avl As Boolean)
            Make = mk
            Model = mdl
            Year = yr
            Category = cat
            HasCDPlayer = cd
            HasDVDPlayer = dvd
            IsAvailable = avl
        End Sub
    End Class
  42. To add a new class to the project, on the main menu, click Project -> Add Class...
  43. Set the Class Name to RentalOrder and press Enter
  44. Access the RentalOrder.vb file and change it as follows:
     
    <Serializable()> Public Class RentalOrder
        Public EmployeeNumber As String
        REM The following flag will allow us to update/know whether
        REM * The car is currently being used by the customer.
        REM   That is, if the car has been picked up by the customer
        REM * The customer has brought the car back
        Public OrderStatus As String
        REM Because every car has a tag number
        REM and that tag number will not change
        REM during the lifetime of a car (while the car remains with our
        REM car rental company, we will 
        REM use only the tag number here.
        REM The other pieces of information will 
        REM be retrieved from the list of cars
        Public CarTagNumber As String
        REM We will identify the customer by the number
        REM and the name on his or her driver's license
        Public CustomerDrvLicNbr As String
        Public CustomerName As String
        REM Although he or she may keep the same driver's 
        REM license number for a lifetime, a customer who 
        REM rents cars at different times with this company 
        REM over months or years may have different addresses.
        REM Therefore, although we will primarily retrieve the 
        REM customer's address from the list of customers,
        REM we will give the clerk the ability to change this 
        REM information on a rental order. This means that the 
        REM same customer could have different information on 
        REM different rental orders.
        REM For this reason, each rental order will its own set
        REM of these pieces of information
        Public CustomerAddress As String
        Public CustomerCity As String
        Public CustomerState As String
        Public CustomerZIPCode As String
        Public CarCondition As String
        Public TankLevel As String
        REM This information will be entered when the car is being rented
        Public MileageStart As Integer
        REM This information will be entered when the car is brought back
        Public MileageEnd As Integer
        REM This information will be entered when the car is being rented
        Public DateStart As DateTime
        REM This information will be entered when the car is brought back
        Public DateEnd As DateTime
        Public Days As Integer
        REM This information will be entered when the car is being rented
        Public RateApplied As Double
        REM This calculation should occur when the car is brought back
        Public SubTotal As Double
        Public TaxRate As Double
        Public TaxAmount As Double
        Public OrderTotal As Double
    End Class
  45. To add a new form to the project, in the Solution Explorer, right-click BethesdaCarRenat1 -> Add -> Windows Form...
  46. Set the Name to OrderProcessing and press Enter
  47. Design the form as follows:
     
    Rental Orders
    Control Text Name Other Properties
    Label Processed By:   AutoSize: False
    BackColor: Gray
    BorderStyle: FixedSingle
    ForeColor: White
    TextAlign: MiddleLeft
    Label Employee #:    
    MaskedTextBox   txtEmployeeNumber Mask: 00-000
    Label Employee Name:    
    TextBox   txtEmployeeName  
    Label Processed For   AutoSize: False
    BackColor: Gray
    BorderStyle: FixedSingle
    ForeColor: White
    TextAlign: MiddleLeft
    Label Driver's Lic #:    
    TextBox   txtDrvLicNumber  
    Label Cust Name:    
    TextBox   txtCustomerName  
    Label Address:    
    TextBox   txtCustomerAddress  
    Label City:    
    TextBox   txtCustomerCity  
    Label State:    
    ComboBox   cbxCustomerStates DropDownStyle: DropDownList
    Sorted: True
    Items: AL, AK, AZ, AR, CA, CO, CT, DE, DC, FL, GA, HI, ID, IL, IN, IA, KS, KY, LA, ME, MD, MA, MI, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VT, VA, WA, WV, WI, WY
    Label ZIP Code    
    TextBox   txtCustomerZIPCode  
    Label Car Selected   AutoSize: False
    BackColor: Gray
    BorderStyle: FixedSingle
    ForeColor: White
    TextAlign: MiddleLeft
    Label Tag Number:    
    TextBox   txtTagNumber  
    Label Car Condition:    
    ComboBox   cbxCarConditions Sorted: True
    Items:
    Needs Repair
    Drivable
    Excellent
    Label Make:    
    TextBox   txtMake  
    Label Model:    
    TextBox   txtModel  
    Label Year:    
    TextBox   txtCarYear  
    label Tank Level:    
    ComboBox   cbxTankLevels Empty
    1/4 Empty
    1/2 Full
    3/4 Full
    Full
    Label Mileage Start:    
    TextBox   txtMileageStart TextAlign: Right
    Label Mileage End:    
    TextBox   txtMileageEnd TextAlign: Right
    Label Order Timing   AutoSize: False
    BackColor: Gray
    BorderStyle: FixedSingle
    ForeColor: White
    TextAlign: MiddleLeft
    Label Start Date:    
    DateTimePicker   dtpStartDate  
    Label End Date:    
    DateTimePicker   dtpEndDate  
    Label Days:    
    TextBox 0 txtDays TextAlign: Right
    Label Order Status    
    ComboBox   cbxOrderStatus Items:
    Car On Road
    Car Returned
    Order Reserved
    Label Order Evaluation   AutoSize: False
    BackColor: Gray
    BorderStyle: FixedSingle
    ForeColor: White
    TextAlign: MiddleLeft
    Label Rate Applied:    
    TextBox 0.00 txtRateApplied TextAlign: Right
    Button Rental Rates btnRentalRates  
    Label Sub-Total:    
    TextBox 0.00 txtSubTotal TextAlign: Right
    Button Calculate btnCalculate  
    Label Tax Rate:    
    TextBox 7.75 txtTaxRate TextAlign: Right
    Label %    
    Button Save btnSave  
    Label Tax Amount:    
    TextBox 0.00 txtTaxAmount TextAlign: Right
    Button Print... btnPrint  
    Label Order Total:    
    TextBox 0.00 txtOrderTotal TextAlign: Right
    Button Print Preview... btnPrintPreview  
    Label Receipt #:    
    TextBox 0 txtReceiptNumber  
    Button Open btnOpen  
    Button New Rental Order/Reset btnNewRentalOrder  
    Button Close btnClose  
  48. Right-click the form and click View Code
  49. In the Class Name combo box, select dtpStartDate
  50. In the Method Name combo box, selectValueChanged and implement the event as follows:
     
    Private Sub dtpStartDate_ValueChanged(ByVal sender As Object, _
                                          ByVal e As System.EventArgs) _
                                          Handles dtpStartDate.ValueChanged
            dtpEndDate.Value = dtpStartDate.Value
    End Sub
  51. In the Class Name combo box, select dtpEndDate
  52. In the Method Name combo box, select ValueChanged and implement the event as follows:
     
    REM This event approximately evaluates the number of days as a
    REM difference between the end date and the starting date
    Private Sub dtpEndDate_ValueChanged(ByVal sender As Object, _
                                        ByVal e As System.EventArgs) _
                                        Handles dtpEndDate.ValueChanged
        Dim Days As Integer
        Dim DateStart As DateTime = dtpStartDate.Value
        Dim DateEnd As DateTime = dtpEndDate.Value
    
        REM Let's calculate the difference in days
        Dim tme As TimeSpan = DateEnd - DateStart
        Days = tme.Days
    
        REM If the customer returns the car the same day, 
        REM we consider that the car was rented for 1 day
        If Days = 0 Then Days = 1
    
        txtDays.Text = Days
        REM At any case, we will let the clerk specify the actual number of days
    End Sub
  53. In the Class Name combo box, select btnRentalRates
  54. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnRentalRates_Click(ByVal sender As Object, _
                                         ByVal e As System.EventArgs) _
                                         Handles btnRentalRates.Click
        Dim RateViewer As RentalRates = New RentalRates
        RateViewer.Show()
    End Sub
  55. In the Class Name combo box, select btnCalculate
  56. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnCalculate_Click(ByVal sender As Object, _
                                       ByVal e As System.EventArgs) _
                                       Handles btnCalculate.Click
            Dim Days As Integer
            Dim RateApplied As Double
            Dim SubTotal As Double
            Dim TaxRate As Double
            Dim TaxAmount As Double
            Dim OrderTotal As Double
    
            Try
                Days = CInt(txtDays.Text)
            Catch ex As FormatException
                MsgBox("Invalid Number of Days")
            End Try
    
            Try
                RateApplied = CDbl(txtRateApplied.Text)
            Catch ex As FormatException
                MsgBox("Invalid Amount for Rate Applied")
            End Try
    
            SubTotal = Days * RateApplied
            txtSubTotal.Text = FormatNumber(SubTotal)
    
            Try
                TaxRate = CDbl(txtTaxRate.Text)
            Catch ex As FormatException
                MsgBox("Invalid Tax Rate")
            End Try
    
            TaxAmount = SubTotal * TaxRate / 100
            txtTaxAmount.Text = FormatNumber(TaxAmount)
    
            OrderTotal = SubTotal + TaxAmount
            txtOrderTotal.Text = FormatNumber(OrderTotal)
    End Sub
  57. Return to the Order Processing form
  58. From the Printing section of the Toolbox, click PrintDocument and click the form
  59. In the Properties window, set its (Name) to docPrint and press Enter
  60. Under the form, double-click docPrint and implement its event as follows:
     
    Private Sub docPrint_PrintPage(ByVal sender As Object, _
                ByVal e As System.Drawing.Printing.PrintPageEventArgs) _
                                   Handles docPrint.PrintPage
            e.Graphics.DrawLine(New Pen(Color.Black, 2), 80, 90, 750, 90)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), 80, 93, 750, 93)
    
            Dim strDisplay As String = "Bethesda Car Rental"
            Dim fntString As System.Drawing.Font = _
    				New Font("Times New Roman", 28, _
                                                         FontStyle.Bold)
            e.Graphics.DrawString(strDisplay, fntString, _
                                Brushes.Black, 240, 100)
    
            strDisplay = "Car Rental Order"
            fntString = New System.Drawing.Font("Times New Roman", 22, _
                                FontStyle.Regular)
            e.Graphics.DrawString(strDisplay, fntString, _
                                Brushes.Black, 320, 150)
    
            e.Graphics.DrawLine(New Pen(Color.Black, 1), 80, 187, 750, 187)
            e.Graphics.DrawLine(New Pen(Color.Black, 2), 80, 190, 750, 190)
    
            fntString = New System.Drawing.Font("Times New Roman", 12, _
                        FontStyle.Bold)
            e.Graphics.DrawString("Receipt #:  ", fntString, _
                        Brushes.Black, 100, 220)
            fntString = New System.Drawing.Font("Times New Roman", 12, _
                        FontStyle.Regular)
            e.Graphics.DrawString(txtReceiptNumber.Text, fntString, _
                                          Brushes.Black, 260, 220)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), 100, 240, 380, 240)
    
            fntString = New System.Drawing.Font("Times New Roman", 12, _
                        FontStyle.Bold)
            e.Graphics.DrawString("Processed By:  ", fntString, _
                        Brushes.Black, 420, 220)
            fntString = New System.Drawing.Font("Times New Roman", 12, _
                        FontStyle.Regular)
            e.Graphics.DrawString(txtEmployeeName.Text, fntString, _
                                          Brushes.Black, 550, 220)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), 420, 240, 720, 240)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
    
            e.Graphics.FillRectangle(Brushes.Gray, _
                                     New Rectangle(100, 260, 620, 20))
            e.Graphics.DrawRectangle(Pens.Black, _
                                     New Rectangle(100, 260, 620, 20))
    
            e.Graphics.DrawString("Customer", fntString, _
                                          Brushes.White, 100, 260)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Driver's License #: ", fntString, _
                                          Brushes.Black, 100, 300)
            e.Graphics.DrawString("Name: ", fntString, _
                                         Brushes.Black, 420, 300)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(txtDrvLicNumber.Text, fntString, _
                                          Brushes.Black, 260, 300)
            e.Graphics.DrawString(txtCustomerName.Text, fntString, _
                                          Brushes.Black, 540, 300)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), 100, 320, 720, 320)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Address: ", fntString, _
                                          Brushes.Black, 100, 330)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(txtCustomerAddress.Text, fntString, _
                                          Brushes.Black, 260, 330)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), 100, 350, 720, 350)
    
            strDisplay = txtCustomerCity.Text & " " & _
                                 cbxCustomerStates.Text & " " & _
                                 txtCustomerZIPCode.Text
            fntString = New System.Drawing.Font("Times New Roman", _
           12, FontStyle.Regular)
            e.Graphics.DrawString(strDisplay, fntString, _
                                          Brushes.Black, 260, 360)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), 260, 380, 720, 380)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
    
            e.Graphics.FillRectangle(Brushes.Gray, _
                                     New Rectangle(100, 410, 620, 20))
            e.Graphics.DrawRectangle(Pens.Black, _
                                     New Rectangle(100, 410, 620, 20))
    
            e.Graphics.DrawString("Car Information", fntString, _
                                          Brushes.White, 100, 410)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Tag #: ", fntString, _
                                          Brushes.Black, 100, 450)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(txtTagNumber.Text, fntString, _
                                          Brushes.Black, 260, 450)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), 100, 470, 380, 470)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Year: ", fntString, _
                                          Brushes.Black, 420, 450)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(txtCarYear.Text, fntString, _
                                          Brushes.Black, 530, 450)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), 420, 470, 720, 470)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Make: ", fntString, _
                                          Brushes.Black, 100, 480)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(txtMake.Text, fntString, _
                                      Brushes.Black, 260, 480)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), 100, 500, 380, 500)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Model: ", fntString, _
                                      Brushes.Black, 420, 480)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(txtModel.Text, fntString, _
                                      Brushes.Black, 530, 480)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), 420, 500, 720, 500)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Car Condition: ", fntString, _
                                      Brushes.Black, 100, 510)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(cbxCarConditions.Text, fntString, _
                                      Brushes.Black, 260, 510)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), 100, 530, 380, 530)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Tank Level: ", fntString, _
                                      Brushes.Black, 420, 510)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(cbxTankLevels.Text, fntString, _
                                      Brushes.Black, 530, 510)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), 420, 530, 720, 530)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Mileage Start:", fntString, _
                                      Brushes.Black, 100, 540)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(txtMileageStart.Text, fntString, _
                                      Brushes.Black, 260, 540)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), _
                                100, 560, 380, 560)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Mileage End:", fntString, _
                              Brushes.Black, 420, 540)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(txtMileageEnd.Text, fntString, _
                                  Brushes.Black, 530, 540)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), _
                                420, 560, 720, 560)
    
            e.Graphics.FillRectangle(Brushes.Gray, _
                                     New Rectangle(100, 590, 620, 20))
            e.Graphics.DrawRectangle(Pens.Black, _
                                     New Rectangle(100, 590, 620, 20))
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Order Timing Information", fntString, _
                                  Brushes.White, 100, 590)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Start Date:", fntString, _
                                  Brushes.Black, 100, 620)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(dtpStartDate.Value.ToString("D"), _
                                  fntString, Brushes.Black, 260, 620)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), _
                                100, 640, 720, 640)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("End Date:", fntString, _
                                  Brushes.Black, 100, 650)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(dtpEndDate.Value.ToString("D"), _
    			      fntString, Brushes.Black, 260, 650)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), _
                                100, 670, 520, 670)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Days:", fntString, _
                                  Brushes.Black, 550, 650)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(txtDays.Text, fntString, _
                                  Brushes.Black, 640, 650)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), _
                                550, 670, 720, 670)
    
            e.Graphics.FillRectangle(Brushes.Gray, _
                                     New Rectangle(100, 700, 620, 20))
            e.Graphics.DrawRectangle(Pens.Black, _
                                     New Rectangle(100, 700, 620, 20))
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Order Evaluation", fntString, _
                                  Brushes.White, 100, 700)
    
            Dim fmtString As StringFormat = New StringFormat
            fmtString.Alignment = StringAlignment.Far
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Rate Applied:", fntString, _
                                  Brushes.Black, 100, 740)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(txtRateApplied.Text, fntString, _
                                  Brushes.Black, 300, 740, fmtString)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), _
                                100, 760, 380, 760)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Tax Rate:", fntString, _
                                  Brushes.Black, 420, 740)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(txtTaxRate.Text, fntString, _
                                  Brushes.Black, 640, 740, fmtString)
            e.Graphics.DrawString("%", fntString, _
                                  Brushes.Black, 640, 740)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), _
                                420, 760, 720, 760)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Sub-Total:", fntString, _
                                  Brushes.Black, 100, 770)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(txtSubTotal.Text, fntString, _
                                  Brushes.Black, 300, 770, fmtString)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), _
                                100, 790, 380, 790)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Tax Amount:", fntString, _
                                  Brushes.Black, 420, 770)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(txtTaxAmount.Text, fntString, _
                                  Brushes.Black, 640, 770, fmtString)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), _
                                420, 790, 720, 790)
    
            fntString = New Font("Times New Roman", 12, FontStyle.Bold)
            e.Graphics.DrawString("Order Total:", fntString, _
                                  Brushes.Black, 420, 800)
            fntString = New Font("Times New Roman", 12, FontStyle.Regular)
            e.Graphics.DrawString(txtOrderTotal.Text, fntString, _
                                  Brushes.Black, 640, 800, fmtString)
            e.Graphics.DrawLine(New Pen(Color.Black, 1), _
                                420, 820, 720, 820)
    End Sub
  61. Return to the Order Processing form
  62. From the Printing section of the Toolbox, click PrintDialog and click the form
  63. In the Properties window, change its Name to dlgPrint
  64. Still in the Properties windows, set its Document property to docPrint
  65. On the Order Processing form, double-click the Print button and implement its event as follows:
     
    Private Sub btnPrint_Click(ByVal sender As Object, _
                                   ByVal e As System.EventArgs) _
                                   Handles btnPrint.Click
        If dlgPrint.ShowDialog() = DialogResult.OK Then
            docPrint.Print()
        End If
    End Sub
  66. Return to the Order Processing form
  67. From the Printing section of the Toolbox, click PrintPreviewDialog and click the form
  68. In the Properties window, change its (Name) to dlgPrintPreview
  69. Still in the Properties windows, set its Document property to docPrint
  70. On the Order Processing form, double-click the Print Preview button
  71. Implement the event as follows:
     
    Private Sub btnPrintPreview_Click(ByVal sender As Object, _
                                      ByVal e As System.EventArgs) _
                                      Handles btnPrintPreview.Click
        dlgPrintPreview.ShowDialog()
    End Sub
  72. In the Solution Explorer, right-click Form1.vb and click Rename
  73. Type Central.vb and press Enter twice
  74. Design the form as follows:
     
    Bethesda Car Rental
    Control Text Name
    Button Customers &Rental Orders btnRentalOrders
    Button C&ars btnCars
    Button &Employees btnEmployees
    Button &Customers btnCustomers
    Button C&lose btnClose
  75. Double-click the Rental Orders button and implement its event as follows:
     
    Private Sub btnRentalOrders_Click(ByVal sender As System.Object, _
                                          ByVal e As System.EventArgs) _
                                          Handles btnRentalOrders.Click
        Dim dlgOrder As OrderProcessing = New OrderProcessing
        dlgOrder.ShowDialog()
    End Sub
  76. In the Class Name combo box, select btnCars
  77. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnCars_Click(ByVal sender As Object, _
                                  ByVal e As System.EventArgs) _
                                  Handles btnCars.Click
        Dim dlgCars As CarEditor = New CarEditor
        dlgCars.ShowDialog()
    End Sub
  78. In the Class Name combo box, select btnEmployees
  79. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnEmployees_Click(ByVal sender As Object, _
                                       ByVal e As System.EventArgs) _
                                       Handles btnEmployees.Click
        Dim dlgEmployees As Employees = New Employees
        dlgEmployees.ShowDialog()
    End Sub
  80. In the Class Name combo box, select btnCustomers
  81. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnCustomers_Click(ByVal sender As Object, _
                                       ByVal e As System.EventArgs) _
                                       Handles btnCustomers.Click
        Dim dlgCustomers As Customers = New Customers
        dlgCustomers.ShowDialog()
    End Sub
  82. In the Class Name combo box, select btnClose
  83. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnClose_Click(ByVal sender As Object, _
                                   ByVal e As System.EventArgs) _
                                   Handles btnClose.Click
        Close()
    End Sub
  84. Save all

Creating a Dictionary-Based Collection Class

To support dictionary-based lists, the .NET Framework provides various interfaces and classes. The interfaces allow you to create your own dictionary type of collection class. The classes allow you to directly create a dictionary-based list with an already built-in functionality. The NET Framework provides support for dictionary-based collections through two classes: Hashtable and SortedList. Both classes implement:

  • The IDictionary: This makes it possible to use the DictionaryEntry class to access a key/value item
  • The ICollection: This makes it possible to know the number of items in the list
  • The IEnumerable: This makes it possible to use the For Each loop to enumerate the members of the list
  • And the ICloneable interfaces.

The Hashtable class implements the ISerializable interface, which makes it possible for the list to be serialized. Still, the SortedList class is marked with the Serializable attribute, which makes it possible to file process its list.

The .NET Framework also provides dictionary-types through generic classes. From the System.Collections.Generic namespace, to create a dictionary type of collection, you can use either the Dictionary, the SortedDictionary, or the SortedList class. The System.Collections.Generic.Dictionary class is equivalent to the System.Collections.Hashtable class. The System.Collections.Generic.SortedList class is equivalent to the System.Collections.SortedList class. The System.Collections.Generic.SortedDictionary class is equivalent to the System.Collections.Generic.SortedList class with some differences in the way both classes deal with memory management.

If you decide to use either the System.Collections.Generic.Dictionary or the System.Collections.Generic.SortedList class, when declaring the variable, you must remember to specify the name of the class whose collection is being created.

Before using a dictionary-type of list, you can declare a variable using one of the constructors of the class. Here is an example:

Public Class Exercise

    Private Sub Exercise_Load(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles MyBase.Load
        Dim Students As Hashtable = new Hashtable
    End Sub
End Class

In this case, the primary list would be empty.

Practical LearningPractical Learning: Creating a Dictionary Variable

  1. In the Solution Explorer, right-click CarEditor.vb and click View Code
  2. In the top section of the file, import the IO and the Binary namespace then declare a variable as follows:
     
    Imports System.IO
    Imports System.Runtime.Serialization.Formatters.Binary
    
    Public Class CarEditor
    
        Private ListOfCars As Dictionary(Of String, Car)
    
  3. In the Class Name combo box, select (CarEditor Events)
  4. In the Method Name combo box, select Load and implement the event as follows:
     
    Private Sub CarEditor_Load(ByVal sender As Object, _
                                   ByVal e As System.EventArgs) _
                                   Handles Me.Load
            Dim vehicle As Car = New Car
            Dim StreamCars As FileStream
            Dim FormatterCars As BinaryFormatter = New BinaryFormatter
    
            REM This is the file that holds the list of items
            Dim Filename As String = "C:\Bethesda Car Rental\Cars.crs"
            lblPictureName.Text = "."
    
            If File.Exists(Filename) Then
                StreamCars = New FileStream(Filename, _
                                            FileMode.Open, _
                                            FileAccess.Read, _
                                            FileShare.Read)
                Try
                    REM Retrieve the list of cars
                    ListOfCars = CType(FormatterCars.Deserialize(StreamCars),  _
                                        Dictionary(Of String, Car))
                Finally
                    StreamCars.Close()
                End Try
            Else
                ListOfCars = New Dictionary(Of String, Car)
            End If
    End Sub
  5. In the Solution Explorer, right-click OrderProcessing.vb and click View Code
  6. Make the following changes:
     
    Imports System.IO
    Imports System.Runtime.Serialization.Formatters.Binary
    
    Public Class OrderProcessing
    
        Private ReceiptNumber As Integer
        Private ListOfRentalOrders As SortedList(Of Integer, RentalOrder)
  7. Save all

Adding Items to the Collection

To add an item to the list, you can call the Add() method. The syntax of the System.Collections.Hashtable.Add() and the System.Collections.SortedList.Add() methods is:

Public Overridable Sub Add(key As Object, value As Object)

The syntax of the System.Collections.Generic.Dictionary.Add(), the System.Collections.Generic.SortedDictionary.Add(), and the System.Collections.Generic.SortedList.Add() method is:

Public Sub Add(key As TKey, value As TValue)

As you can see, you must provide the key and the value as the first and second arguments to the method respectively. Here are examples of calling the Add() method:

Private Sub Exercise_Load(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles MyBase.Load
        Dim Students As Hashtable = New Hashtable

        Students.Add("Hermine", "Tolston")
        Students.Add("Patrick", "Donley")
End Sub

When calling the Add() method, you must provide a valid Key argument: it cannot be Nothing. For example, the following code would produce an error:

Private Sub Exercise_Load(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles MyBase.Load
        Dim Students As Hashtable = New Hashtable

        Students.Add("Hermine", "Tolston")
        Students.Add("Patrick", "Donley")
        Students.Add(Nothing, "Hannovers")
End Sub

This would produce:

Error

When adding the items to the list, as mentioned in our introduction, each key must be unique: you cannot have two exact keys. If you try adding a key that exists already in the list, the compiler would throw an ArgumentException exception. Based on this, the following code would not work because, on the third call, a "Patrick" key exists already:

Private Sub Exercise_Load(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles MyBase.Load
        Dim Students As Hashtable = New Hashtable

        Students.Add("Hermine", "Tolston")
        Students.Add("Patrick", "Donley")
        Students.Add("Chrissie", "Hannovers")
        Students.Add("Patrick", "Herzog")
End Sub

This would produce:

Error

This means that, when creating a dictionary type of list, you must define a scheme that would make sure that each key is unique among the other keys in the list.

Besides the Add() method, you can use the Item property to add an item to the collection. To do this, enter the Key in the parentheses of the property and assign it the desired Value. Here is an example:

Private Sub Exercise_Load(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles MyBase.Load
        Dim Students As Hashtable = New Hashtable

        Students.Add("Hermine", "Tolston")
        Students.Add("Patrick", "Donley")
        Students.Add("Chrissie", "Hannovers")
        Students.Add("Patricia", "Herzog")
        Students("Michael") = "Herlander"
End Sub

Practical LearningPractical Learning: Adding Items to the Collection

  1. In the Solution Explorer, right-click CarEditor.vb and click View Code
  2. In the Class Name combo box, select btnSubmit
  3. In the Method Name combo box, select Click and implement the Click event as follows:
     
    Private Sub btnSubmit_Click(ByVal sender As Object, _
                                ByVal e As System.EventArgs) _
                                Handles btnSubmit.Click
        Dim Vehicle As Car = New Car
        Dim StreamCars As FileStream
        Dim FormatterCars As BinaryFormatter = New BinaryFormatter
    
        Directory.CreateDirectory("C:\Bethesda Car Rental")
        Dim strFilename As String = "C:\Bethesda Car Rental\Cars.crs"
    
        If txtTagNumber.Text.Length = 0 Then
            MsgBox("You must enter the car's tag number")
            Exit Sub
        End If
    
        If txtMake.Text.Length = 0 Then
            MsgBox("You must specify the car's manufacturer")
            Exit Sub
        End If
    
        If txtModel.Text.Length = 0 Then
            MsgBox("You must enter the model of the car")
            Exit Sub
        End If
    
        If txtYear.Text.Length = 0 Then
           MsgBox("You must enter the year of the car")
           Exit Sub
        End If
    
        REM Create a car
        Vehicle.Make = txtMake.Text
        Vehicle.Model = txtModel.Text
        Vehicle.Year = CInt(txtYear.Text)
        Vehicle.Category = cbxCategories.Text
        Vehicle.HasCDPlayer = chkCDPlayer.Checked
        Vehicle.HasDVDPlayer = chkDVDPlayer.Checked
        Vehicle.IsAvailable = chkAvailable.Checked
    
        REM Call the Add method of our collection class to add the car
        ListOfCars.Add(txtTagNumber.Text, Vehicle)
    
        REM Save the list
        StreamCars = New FileStream(strFilename, _
                                 FileMode.Create, _
                                 FileAccess.Write, _
                                 FileShare.Write)
    
        Try
            FormatterCars.Serialize(StreamCars, ListOfCars)
    
            If lblPictureName.Text.Length <> 0 Then
                Dim PictureFile As FileInfo = New FileInfo(lblPictureName.Text)
                PictureFile.CopyTo("C:\Bethesda Car Rental\" & _
                                  txtTagNumber.Text & _
                                  PictureFile.Extension)
            End If
    
            txtTagNumber.Text = ""
            txtMake.Text = ""
            txtModel.Text = ""
            txtYear.Text = ""
            cbxCategories.Text = "Economy"
            chkCDPlayer.Checked = False
            chkDVDPlayer.Checked = False
            chkAvailable.Checked = False
            lblPictureName.Text = "."
            pbxCar.Image = Nothing
    
        Finally
            StreamCars.Close()
        End Try
    End Sub
  4. In the Solution Explorer, right-click Customers.vb and click View Code
  5. Make the following changes:
     
    Imports System.IO
    Imports System.Runtime.Serialization.Formatters.Binary
    
    Public Class Customers
        Private ListOfCustomers As Dictionary(Of String, Customer)
    
        Private Sub ShowCustomers()
    
        End Sub
    
        Private Sub Customers_Load(ByVal sender As Object, _
                                   ByVal e As System.EventArgs) _
                                   Handles Me.Load
            Dim StreamCustomers As FileStream
            ListOfCustomers = New Dictionary(Of String, Customer)
            Dim FormatterCustomers As BinaryFormatter = New BinaryFormatter
    
            REM This is the file that holds the list of parts
            Dim strFilename As String = "C:\Bethesda Car Rental\Customers.crc"
    
            If File.Exists(strFilename) Then
                StreamCustomers = New FileStream(strFilename, _
                                                         FileMode.Open, _
                                                         FileAccess.Read, _
                                                         FileShare.Read)
    
                Try
                    REM Retrieve the list of employees from file
                    ListOfCustomers = _
    		    CType(FormatterCustomers.Deserialize(StreamCustomers),  _
                              Dictionary(Of String, Customer))
                Finally
                    StreamCustomers.Close()
                End Try
            End If
    
            ShowCustomers()
        End Sub
    End Class
  6. In the Class Name combo box, select btnNewCustomer
  7. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnNewCustomer_Click(ByVal sender As Object, _
                                         ByVal e As System.EventArgs) _
                                         Handles btnNewCustomer.Click
            Dim bcrStream As FileStream
            Dim bcrBinary As BinaryFormatter = New BinaryFormatter
            Dim Editor As CustomerEditor = New CustomerEditor
    
            Directory.CreateDirectory("C:\Bethesda Car Rental")
    
            If Editor.ShowDialog() = DialogResult.OK Then
    
                If Editor.txtDrvLicNbr.Text = "" Then
    
                    MsgBox("You must provide the driver's " & _
                                    "license number of the customer")
                    Exit Sub
                End If
    
                If Editor.txtFullName.Text = "" Then
                    MsgBox("You must provide the employee's full name")
                    Exit Sub
                End If
    
                Dim strFilename As String = "C:\Bethesda Car Rental\Customers.crc"
    
                Dim Cust As Customer = New Customer
    
                Cust.FullName = Editor.txtFullName.Text
                Cust.Address = Editor.txtAddress.Text
                Cust.City = Editor.txtCity.Text
                Cust.State = Editor.cbxStates.Text
                Cust.ZIPCode = Editor.txtZIPCode.Text
                ListOfCustomers.Add(Editor.txtDrvLicNbr.Text, Cust)
    
                bcrStream = New FileStream(strFilename, _
                                           FileMode.Create, _
                                           FileAccess.Write, _
                                           FileShare.Write)
                bcrBinary.Serialize(bcrStream, ListOfCustomers)
                bcrStream.Close()
    
                ShowCustomers()
            End If
    End Sub
  8. In the Solution Explorer, right-click Employees.vb and click View Code
  9. Change the file as follows:
     
    Imports System.IO
    Imports System.Runtime.Serialization.Formatters.Binary
    
    Public Class Employees
        Private ListOfEmployees As SortedDictionary(Of String, Employee)
    
        Private Sub ShowEmployees()
    
        End Sub
    
        Private Sub Employees_Load(ByVal sender As Object, _
                                   ByVal e As System.EventArgs) _
                                   Handles Me.Load
            Dim StreamEmployees As FileStream
            ListOfEmployees = New SortedDictionary(Of String, Employee)
            Dim FormatterEmployees As BinaryFormatter = New BinaryFormatter
    
            REM This is the file that holds the list of parts
            Dim strFilename As String = "C:\Bethesda Car Rental\Employees.cre"
    
            If File.Exists(strFilename) Then
                StreamEmployees = New FileStream(strFilename, _
                                                 FileMode.Open, _
                                                 FileAccess.Read, _
                                                 FileShare.Read)
    
                Try
                    REM Retrieve the list of employees from file
                    ListOfEmployees = _
                        CType(FormatterEmployees.Deserialize(StreamEmployees),  _
                              SortedDictionary(Of String, Employee))
                Finally
                    StreamEmployees.Close()
                End Try
            End If
    
            ShowEmployees()
        End Sub
    End Class
  10. In the Class Name combo box, select btnNewEmployee
  11. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnNewEmployee_Click(ByVal sender As Object, _
                                         ByVal e As System.EventArgs) _
                                         Handles btnNewEmployee.Click
            Dim Editor As EmployeeEditor = New EmployeeEditor
            Dim bcrBinary As BinaryFormatter = New BinaryFormatter
    
            REM If this folder doesn't exist, create it
            Directory.CreateDirectory("C:\Bethesda Car Rental")
    
            REM Display the Employee Editor dialog box 
            REM and find out if the user clicked OK after using it
            If Editor.ShowDialog() = DialogResult.OK Then
                REM If the user didn't provide an employee number
                REM don't do anything
                If Editor.txtEmployeeNumber.Text = "" Then
                    MsgBox("You must provide an employee number")
                    Exit Sub
                End If
    
                REM If the user didn't provide a last name,
                REM don't do anything
                If Editor.txtLastName.Text = "" Then
                    MsgBox("You must provide the employee's last name")
                    Exit Sub
                End If
    
                REM Ger a reference to the Employees file if it exists
                Dim strFilename As String = "C:\Bethesda Car Rental\Employees.cre"
    
                REM Get the values that the user entered in the dialog box
                Dim Empl As Employee = New Employee
    
                REM Create an employee from those values
                Empl.FirstName = Editor.txtFirstName.Text
                Empl.LastName = Editor.txtLastName.Text
                Empl.Title = Editor.txtTitle.Text
                Empl.HourlySalary = CDbl(Editor.txtHourlySalary.Text)
    
                REM Add the employee to the main list
                ListOfEmployees.Add(Editor.txtEmployeeNumber.Text, Empl)
    
                REM Save the current list of employees
                Dim bcrStream As FileStream = New FileStream(strFilename, _
                                                       FileMode.Create, _
                                                       FileAccess.Write, _
                                                       FileShare.Write)
                bcrBinary.Serialize(bcrStream, ListOfEmployees)
                bcrStream.Close()
    
                REM Display the list of employees
                ShowEmployees()
            End If
    End Sub
  12. Save all

Accessing the Items of a Dictionary-Type of List

Although, or because, the key and value are distinct, to consider their combination as a single object, if you are using either the System.Collections.Hasthtable or the System.Collections.SortedList class, the .NET Framework provides the DictionaryEntry structure. To access an item, you can use the For Each loop to visit each item.

To support the For Each loop, the System.Collections.Hashtable and the System.Collections.SortedList classes implement the IEnumerable.GetEnumerator() method. In this case, the item is of type DictionaryEntry: it contains a Key and a Value in combination.

The DictionaryEntry structure contains two properties named Key and Value to identify the components of a combination. Here is an example:

Private Sub Exercise_Load(ByVal sender As System.Object, _
                          ByVal e As System.EventArgs) _
                          Handles MyBase.Load
        Dim Students As Hashtable = New Hashtable

        Students.Add("Hermine", "Tolston")
        Students.Add("Patrick", "Donley")
        Students.Add("Chrissie", "Hannovers")
        Students.Add("Patricia", "Herzog")
        Students("Michael") = "Herlander"

        For Each Entry As DictionaryEntry In Students
            lbxStudents.Items.Add(Entry.Key & " " & Entry.Value)
        Next
End Sub

This would produce:

Hash Table

If you are using a generic class, the .NET Framework provides the KeyValuePair structure that follows the same functionality as the System.Collections.DictionaryEntry structure, except that you must apply the rules of generic classes.

Practical LearningPractical Learning: Enumerating the Members of a Collection

  1. In the Solution Explorer, right-click OrderProcessing.vb and click View Code
  2. In the Class Name combo box, select txtDrvLicNumber
  3. In the Method Name combo box, select Leave and implement the event as follows:
     
    Private Sub txtDrvLicNumber_Leave(ByVal sender As Object, _
                                          ByVal e As System.EventArgs) _
                                          Handles txtDrvLicNumber.Leave
            Dim Renter As Customer
            Dim strDrvLicNumber As String = txtDrvLicNumber.Text
            Dim FormatterCustomers As BinaryFormatter = New BinaryFormatter
            Dim ListOfCustomers As Dictionary(Of String, Customer) = _
                    New Dictionary(Of String, Customer)
    
            REM Make sure the user entered a driver's license number
            If strDrvLicNumber.Length = 0 Then
                MsgBox("You must enter the renter's " & _
                                "driver's license number")
                txtDrvLicNumber.Focus()
                Exit Sub
            End If
    
            REM Get a reference to the file that holds the list of customers
            Dim strFilename As String = "C:\Bethesda Car Rental\Customers.crc"
    
            REM Find out if that file exists
            If File.Exists(strFilename) Then
                REM If there is a file of customers, open it
                Dim StreamCustomers As FileStream = New FileStream(strFilename, _
                                                              FileMode.Open, _
                                                              FileAccess.Read, _
                                                              FileShare.Read)
    
                Try
                    REM Retrieve the customers from the file and store 
                    REM them in the ListOfCustomers variable
                    ListOfCustomers = _
                        CType(FormatterCustomers.Deserialize(StreamCustomers),  _
                              Dictionary(Of String, Customer))
                    REM Check the list of customers to find out if there is a customer 
                    REM who has the driver's license number that the user entered
                    If ListOfCustomers.ContainsKey(strDrvLicNumber) = True Then
                        REM If so, get the information about that customer
                        REM and display that information on the Order Processing form
                        For Each Cust As KeyValuePair(Of String, Customer) In ListOfCustomers
                            If Cust.Key = strDrvLicNumber Then
                                Renter = Cust.Value
                                txtCustomerName.Text = Renter.FullName
                                txtCustomerAddress.Text = Renter.Address
                                txtCustomerCity.Text = Renter.City
                                cbxCustomerStates.Text = Renter.State
                                txtCustomerZIPCode.Text = Renter.ZIPCode
                            End If
                        Next
                    Else
                        REM If there is no customer with that driver's license number
                        REM there is nothing to display...
                        txtCustomerName.Text = ""
                        txtCustomerAddress.Text = ""
                        txtCustomerCity.Text = ""
                        cbxCustomerStates.Text = ""
                        txtCustomerZIPCode.Text = ""
                        REM ... and let the user know
                        MsgBox("There is no customer with that driver's " & _
                                    "license number in our database")
                        Exit Sub
                    End If
                Finally
                    StreamCustomers.Close()
                End Try
            End If
    End Sub
  4. Access the Employees.vb file and implement the ShowEmployees() procedure as follows:
     
    Private Sub ShowEmployees()
            If ListOfEmployees.Count = 0 Then
                Exit Sub
            End If
    
            REM Before displaying the employees, empty the list view
            lvwEmployees.Items.Clear()
            REM This variable will allow us to identify the odd and even indexes
            Dim Counter As Integer = 1
    
            REM Use the KeyValuePair class to visit each key/value item
            For Each kvp As KeyValuePair(Of String, Employee) In ListOfEmployees
                Dim lviEmployee As ListViewItem = New ListViewItem(kvp.Key)
                Dim empl As Employee = kvp.Value
    
                lviEmployee.SubItems.Add(empl.FirstName)
                lviEmployee.SubItems.Add(empl.LastName)
                lviEmployee.SubItems.Add(empl.FullName)
                lviEmployee.SubItems.Add(empl.Title)
                lviEmployee.SubItems.Add(FormatNumber(empl.HourlySalary))
    
                If Counter Mod 2 = 0 Then
                    lviEmployee.BackColor = Color.FromArgb(255, 128, 0)
                    lviEmployee.ForeColor = Color.White
                Else
    
                    lviEmployee.BackColor = Color.FromArgb(128, 64, 64)
                    lviEmployee.ForeColor = Color.White
                End If
    
                lvwEmployees.Items.Add(lviEmployee)
                Counter = Counter + 1
            Next
    End Sub
  5. Access the Customers.vb file and implement the ShowCustomers() method as follows:
     
    Private Sub ShowCustomers()
            Dim Counter As Integer
            If ListOfCustomers.Count = 0 Then
                Exit Sub
            End If
    
            lvwCustomers.Items.Clear()
            Counter = 1
    
            For Each kvp As KeyValuePair(Of String, Customer) In ListOfCustomers
    
                Dim lviCustomer As ListViewItem = New ListViewItem(kvp.Key)
    
                Dim Cust As Customer = kvp.Value
    
                lviCustomer.SubItems.Add(Cust.FullName)
                lviCustomer.SubItems.Add(Cust.Address)
                lviCustomer.SubItems.Add(Cust.City)
                lviCustomer.SubItems.Add(Cust.State)
                lviCustomer.SubItems.Add(Cust.ZIPCode)
    
                If Counter Mod 2 = 0 Then
                    lviCustomer.BackColor = Color.Navy
                    lviCustomer.ForeColor = Color.White
                Else
                    lviCustomer.BackColor = Color.Blue
                    lviCustomer.ForeColor = Color.White
                End If
    
                lvwCustomers.Items.Add(lviCustomer)
                Counter = Counter + 1
            Next
    End Sub
  6. Execute the application
  7. Click the Cars button and create the cars
     
    Bethesda Car Rental - Car Editor
    Cars
  8. Close the Car Editor form
  9. Click the Customers button then click the New Customer button continually and create a few customers as follows:
     
    Driver's Lic. # State Full Name Address City ZIP Code
    M-505-862-575 MD Lynda Melman 4277 Jamison Avenue Silver Spring 20904
    379-82-7397 DC John Villard 108 Hacken Rd NE Washington 20012
    J-938-928-274 MD Chris Young 8522 Aulage Street Rockville 20852
    497-22-0614 PA Pamela Ulmreck 12075 Famina Rd Blain 17006
    922-71-8395 VA Helene Kapsco 806 Hyena Drive Alexandria 22231
    C-374-830-422 MD Hermine Crasson 6255 Old Georgia Ave Silver Spring 20910
    836-55-2279 NY Alan Pastore 4228 Talion Street Amherst 14228
    397-59-7487 TN Phillis Buster 724 Cranston Circle Knoxville 37919
    115-80-2957 FL Elmus Krazucki 808 Rasters Ave Orlando 32810
    294-90-7744 VA Helena Weniack 10448 Great Pollard Hwy Arlington 22232
    Customers
  10. Close the Customers form

The Hashtable/SortedList and the Dictionary/SortedList Difference

If you use the System.Collections.Hashtable or the System.Collections.Generic.Dictionary class to create your list, the items are cumulatively added to the collection every time you call the Add() method or when you use the Item property to add an item. In our introduction, we saw that the optional third rule of a dictionary type of list is that the list be sorted based on the key. To spare you the hassle of manually taking care of this, the alternative is to use the SortedList class.

Whenever a new item is added to a System.Collections.SortedList variable, a System.Collections.Generic.SortedDictionary variable, or a System.Collections.Generic.SortedList variable, the list is rearranged so the collection can be sorted in either alphabetical or chronological order based on the keys. This means that, if you want your list to be logically arranged by the keys, use one of these Sorted classes to create the collection.

Practical LearningPractical Learning: Sorting a Dictionary the Members of a Collection

  1. On the Central form, click the Employees button
  2. Create a few employees as follows:
     
    Employee # First Name Last Name Title Hourly Salary
    62-845 Patricia Katts General Manager 42.25
    92-303 Henry Larson Sales Representative 12.50
    25-947 Gertrude Monay Sales Representative 14.05
    73-947 Helene Sandt Intern 8.85
    40-508 Melanie Karron Sales Representative 12.75
    22-580 Ernest Chisen Sales Manager 22.95
    20-308 Melissa Roberts Administrative Assistant 15.45
    Employees
    Bethesda Car Rental: Employees
  3. Notice that the list of employees is automatically sorted based on the employees numbers.
    Close the forms and return to your programming environment

The Keys and the Values of a Collection

After adding one or more items to the list, they are stored in two collections. The keys are stored in a collection represented by a property named Keys. The values are stored in the Values property. In the System.Collections classes, the Keys and the Values properties are of type ICollection.

To assist you with managing the keys of their collections, the System.Collections.Generic.Dictionary, the System.Collections.Generic.SortedDictionary, and the System.Collections.Generic.SortedList classes are equipped with a nested class named KeyCollection. KeyCollection is a serializable generic class that implements the ICollection interface. The only real functionalities of the nested KeyCollection class are its ability to know the current number of items in the list and the ability to enumerate the members of the collection through a For Each loop.

To assist you with the values of their lists, the System.Collections.Generic.Dictionary, the System.Collections.Generic.SortedDictionary, and the System.Collections.Generic.SortedList classes are equipped with the nested ValueCollection. The ValueCollection serializable class implements the ICollection and the IEnumerable interfaces. The functionality of the ValueCollection class is the same as its counterpart of the System.Collections namespace.

Practical LearningPractical Learning: Using the Keys of a Collection

  1. In the Solution Explorer, right-click OrderProcessing.vb and click View Code
  2. In the Class Name combo box, select btnNewRentalOrder
  3. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnNewRentalOrder_Click(ByVal sender As Object, _
                                            ByVal e As System.EventArgs) _
                                            Handles btnNewRentalOrder.Click
            Dim StreamRentalOrders As FileStream
    
            txtEmployeeNumber.Text = ""
            txtEmployeeName.Text = ""
            txtDrvLicNumber.Text = ""
            txtCustomerName.Text = ""
            txtCustomerAddress.Text = ""
            txtCustomerCity.Text = ""
            cbxCustomerStates.Text = ""
            txtCustomerZIPCode.Text = ""
            txtTagNumber.Text = ""
            cbxCarConditions.Text = ""
            txtMake.Text = ""
            txtModel.Text = ""
            txtCarYear.Text = ""
            cbxTankLevels.Text = "Empty"
            txtMileageStart.Text = "0"
            txtMileageEnd.Text = "0"
            dtpStartDate.Value = DateTime.Today
            dtpEndDate.Value = DateTime.Today
            txtDays.Text = ""
            cbxOrderStatus.Text = ""
            txtRateApplied.Text = "0.00"
            txtSubTotal.Text = "0.00"
            txtTaxRate.Text = "7.75"
            txtTaxAmount.Text = "0.00"
            txtOrderTotal.Text = "0.00"
    
            Dim FormatterRentalOrders As BinaryFormatter = New BinaryFormatter()
    
            Dim Filename As String = "C:\Bethesda Car Rental\RentalOrders.cro"
    
            If File.Exists(Filename) Then
                StreamRentalOrders = New FileStream(Filename, _
                                                    FileMode.Open, _
                                                    FileAccess.Read, _
                                                    FileShare.Read)
    
                Try
                    ListOfRentalOrders = _
                        CType(FormatterRentalOrders.Deserialize(StreamRentalOrders),  _
                              SortedList(Of Integer, RentalOrder))
                    ReceiptNumber = _
                        ListOfRentalOrders.Keys(ListOfRentalOrders.Count - 1) + 1
                Finally
                    StreamRentalOrders.Close()
                End Try
    
            Else
                ReceiptNumber = 100001
                ListOfRentalOrders = New SortedList(Of Integer, RentalOrder)
            End If
    
            txtReceiptNumber.Text = ReceiptNumber
    End Sub
  4. In the Class name combo box, select (OrderProcessing Events)
  5. In the Method Name combo box, select Load and implement the event as follows:
     
    Private Sub OrderProcessing_Load(ByVal sender As Object, _
                                     ByVal e As System.EventArgs) _
                                     Handles Me.Load
        btnNewRentalOrder_Click(sender, e)
    End Sub
  6. Return to the Order Processing form

Checking the Existence of an Item

Locating an item in a dictionary type of list consists of looking for either a key, a value, or a combination of Key=Value. The Hashtable, the Dictionary, and the SortedList classes are equipped to handle these operations with little effort on your part. If you know the key of an item but want to find a value, you can use the Item property because it produces it. Here is an example:

Private Sub Exercise_Load(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles MyBase.Load
        Dim Students As Hashtable = New Hashtable

        Students.Add("Hermine", "Tolston")
        Students.Add("Patrick", "Donley")
        Students.Add("Chrissie", "Hannovers")
        Students.Add("Patricia", "Herzog")
        Students("Michael") = "Herlander"

        For Each Entry As DictionaryEntry In Students
            lbxStudents.Items.Add(Entry.Key & " " & Entry.Value)
        Next

        Dim Value As String = CType(Students("Chrissie"), String)
        MsgBox("The value of the Chrissie key is " & Value)
End Sub

This would produce:

Message Box

To find out whether a Key/Value item exists in the list, if you are using one of the classes from the System.Collections namespace, you can call the System.Collections.Hashtable.Contains() or the System.Collections.SortedList.Contains() method. Its syntax is:

Public Overridable Function Contains(key As Object) As Boolean

To look for an item, you pass its key as argument to this method. Here is an example:

Private Sub Exercise_Load(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles MyBase.Load
        Dim Students As Hashtable = New Hashtable

        Students.Add("Hermine", "Tolston")
        Students.Add("Patrick", "Donley")
        Students.Add("Chrissie", "Hannovers")
        Students.Add("Patricia", "Herzog")
        Students("Michael") = "Herlander"

        For Each Entry As DictionaryEntry In Students
            lbxStudents.Items.Add(Entry.Key & " " & Entry.Value)
        Next

        Dim Found As Boolean = Students.Contains("Chrissie")

        If Found = True Then
            MsgBox("The list contains an item " & _
                            "whose key is Chrissie")
        Else
            MsgBox("The list doesn't contain an " & _
                            "item whose key is Chrissie")
        End If

        Found = Students.Contains("James")

        If Found = True Then
            MsgBox("The list contains an item " & _
                        "whose key is James")
        Else
            MsgBox("The list doesn't contain an " & _
                        "item whose key is James")
        End If
End Sub

This would produce:

Message Box
 

Checking the Existence of a Key

We have seen that the System.Collections.Hashtable.Contains() and the System.Collections.SortedList.Contains() methods allow you to find out whether a collection contains a certain specific key. An alternative is to call a method named ContainsKey.

The syntax of the System.Collections.Hashtable.ContainsKey() and the System.Collections.SortedList.ContainsKey() method is:

Public Overridable Function ContainsKey(key As Object) As Boolean

The syntax of the System.Collections.Generic.Dictionary.ContainsKey() and the System.Collections.Generic.SortedList.ContainsKey() method is:

Public Function ContainsKey(key As TKey) As Boolean

Practical LearningPractical Learning: Checking the Existence of a Key

  1. In the Class Name combo box, select btnSave
  2. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnSave_Click(ByVal sender As Object, _
                                  ByVal e As System.EventArgs) _
                                  Handles btnSave.Click
            If txtReceiptNumber.Text = "" Then
                MsgBox("The receipt number is missing")
                Exit Sub
            End If
    
            REM Don't save this rental order if we don't
            REM know who processed it
            If txtEmployeeNumber.Text = "" Then
                MsgBox("You must enter the employee number or the " & _
                            "clerk who processed this order.")
                Exit Sub
            End If
    
            REM Don't save this rental order if we don't
            REM know who is renting the car
            If txtDrvLicNumber.Text = "" Then
                MsgBox("You must specify the driver's license number " & _
                            "of the customer who is renting the car")
                Exit Sub
            End If
    
            REM Don't save the rental order if we don't
            REM know what car is being rented
            If txtTagNumber.Text = "" Then
                MsgBox("You must enter the tag number " & _
                            "of the car that is being rented")
                Exit Sub
            End If
    
            REM Create a rental order based on the information on the form
            Dim CurrentOrder As RentalOrder = New RentalOrder
    
            CurrentOrder.EmployeeNumber = txtEmployeeNumber.Text
            CurrentOrder.OrderStatus = cbxOrderStatus.Text
            CurrentOrder.CarTagNumber = txtTagNumber.Text
            CurrentOrder.CustomerDrvLicNbr = txtDrvLicNumber.Text
            CurrentOrder.CustomerName = txtCustomerName.Text
            CurrentOrder.CustomerAddress = txtCustomerAddress.Text
            CurrentOrder.CustomerCity = txtCustomerCity.Text
            CurrentOrder.CustomerState = cbxCustomerStates.Text
            CurrentOrder.CustomerZIPCode = txtCustomerZIPCode.Text
            CurrentOrder.CarCondition = cbxCarConditions.Text
            CurrentOrder.TankLevel = cbxTankLevels.Text
    
            Try
                CurrentOrder.MileageStart = CInt(txtMileageStart.Text)
            Catch ex As FormatException
                MsgBox("Invalid mileage start value")
            End Try
    
            Try
                CurrentOrder.MileageEnd = CInt(txtMileageEnd.Text)
            Catch ex As FormatException
                MsgBox("Invalid mileage End value")
            End Try
    
            Try
            CurrentOrder.DateStart = dtpStartDate.Value;
            Catch ex As FormatException
                MsgBox("Invalid start date")
            End Try
    
            Try
                    CurrentOrder.DateEnd = dtpEndDate.Value;
            Catch ex As FormatException
                MsgBox("Invalid End date")
            End Try
    
            Try
                CurrentOrder.Days = CInt(txtDays.Text)
            Catch ex As FormatException
                MsgBox("Invalid number of days")
            End Try
    
            Try
                CurrentOrder.RateApplied = CDbl(txtRateApplied.Text)
            Catch ex As FormatException
                MsgBox("Invalid rate value")
            End Try
    
            CurrentOrder.SubTotal = CDbl(txtSubTotal.Text)
    
            Try
                CurrentOrder.TaxRate = CDbl(txtTaxRate.Text)
            Catch ex As FormatException
                MsgBox("Inavlid tax rate")
            End Try
    
            CurrentOrder.TaxAmount = CDbl(txtTaxAmount.Text)
            CurrentOrder.OrderTotal = CDbl(txtOrderTotal.Text)
            REM The rental order is ready
    
            REM Get the receipt number from its text box
            Try
                ReceiptNumber = CInt(txtReceiptNumber.Text)
            Catch ex As FormatException
                MsgBox("You must provide a receipt number")
            End Try
    
            REM Get the list of rental orders and 
            REM check if there is already one with the current receipt number
            REM If there is already a receipt number like that...
            If ListOfRentalOrders.ContainsKey(ReceiptNumber) = True Then
                REM Simply update its value
                ListOfRentalOrders(ReceiptNumber) = CurrentOrder
            Else
                REM If there is no order with that receipt,
                REM then create a new rental order
                ListOfRentalOrders.Add(ReceiptNumber, CurrentOrder)
            End If
    
            REM The list of rental orders
            Dim strFilename As String = "C:\Bethesda Car Rental\RentalOrders.cro"
            Dim bcrStream As FileStream = New FileStream(strFilename, _
                                                      FileMode.Create, _
                                                      FileAccess.Write, _
                                                      FileShare.Write)
            Dim bcrBinary As BinaryFormatter = New BinaryFormatter
    
            Try
                bcrBinary.Serialize(bcrStream, ListOfRentalOrders)
            Finally
    
                bcrStream.Close()
            End Try
    End Sub
  3. Save the file

Checking the Existence of a Value

To find out whether a particular value exists in the list, you can call the ContainsValue() method. The syntax of the System.Collections.Hashtable.ContainsValue() and the System.Collections.SortedList.ContainsValue() method is::

Public Overridable Function ContainsValue(value As Object) As Boolean

The syntax of the System.Collections.Generic.Dictionary.ContainsValue() and the System.Collections.Generic.SortedList.ContainsValue() method is:

Public Function ContainsValue(value As TValue) As Boolean

Getting the Value of a Key

The ContainsKey() method allows you to only find out whether a dictionary-based collection contains a certain key. It does not identify that key and it does not give any significant information about that key, except its existence. In some operations, first you may want to find out if the collection contains a certain key. Second, if that key exists, you may want to get its corresponding value.

To assist you with both checking the existence of a key and getting its corresponding value, the generic Dictionary, SortedDictionary, and SortedList classes are equipped with a method named TryGetValue. Its syntax is:

Public Function TryGetValue(key As TKey, _
	<OutAttribute> ByRef value As TValue) As Boolean

When calling this method, the first argument must be the key to look for. If that key is found, the method returns its corresponding value as the second argument passed by reference.

Practical LearningPractical Learning: Getting the Value of a Key

  1. In the Class Name combo box, select txtEmployeeNumber
  2. In the Method Name combo box, select Leave and implement the event as follows:
     
    Private Sub txtEmployeeNumber_Leave(ByVal sender As Object, _
                                            ByVal e As System.EventArgs) _
                                            Handles txtEmployeeNumber.Leave
            Dim Clerk As Employee = Nothing
            Dim StreamEmployees As FileStream
            Dim strEmployeeNumber As String = txtEmployeeNumber.Text
    
            If strEmployeeNumber.Length = 0 Then
                MsgBox("You must enter the employee's number")
                txtEmployeeNumber.Focus()
                Exit Sub
            End If
    
            Dim ListOfEmployees As SortedDictionary(Of String, Employee) = _
                        New SortedDictionary(Of String, Employee)
            Dim FormatterEmployees As BinaryFormatter = New BinaryFormatter
    
            Dim strFilename As String = "C:\Bethesda Car Rental\Employees.cre"
    
            If File.Exists(strFilename) Then
                StreamEmployees = New FileStream(strFilename, _
                                                         FileMode.Open, _
                                                         FileAccess.Read, _
                                                         FileShare.Read)
                Try
                    REM Retrieve the list of employees
                    ListOfEmployees = CType(FormatterEmployees.Deserialize(StreamEmployees),  _
                                            SortedDictionary(Of String, Employee))
    
                    If ListOfEmployees.TryGetValue(strEmployeeNumber, Clerk) Then
                        txtEmployeeName.Text = Clerk.FullName
                    Else
                        txtEmployeeName.Text = ""
                        MsgBox("There is no employee with that number")
                        Exit Sub
                    End If
                Finally
                    StreamEmployees.Close()
                End Try
            End If
    End Sub
  3. In the Class Name combo box, select txtTagNumber
  4. In the Method Name combo box, select Leave and implement the event as follows:
     
    Private Sub txtTagNumber_Leave(ByVal sender As Object, _
                                       ByVal e As System.EventArgs) _
                                       Handles txtTagNumber.Leave
            Dim SelectedCar As Car
            Dim StreamCars As FileStream
            Dim strTagNumber As String = txtTagNumber.Text
            Dim ListOfCars As Dictionary(Of String, Car) = _
                          New Dictionary(Of String, Car)
            Dim FormatterCars As BinaryFormatter = New BinaryFormatter()
    
            If strTagNumber.Length = 0 Then
                MsgBox("You must enter the car's tag number")
                txtTagNumber.Focus()
                Exit Sub
            End If
    
            Dim strFilename As String = "C:\Bethesda Car Rental\Cars.crs"
    
            If File.Exists(strFilename) Then
                StreamCars = New FileStream(strFilename, _
                                            FileMode.Open, _
                                            FileAccess.Read, _
                                            FileShare.Read)
                Try
                    REM Retrieve the list of employees from file
                    ListOfCars = CType(FormatterCars.Deserialize(StreamCars),  _
                                       Dictionary(Of String, Car))
    
                    If ListOfCars.TryGetValue(strTagNumber, SelectedCar) Then
                        txtMake.Text = SelectedCar.Make
                        txtModel.Text = SelectedCar.Model
                        txtCarYear.Text = SelectedCar.Year
                    Else
                        txtMake.Text = ""
                        txtModel.Text = ""
                        txtCarYear.Text = ""
                        MsgBox("There is no car with that tag " & _
                                    "number in our database")
                        Exit Sub
                    End If
                Finally
                    StreamCars.Close()
                End Try
            End If
    End Sub
  5. In the Class Name combo box, select btnOpen
  6. In the Method Name combo box, select Click and implement the event as follows:
      
    Private Sub btnOpen_Click(ByVal sender As Object, _
                                  ByVal e As System.EventArgs) _
                                  Handles btnOpen.Click
            Dim Order As RentalOrder = Nothing
    
            If txtReceiptNumber.Text = "" Then
                MsgBox("You must enter a receipt number")
                Exit Sub
            End If
    
            ReceiptNumber = CInt(txtReceiptNumber.Text)
    
            If ListOfRentalOrders.TryGetValue(ReceiptNumber, Order) Then
                txtEmployeeNumber.Text = Order.EmployeeNumber
                txtEmployeeNumber_Leave(sender, e)
                cbxOrderStatus.Text = Order.OrderStatus
                txtTagNumber.Text = Order.CarTagNumber
                txtTagNumber_Leave(sender, e)
                txtDrvLicNumber.Text = Order.CustomerDrvLicNbr
                txtCustomerName.Text = Order.CustomerName
                txtCustomerAddress.Text = Order.CustomerAddress
                txtCustomerCity.Text = Order.CustomerCity
                cbxCustomerStates.Text = Order.CustomerState
                txtCustomerZIPCode.Text = Order.CustomerZIPCode
                cbxCarConditions.Text = Order.CarCondition
                cbxTankLevels.Text = Order.TankLevel
                txtMileageStart.Text = Order.MileageStart
                txtMileageEnd.Text = Order.MileageEnd
                dtpStartDate.Value = Order.DateStart
                dtpEndDate.Value = Order.DateEnd
                txtDays.Text = Order.Days
                txtRateApplied.Text = FormatNumber(Order.RateApplied)
                txtSubTotal.Text = FormatNumber(Order.SubTotal)
                txtTaxRate.Text = FormatNumber(Order.TaxRate)
                txtTaxAmount.Text = FormatNumber(Order.TaxAmount)
                txtOrderTotal.Text = FormatNumber(Order.OrderTotal)
            Else
                MsgBox("There is no rental order with that receipt number")
                Exit Sub
            End If
    End Sub
  7. In the Class Name combo box, select btnClose
  8. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnClose_Click(ByVal sender As Object, _
                                   ByVal e As System.EventArgs) _
                                   Handles btnClose.Click
            Close()
    End Sub
  9. Execute the application
  10. Create a few rental orders and print them
     
    Bethesda Car Rental: Rental Order
  11. Close the forms and return to your programming environment
  12. Execute the application again
  13. Open a previously created order to simulate a customer returning a car and change some values on the form such as the return date, the mileage end, and the order status
  14. Also click the Calculate button to get the final evaluation
     
    Bethesda Car Rental: Rental Order
    Rental Orders
  15. Print the rental orders
  16. Close the forms and return to your programming environment

Removing Items From a Dictionary Type of List

To delete one item from the list, you can call the Remove() method. Its syntax is:

Public Overridable Sub Remove(key As Object)

Here is an example:

Public Class Exercise
    Private Students As Hashtable

    Private Sub Exercise_Load(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles MyBase.Load
        Students = New Hashtable

        Students.Add("Hermine", "Tolston")
        Students.Add("Patrick", "Donley")
        Students.Add("Chrissie", "Hannovers")
        Students.Add("Patricia", "Herzog")
        Students("Michael") = "Herlander"
        Students("Philemon") = "Jacobs"
        Students("Antoinette") = "Malhoun"

        For Each Entry As DictionaryEntry In Students
            lbxStudents.Items.Add(Entry.Key & " " & Entry.Value)
        Next
    End Sub

    Private Sub btnDelete_Click(ByVal sender As System.Object, _
                                ByVal e As System.EventArgs) _
                                Handles btnDelete.Click
        Students.Remove("Chrissie")

        lbxStudents.Items.Clear()

        For Each Entry As DictionaryEntry In Students
            lbxStudents.Items.Add(Entry.Key & " " & Entry.Value)
        Next
    End Sub
End Class

This would produce:

Hashtable Hashtable

To delete all items from the list, you can call the Clear() method. Its syntax is:

Public Overridable Sub Clear

 


Previous Copyright 2008 Yevol Next