Home

Built-In Collection Classes

 

Introduction to List Classes

 

Overview

Instead of creating a collection class from scratch or instead of deriving a collection, you can use one of the built-in collection classes of the .NET Framework. To support the creation of any kinds of list, the Microsoft .NET Framework provides the ArrayList and the generic List classes. 

The ArrayList class is defined in the System.Collections namespace while the generic List class is part of the System.Collections.Generic namespace. Therefore, in order to use one of these classes in your application, you can first include its namespace in the file that would perform the list-related operations.

The ArrayList class implements the IList, the ICollection, and the IEnumerable interfaces. The List class implements the generic IList(Of Type), the generic ICollection(Of Type), the generic IEnumerable(Of Type), the IList, the ICollection, and the IEnumerable interfaces.

The ArrayList class is founded as follows:

Public Class ArrayList _
	Implements IList, ICollection, IEnumerable, ICloneable

The generic List class is founded as follows:

Public Class List(Of T) _
	Implements IList(Of T), ICollection(Of T),  _
	IEnumerable(Of T), IList, ICollection, IEnumerable

You can use either the ArrayList or the generic List class to create and manage values for a list. Here is an example of declaring an ArrayList variable:

Imports System.Collections

Public Class Exercise
    Private ListOfNames As ArrayList

    Private Sub Exercise_Load(ByVal sender As Object, _
                              ByVal e As System.EventArgs) _
                              Handles Me.Load
        ListOfNames = New ArrayList
    End Sub
End Class

Besides the ability to create a list, both the ArrayList and the List classes have the built-in mechanism for serialization.

The default constructor allows you to create an empty list before adding values to it. If you already have an ICollection-based list, that is, a list created from a class that implements the ICollection interface, you can initialize your ArrayList list with it. To support this, the ArrayList class is equipped with the following constructor:

Public Sub New(c As ICollection)

Here is an example:

Imports System.Collections

Public Class Exercise
    Private ListOfNames As ArrayList

    Private Sub Exercise_Load(ByVal sender As Object, _
                              ByVal e As System.EventArgs) _
                              Handles Me.Load
        Dim cbx As ComboBox = New ComboBox

        cbx.Items.Add("Paul Bertrand Yamaguchi")
        cbx.Items.Add("Helene Mukoko")
        cbx.Items.Add("John Hancock")
        cbx.Items.Add("Gertrude Monay")

        ListOfNames = New ArrayList(cbx.Items)
    End Sub
End Class

Practical Learning Practical Learning: Introducing Built-In List Classes

  1. Start Microsoft Visual Basic and create a new Windows Forms Application named CollegeParkAutoParts1
  2. To create a dialog box, on the main menu, click Project -> Add Windows Form...
  3. Set the name to MakeEditor and click Add
  4. Design the form as follows:
     
    Make Editor
    Control Text Name Other Properties
    Label &Make:    
    TextBox   txtMake Modifiers: Public
    Button OK btnOK DialogResult: OK
    Button Cancel btnCancel DialogResult: Cancel
    Form Property Value
    FormBorderStyle FixedDialog
    Text Make Editor
    StartPosition CenterScreen
    AcceptButton btnOK
    CancelButton btnCancel
    MaximizeBox False
    MinimizeBox False
    ShowInTaskbar False
  5. To create a dialog box, on the main menu, click Project -> Add Windows Form...
  6. Set the name to ModelEditor and click Add
  7. Design the form as follows:
     
    College Park Auto Parts: Model Editor
    Control Text Name Other Properties
    Label &Model:    
    TextBox   txtModel Modifiers: Public
    Button OK btnOK DialogResult: OK
    Button Cancel btnCancel DialogResult: Cancel
    Form Property Value
    FormBorderStyle FixedDialog
    Text Model Editor
    StartPosition CenterScreen
    AcceptButton btnOK
    CancelButton btnCancel
    MaximizeBox False
    MinimizeBox False
    ShowInTaskbar False
  8. To create a dialog box, in the Solution Explorer, right-click CollegeParkAutoParts1 -> Add -> Windows Form...
  9. Set the name to CategoryEditor and click Add
  10. Design the form as follows:
     
    College Park Auto Parts: Category Editor
    Control Text Name Other Properties
    Label &Category:    
    TextBox   txtCategory Modifiers: Public
    Button OK btnOK DialogResult: OK
    Button Cancel btnCancel DialogResult: Cancel
    Form Property Value
    FormBorderStyle FixedDialog
    Text Category Editor
    StartPosition CenterScreen
    AcceptButton btnOK
    CancelButton btnCancel
    MaximizeBox False
    MinimizeBox False
    ShowInTaskbar False
  11. On the main menu, click Project -> Add Windows Form...
  12. Set the Name to NewStoreItem and click Add
  13. Design the form as follows:
     
    College Park Auto-Part - Part Editor
     
    Control Text Name Other Properties
    Label &Year:    
    TextBox   txtItemNumber  
    Label &Make:    
    ComboBox   cbxMakes  
    Button New C&ategory... btnNewMake  
    Label M&odel:    
    ComboBox   cbxModels  
    Button New Mo &del... btnNewModel  
    Label &Category:    
    ComboBox   cbxCategories  
    Button New Ca&tegory btnNewCategory  
    Label &Unit Price:    
    TextBox 0.00 txtUnitPrice TextAlign: Right
    Label Part #:    
    TextBox   txtPartNumber  
    Label &Part Name:    
    TextBox   txtPartName  
    Button Submit btnSubmit  
    Button Close btnClose DialogResult: Cancel
    Form Property Value
    FormBorderStyle FixedDialog
    Text College Park Auto -Parts: Part Editor
    StartPosition CenterScreen
    MaximizeBox False
    MinimizeBox False
    ShowInTaskbar False
  14. Right-click the form and click View Code
  15. In the Class Name combo box, select btnNewMake
  16. In the Method Name combo box, select Click and implement the event as follows:
      
    Private Sub btnNewMake_Click(ByVal sender As Object, _
                                     ByVal e As System.EventArgs) _
                                     Handles btnNewMake.Click
            Dim Editor As MakeEditor = New MakeEditor
    
            If Editor.ShowDialog() = DialogResult.OK Then
                If Editor.txtMake.Text.Length > 0 Then
                    Dim strMake As String = Editor.txtMake.Text
    
                    ' Make sure the category is not yet in the list
                If cbxMakes.Items.Contains(strMake) Then
                        MsgBox(strMake & " is already in the list")
                    Else
                        ' Since this is a new category, add it to the combo box
                        cbxMakes.Items.Add(strMake)
                    End If
    
                    cbxMakes.Text = strMake
                End If
            End If
    End Sub
  17. In the Class Name combo box, select btnNewModel
  18. In the Method Name combo box, select Click and implement the event as follows:
      
    Private Sub btnNewModel_Click(ByVal sender As Object, _
                                      ByVal e As System.EventArgs) _
                                      Handles btnNewModel.Click
            Dim Editor As ModelEditor = New ModelEditor
    
            If Editor.ShowDialog() = DialogResult.OK Then
                If Editor.txtModel.Text.Length > 0 Then
                    Dim strModel As String = Editor.txtModel.Text
    
                    ' Make sure the category is not yet in the list
                If cbxModels.Items.Contains(strModel) Then
                        MsgBox(strModel & " is already in the list")
                    Else
                        ' Since this is a new category, add it to the combo box
                        cbxModels.Items.Add(strModel)
                    End If
    
                    cbxModels.Text = strModel
                End If
            End If
    End Sub
  19. In the Class Name combo box, select btnNewCategory
  20. In the Method Name combo box, select Click and implement the event as follows:
      
    Private Sub btnNewCategory_Click(ByVal sender As Object, _
                                         ByVal e As System.EventArgs) _
                                         Handles btnNewCategory.Click
            Dim Editor As CategoryEditor = New CategoryEditor
    
            If Editor.ShowDialog() = DialogResult.OK Then
                If Editor.txtCategory.Text.Length > 0 Then
                    Dim strCategory As String = Editor.txtCategory.Text
    
                    ' Make sure the category is not yet in the list
                    If cbxCategories.Items.Contains(strCategory) Then
                        MsgBox(strCategory & " is already in the list")
                    Else
                        ' Since this is a new category, add it to the combo box
                        cbxCategories.Items.Add(strCategory)
                    End If
    
                    cbxCategories.Text = strCategory
                End If
            End If
    End Sub
  21. Save the file
  22. To create an icon, on the main menu, click Project -> Add New Item...
  23. In the Templates list, click Icon File
  24. Set the Name to cpap1 and click Add
  25. Right-click the white area and click Delete Image Type
  26. Design the 16x16, 16 colors version of the icon as follows:
     
    House
  27. On the main menu, click File -> Save cpap1.ico As
  28. Select the bin\Debug folder of the current folder and click Save
  29. On the main menu, click File -> Close
  30. In the Solution Explorer, expand bin and expand Debug
  31. In the Solution Explorer, right-click the Debug folder -> Add -> New Item...
  32. In the Templates list, make sure Icon File is selected.
    Set the Name to cpap2 and click Add
  33. Right-click the white area and click Delete Image Type
  34. Design the 16x16, 16 colors version of the icon as follows:
     
  35. Save the file and close the icon window
  36. In the Solution Explorer, right- click the Debug folder -> Add -> New Item...
  37. In the Templates list, make sure Icon File is selected.
    Set the Name to year1 and click Add
  38. Right-click the white area and click Delete Image Type
  39. Design the 16x16, 16 colors version of the icon as follows:
     
  40. Save the file and close the icon window
  41. In the Solution Explorer, right- click the Debug folder -> Add -> New Item...
  42. In the Templates list, make sure Icon File is selected.
    Set the Name to year2 and click Add
  43. Right-click the white area and click Delete Image Type
  44. Design the 16x16, 16 colors version of the icon as follows:
     
  45. Save the file and close the icon window
  46. In the Solution Explorer, right- click the Debug folder -> Add -> New Item...
  47. In the Templates list, make sure Icon File is selected.
    Set the Name to make1 and click Add
  48. Right-click the white area and click Delete Image Type
  49. Design the 16x16, 16 colors version of the icon as follows:
     
    Icon Design: Diamond
  50. Save the file and close the icon window
  51. In the Solution Explorer, right- click the Debug folder -> Add -> New Item...
  52. In the Templates list, make sure Icon File is selected.
    Set the Name to make2 and click Add
  53. Right-click the white area and click Delete Image Type
  54. Design the 16x16, 16 colors version of the icon as follows:
     
    Icon Design: Diamond
  55. Save the file and close the icon window
  56. In the Solution Explorer, right- click the Debug folder -> Add -> New Item...
  57. In the Templates list, make sure Icon File is selected.
    Set the Name to model1 and click Add
  58. Right-click the white area and click Delete Image Type
  59. Design the 16x16, 16 colors version of the icon as follows:
     
  60. Save the file and close the icon window
  61. In the Solution Explorer, right- click the Debug folder -> Add -> New Item...
  62. In the Templates list, make sure Icon File is selected.
    Set the Name to model2 and click Add
  63. Right-click the white area and click Delete Image Type
  64. Design the 16x16, 16 colors version of the icon as follows:
     
  65. Save the file and close the icon window
  66. In the Solution Explorer, right- click the Debug folder -> Add -> New Item...
  67. In the Templates list, make sure Icon File is selected.
    Set the Name to category1 and click Add
  68. Right-click the white area and click Delete Image Type
  69. Design the 16x16, 16 colors version of the icon as follows:
     
  70. Save the file and close the icon window
  71. In the Solution Explorer, right- click the Debug folder -> Add -> New Item...
  72. In the Templates list, make sure Icon File is selected.
    Set the Name to category2 and click Add
  73. Right-click the white area and click Delete Image Type
  74. Design the 16x16, 16 colors version of the icon as follows:
     
    Icon Design: Minus
  75. Save the file and close the icon window
  76. In the Solution Explorer, right-click Form1.vb and click Rename
  77. Type Central.vb and press Enter twice to display the Central form
  78. From the Components section of the Toolbox, click ImageList and click the form
  79. In the Properties window, click (Name) and type AutoPartsImages
  80. Click the ellipsis button of the Images field
  81. In the Image Collection Editor, click Add
  82. Locate the folder that contains the icons you created and display it in the Look In combo box
  83. Select cpap1.ico and click Open
  84. In the same way, add the other pictures in the following order: cpap2.ico, year1.ico, year2.ico, make1.ico, make2.ico, model1.ico, model2.ico, category1.ico, and category1.ico
     
    Image Collection Editor
  85. Click OK
  86. Design the form as follows:
     
    College Park Auto Parts - Form Design
    Control Text Name Other Properties
    Label Label College Park Auto-Parts   Font: Times New Roman, 20.25pt, style=Bold
    ForeColor: Blue
    Panel     Height: 2
    GroupBox GroupBox Part Identification    
    TreeView TreeView   tvwAutoParts ImageList: imgAutoParts
    GroupBox GroupBox Available Parts    
    ListView ListView   lvwAutoParts FullRowSelect: True
    GridLines: True
    View: Details
    Columns   (Name) Text TextAlign Width
    colPartNumber Part #    
    colPartName Part Name   300
    colUnitPrice Unit Price Right 80
    GroupBox GroupBox Customer Order - Selected Parts    
    Label Label Part #    
    Label Label Part Name    
    Label Label Unit Price    
    Label Label Qty    
    Label Label Sub Total    
    TextBox TextBox   txtPartNumber  
    TextBox TextBox   txtPartName  
    TextBox TextBox 0.00 txtUnitPrice TextAlign: Right
    TextBox TextBox 0 txtQuantity TextAlign: Right
    TextBox TextBox 0.00 txtSubTotal TextAlign: Right
    Button Button Add/Select btnAdd
    ListView ListView   lvwSelectedParts FullRowSelect: True
    GridLines: True
    View: Details
    Columns   (Name) Text TextAlign Width
    colPartNumberSelected Part #   45
    colPartNameSelected Part Name   274
    colUnitPriceSelected Unit Price Right 58
    colQuantitySelected Qty Right 28
    colSubTotalSelected Sub-Total Right 58
    GroupBox GroupBox Order Summary
    Button Button New Au&to Part... btnNewAutoPart  
    Label Label Receipt #:  
    TextBox TextBox txtSave
    Button Button Save btnSave
    Label Label Tax Rate:
    TextBox TextBox 7.75 txtTaxRate TextAlign: Right
    Label Label %
    Label Label Parts Total:
    TextBox TextBox 0.00 txtPartsTotal TextAlign: Right
    Button Button &New Customer Order btnNewCustomerOrder  
    Label Label Receipt #:  
    TextBox TextBox txtOpen
    Button Button Save btnSave
    Label Label Tax Amount:
    TextBox TextBox 0.00 txtTaxAmount TextAlign: Right
    Label Label Order Total:
    TextBox TextBox 0.00 txtOrderTotal TextAlign: Right
    Button Button Close btnClose  
  87. Right-click the table and click Form View
  88. In the Class Name combo box, select lvwAutoParts
  89. In the Method Name combo box, select DoubleClick and implement the event as follows:
     
    Private Sub lvwAutoParts_DoubleClick(ByVal sender As Object, _
                                             ByVal e As System.EventArgs) _
                                             Handles lvwAutoParts.DoubleClick
            Dim lviAutoPart As ListViewItem = lvwAutoParts.SelectedItems(0)
    
            If (lvwAutoParts.SelectedItems.Count = 0) Or _
               (lvwAutoParts.SelectedItems.Count > 1) Then
                Exit Sub
            End If
    
            txtPartNumber.Text = lviAutoPart.Text
            txtPartName.Text = lviAutoPart.SubItems(1).Text
            txtUnitPrice.Text = lviAutoPart.SubItems(2).Text
    
            txtQuantity.Text = "1"
            txtSubTotal.Text = lviAutoPart.SubItems(2).Text
    
            txtQuantity.Focus()
    End Sub
  90. In the Class Name combo box, select txtUnitPrice
  91. In the Method Name combo box, select Leave and implement the event as follows:
     
    Private Sub txtUnitPrice_Leave(ByVal sender As Object, _
                                       ByVal e As System.EventArgs) _
                                       Handles txtUnitPrice.Leave, _
                                               txtQuantity.Leave
            Dim UnitPrice As Double
            Dim Quantity As Integer
            Dim SubTotal As Double
    
            Try
                UnitPrice = CDbl(txtUnitPrice.Text)
            Catch Exc As FormatException
                MsgBox("Invalid Unit Price!")
            End Try
    
            Try
                Quantity = CInt(txtQuantity.Text)
            Catch Exc As FormatException
                MsgBox("Invalid Quandtity!")
            End Try
    
            SubTotal = UnitPrice * Quantity
            txtSubTotal.Text = FormatNumber(SubTotal)
    End Sub
    
    Public Sub CalculateOrder()
            ' Calculate the current total order and update the order
            Dim PartsTotal As Double
            Dim TaxRate As Double
            Dim TaxAmount As Double
            Dim OrderTotal As Double
            Dim SubItem As ListViewItem.ListViewSubItem
            Dim lviAutoPart As ListViewItem
    
            For Each lviAutoPart In lvwSelectedParts.Items
                SubItem = lviAutoPart.SubItems(4)
                PartsTotal = PartsTotal + CDbl(SubItem.Text)
            Next
    
            Try
                TaxRate = CDbl(txtTaxRate.Text) / 100
            Catch Exc As FormatException
                MsgBox("Invalid Tax Rate")
            End Try
    
            TaxAmount = PartsTotal * TaxRate
            OrderTotal = PartsTotal + TaxAmount
    
            txtPartsTotal.Text = FormatNumber(PartsTotal)
            txtTaxAmount.Text = FormatNumber(TaxAmount)
            txtOrderTotal.Text = FormatNumber(OrderTotal)
    End Sub
  92. In the Class Name combo box, select lvwSelectedParts
  93. In the Method Name combo box, select DoubleClick and implement the event as follows:
     
    Private Sub lvwSelectedParts_DoubleClick(ByVal sender As Object, _
                                                 ByVal e As System.EventArgs) _
                                                 Handles lvwSelectedParts.DoubleClick
            Dim lviSelectedPart As ListViewItem = lvwSelectedParts.SelectedItems(0)
    
            If (lvwSelectedParts.SelectedItems.Count = 0) Or _
                (lvwSelectedParts.SelectedItems.Count > 1) Then
                Exit Sub
            End If
    
            txtPartNumber.Text = lviSelectedPart.Text
            txtPartName.Text = lviSelectedPart.SubItems(1).Text
            txtUnitPrice.Text = lviSelectedPart.SubItems(2).Text
            txtQuantity.Text = lviSelectedPart.SubItems(3).Text
            txtSubTotal.Text = lviSelectedPart.SubItems(4).Text
    
            lvwSelectedParts.Items.Remove(lviSelectedPart)
            CalculateOrder()
    End Sub
  94. In the Solution Explorer, right-click CollegeParkAutoParts1 -> Add -> Class...
  95. Set the name to PartDescription and press Enter
  96. To create a class that can hold a structured item of a list, change the class as follows:
     
    <Serializable()> Public Class PartDescription
        ' These members will be used to define a car part
        Private ID As Long
        Private yr As Integer
        Private mk As String
        Private mdl As String
        Private cat As String
        Private name As String
        Private price As Double
    
        Public Sub New()
            ID = 0
            yr = 1960
            mk = ""
            mdl = ""
            name = "Unknown"
            price = 0.0
        End Sub
    
        Public Sub New(ByVal code As Long, ByVal year As Integer, _
                       ByVal make As String, ByVal model As String, _
                       ByVal type As String, ByVal desc As String, _
                       ByVal UPrice As Double)
    
            ID = code
            yr = year
            mk = make
            mdl = model
            cat = type
            name = desc
            price = UPrice
        End Sub
    
        Public Property PartNumber() As Long
            Get
                Return ID
            End Get
            Set(ByVal value As Long)
                ID = value
            End Set
        End Property
    
        Public Property Year() As Integer
            Get
                Return yr
            End Get
            Set(ByVal value As Integer)
                yr = value
            End Set
        End Property
    
        Public Property Make() As String
            Get
                Return mk
            End Get
            Set(ByVal value As String)
                mk = value
            End Set
        End Property
    
        Public Property Model() As String
            Get
                Return mdl
            End Get
            Set(ByVal value As String)
                mdl = value
            End Set
        End Property
    
        Public Property Category() As String
            Get
                Return cat
            End Get
            Set(ByVal value As String)
                cat = value
            End Set
        End Property
    
        Public Property PartName() As String
            Get
                Return name
            End Get
            Set(ByVal value As String)
                name = value
            End Set
        End Property
    
        Public Property UnitPrice() As Double
            Get
                Return price
            End Get
            Set(ByVal value As Double)
                price = value
            End Set
        End Property
    
        Public Overrides Function ToString() As String
            Return PartNumber & " " & _
                   CStr(Year) & " " & _
                   Make & " " & _
                   Model & " " & _
                   Category & " " & _
                   PartName & " " & _
                   UnitPrice
        End Function
    End Class        
  97. In the Solution Explorer, right-click CollegeParkAutoParts1 -> Add -> Class...
  98. Set the name to PartOrdered and press Enter
  99. To create another class independent for a list, change the document as follows:
     
    <Serializable()> Public Class PartOrdered
        Public PartNumber As Long
        Public PartName As String
        Public UnitPrice As Double
        Public Quantity As Integer
        Public SubTotal As Double
    End Class
  100. Save all

The Capacity of a List

After declaring an ArrayList or a List variable, it is empty. As objects are added to it, the list grows. The list can grow tremendously as you wish. The number of items of the list is managed through the memory it occupies and this memory grows as needed. The number of items that the memory allocated is currently using is represented by the Capacity property. Here is an example of accessing the ArrayList.Capacity property:

Imports System.Collections

Public Class Exercise
    Private ListOfNames As ArrayList

    Private Sub Exercise_Load(ByVal sender As Object, _
                              ByVal e As System.EventArgs) _
                              Handles Me.Load
        ListOfNames = New ArrayList

        Text = "List Capacity: " & ListOfNames.Capacity
    End Sub
End Class

This would produce:

ArrayList Capacity

The capacity of a list will usually be the least of your concerns. If for some reason, you want to intervene and control the number of items that your list can contain, you can manipulate the Capacity property. For example, you can assign it a constant to set the maximum value that the list can contain. Instead of specifying the capacity after the list has been created, when declaring the list variable, you can specify its maximum capacity. To support this, both the ArrayList and the List classes are equipped with an additional constructor as follows:

Public Sub New(capacity As Integer)
Public Sub New(capacity As Integer)

Once again, you will hardly have any reason to use the Capacity property: the compiler knows what to do with it.

A Read-Only List

One of the reason for creating a list is to be able to add values to it, edit its values, retrieve a value, or delete values from it. These are the default operations. You can still limit these operations as you judge them unnecessary. For example, you may create a list and then initialize it with the values that you want the list to only have. If you do not want to have the user adding values to it, you can create the list as read-only. To do this, you can call the ArrayList.ReadOnly() method. It is overloaded with two versions as follows:

Public Shared Function ReadOnly(list As ArrayList) As ArrayList
Public Shared Function ReadOnly(list As IList) As IList

Some operations cannot be performed on a read-only list. To perform such operations, you can first find out whether an ArrayList list is read-only. This is done by checking its IsReadOnly property.

Item Addition

The primary operation performed on a list is to create one or more values. To do this, you have various alternatives. Both the ArrayList and the List classes are equipped with an Add() method. The syntax of the System.Collections.ArrayList.Add() method is:

Public Overridable Function Add(value As Object) As Integer

The syntax of the System.Collections.Generic.List.Add() method is:

Public Sub Add(item As T)

The argument of the method is the value to add to the list. If the method succeeds with the addition, it returns the position where the value was added in the list. Here are example for an ArrayList variable:

Private Sub Exercise_Load(ByVal sender As Object, _
                              ByVal e As System.EventArgs) _
                              Handles Me.Load
        ListOfNames = New ArrayList

        ListOfNames.Add("Christine Kingston")
        ListOfNames.Add("Hermine Paulson")
        ListOfNames.Add("William Harrison")
        ListOfNames.Add("Ursula Morales")
        ListOfNames.Add("Evan Lancos")
End Sub

If the method fails to add the value and if you are using the ArrayList class, the compiler would throw an error. One of the errors that could result from the ArrayList's failure of this operation would be based on the fact that either a new value cannot be added to the list because the list is read-only, or the list was already full prior to adding the new value. Normally, a list can be full only if you had specified the maximum number of items it can contain using the ArrayList.Capacity property. As mentioned above, the list can be made read-only by passing its variable to the ArrayList.ReadOnly() method.

Instead of adding one values at a time, you can first create a list of values and add that whole list at once. To support this operation, both the ArrayList and the List classes are equipped with a method named AddRange.

The syntax of the ArrayList.AddRange() method is:

Public Overridable Sub AddRange(c As ICollection)

The syntax of the List.AddRange() method is:

Public Sub AddRange(collection As IEnumerable(Of T))

The ArrayList.AddRange() method takes as argument a list created from a class that implements the ICollection interface. Here is an example:

Private Sub Exercise_Load(ByVal sender As Object, _
                              ByVal e As System.EventArgs) _
                              Handles Me.Load
        Dim cbx As ComboBox = New ComboBox
        cbx.Items.Add("Paul Bertrand Yamaguchi")
        cbx.Items.Add("Helene Mukoko")
        cbx.Items.Add("John Hancock")
        cbx.Items.Add("Gertrude Monay")

        ListOfNames = New ArrayList
        ListOfNames.AddRange(cbx.Items)
End Sub

The List.AddRange() method takes as argument a list created from a class that implements the generic IEnumerable interface.

Practical Learning Practical Learning: Adding Items to an ArrayList List

  1. In the Solution Explorer, right-click NewStoreItem and click View Code
  2. Add the following lines:
     
    Imports System.IO
    Imports System.Runtime.Serialization.Formatters.Binary
    
    Public Class NewStoreItem
        Private ListOfAutoParts As List(Of PartDescription)
    
  3. In the Class Name combo box, select btnSubmit
  4. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnSubmit_Click(ByVal sender As Object, _
                                    ByVal e As System.EventArgs) _
                                    Handles btnSubmit.Click
            Dim stmAutoParts As FileStream
            Dim bfmAutoParts As BinaryFormatter = New BinaryFormatter
    
            ' If this directory doesn't exist, create it
            Directory.CreateDirectory("C:\College Park Auto Parts")
            ' This is the file that holds the list of items
            Dim FileName As String = "C:\College Park Auto Parts\Parts.prs"
    
            ' Create a random number that will be used to identify the item
            Dim RndNumber As Random = New Random()
            txtPartNumber.Text = RndNumber.Next(100000, 999999).ToString()
    
            ' Make sure the user had selected a make
            If cbxYears.Text.Length = 0 Then
                MsgBox("You must specify the year")
                cbxYears.Focus()
                Exit Sub
            End If
    
            ' Make sure the user had selected a make
            If cbxMakes.Text.Length = 0 Then
                MsgBox("You must specify the car name")
                cbxMakes.Focus()
                Exit Sub
            End If
    
            ' Make sure the user had selected a model
            If cbxModels.Text.Length = 0 Then
                MsgBox("You must specify the model of the car")
                cbxModels.Focus()
                Exit Sub
            End If
    
            ' Make sure the user had selected the part category
            If cbxCategories.Text.Length = 0 Then
                MsgBox("You must specify the part's category")
                cbxCategories.Focus()
                Exit Sub
            End If
    
            ' Make sure the user had entered a name/description
            If txtPartName.Text.Length = 0 Then
                MsgBox("You must enter the name (or a " & _
                                "short description) for the part")
                txtPartName.Focus()
                Exit Sub
            End If
    
            ' Make sure the user had typed a price for the item
            If txtUnitPrice.Text.Length = 0 Then
                MsgBox("You must enter the price of the item")
                txtUnitPrice.Focus()
                Exit Sub
            End If
    
            ' Before saving the new part, find out if there was
            ' already a file that holds the list of parts
            ' If that file exists, open it and store its parts 
            ' in our ListOfParts variable
            If File.Exists(FileName) Then
                stmAutoParts = New FileStream(FileName, _
                                              FileMode.Open, _
                                              FileAccess.Read, _
                                              FileShare.Read)
    
                Try
                    ' Retrieve the list of items from file
                    ListOfAutoParts = CType(bfmAutoParts.Deserialize(stmAutoParts),  _
                                            List(Of PartDescription))
                Finally
    
                    stmAutoParts.Close()
                End Try
            End If
    
            ' Create the part
            Dim Part As PartDescription = New PartDescription
            Part.PartNumber = CLng(txtPartNumber.Text)
            Part.Year = CInt(cbxYears.Text)
            Part.Make = cbxMakes.Text
            Part.Model = cbxModels.Text
            Part.Category = cbxCategories.Text
            Part.PartName = txtPartName.Text
            Part.UnitPrice = CDbl(txtUnitPrice.Text)
    
            ' Call the Add method of our collection class to add the part
            ListOfAutoParts.Add(Part)
    
            ' Save the list
            stmAutoParts = New FileStream(FileName, _
                                          FileMode.Create, _
                                          FileAccess.Write, _
                                          FileShare.Write)
    
            Try
                bfmAutoParts.Serialize(stmAutoParts, ListOfAutoParts)
    
                ' After saving the item, reset the form
                cbxYears.Text = ""
                cbxMakes.Text = ""
                cbxModels.Text = ""
                cbxCategories.Text = ""
                txtPartName.Text = ""
                txtUnitPrice.Text = "0.00"
                txtPartNumber.Text = RndNumber.Next(100000, 999999).ToString()
            Finally
                stmAutoParts.Close()
            End Try
    End Sub
  5. In the Solution Explorer, right-click Central.vb and click View Code
  6. Add the following namespaces in the top section of the file and declare the two variables:
     
    Imports System.IO
    Imports System.Runtime.Serialization.Formatters.Binary
    
    Public Class Central
        Private iFileName As Integer
        Private ListOfAutoParts As List(Of PartDescription)
  7. In the Class Name combo box, select btnSaveCustomerOrder
  8. 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
            Dim i As Integer
            Dim Part As PartsOrdered
            Dim bfmCustomerOrder As BinaryFormatter = New BinaryFormatter
    
            ' We will store our files in the following folder    
            Dim FolderName As String = "C:\College Park Auto Parts\Receipts"
            Dim Folder As DirectoryInfo = New DirectoryInfo(FolderName)
    
            Dim strFilename As String = FolderName & "\" & txtSave.Text & ".cap"
    
            Dim ListOfOrderedParts As List(Of PartsOrdered)
    
            If lvwSelectedParts.Items.Count = 0 Then
                Exit Sub
            Else
    
                ListOfOrderedParts = New List(Of PartsOrdered)
    
                For i = 0 To lvwSelectedParts.Items.Count - 1
    
                    Part = New PartsOrdered
    
                    Part.PartNumber = CLng(lvwSelectedParts.Items(i).Text)
                    Part.PartName = lvwSelectedParts.Items(i).SubItems(1).Text
                    Part.UnitPrice = CDbl(lvwSelectedParts.Items(i).SubItems(2).Text)
                    Part.Quantity = CInt(lvwSelectedParts.Items(i).SubItems(3).Text)
                    Part.SubTotal = CDbl(lvwSelectedParts.Items(i).SubItems(4).Text)
                    ListOfOrderedParts.Add(Part)
                Next
    
                Dim stmCustomerOrder As FileStream = New FileStream(strFilename, _
                                                                    FileMode.Create)
    
                Try
                    bfmCustomerOrder.Serialize(stmCustomerOrder, ListOfOrderedParts)
                Finally
                    stmCustomerOrder.Close()
                End Try
            End If
    End Sub
  9. Save all

The Number of Items in the List

When using a list, at any time, you should be able to know the number of items that the list contains. This information is provided by the ArrayList.Count or the List.Count property.

The Capacity and the Count properties have this in common: the value of each increases as the list grows and the same value decreases if the list shrinks. It is important to know that there are various differences between the capacity of a list and the number of items it contains:

  • Capacity is a read/write property. This means that you can assign a value to the capacity to fix the number of items that the list can contain. You can also retrieve the value of the Capacity
  • The Count property is read-only because it is used by the compiler to count the current number of values of the list and this counting is performed without your intervention

Item Retrieval

Once a list is ready, you can perform different types of operations on it. Besides adding items, one of the most regular operations performed on a list consists of locating and retrieving its values. You have various options.

To give you access to each member of their list, both the ArrayList and the List classes are equipped with the default Item property. The first value of the list has an index of 0. The second has an index of 1, and so on. 

To retrieve a single value based on its position, you can apply the parentheses of arrays to the variable. Here is an example:

Private Sub Exercise_Load(ByVal sender As Object, _
                              ByVal e As System.EventArgs) _
                              Handles Me.Load
        Dim i As Integer
        ListOfNames = New ArrayList

        ListOfNames.Add("Christine Kingston")
        ListOfNames.Add("Hermine Paulson")
        ListOfNames.Add("William Harrison")
        ListOfNames.Add("Ursula Morales")
        ListOfNames.Add("Evan Lancos")

        For i = 0 To 4
            lbxNames.Items.Add(ListOfNames(i))
        Next

End Sub

ArrayList

Another issue to keep in mind is that the ArrayList.Item() property returns an Object value. Therefore, you may have to cast this value to your type of value to get it right.

Besides using the index to access a value from the list, the ArrayList and the List classes implement the IEnumerable.GetEnumerator() method. For this reason, you can use the For Each loop to access each member of the collection. Here is an example:

Private Sub Exercise_Load(ByVal sender As Object, _
                              ByVal e As System.EventArgs) _
                              Handles Me.Load
        Dim strName As String
        ListOfNames = New ArrayList

        ListOfNames.Add("Christine Kingston")
        ListOfNames.Add("Hermine Paulson")
        ListOfNames.Add("William Harrison")
        ListOfNames.Add("Ursula Morales")
        ListOfNames.Add("Evan Lancos")

        For Each strName In ListOfNames
            lbxNames.Items.Add(strName)
        Next
End Sub

You can use the Item property to change a value in the list. Because the Item property is used to access an existing value from the list, the value must have been created. If you try setting the value of a non existing item, the compiler would throw an ArgumentOutOfRangeException Exception. Here is an example:

Private Sub Exercise_Load(ByVal sender As Object, _
                              ByVal e As System.EventArgs) _
                              Handles Me.Load
        ListOfNames = New ArrayList

        ListOfNames(0) = "Paul Bertrand Yamaguchi"
End Sub

Notice that at the time the 0 item is accessed, it has not previous been created. This would produce:

Error

A review of the Details section shows:

System.ArgumentOutOfRangeException: Index was out of range. 
Must be non-negative and less than the size of the collection.
Parameter name: index
at System.Collections.ArrayList.set_Item(Int32 index, Object value)
at Exercise.StartForm(Object sender, EventArgs e) 
in E:\Programs\vb\Exercise1\Exercise1\Exercise.cs:line 31

This means that you can use the Item property only to change the value of a previous created item.

Practical Learning Practical Learning: Enumerating a List

  1. In the Solution Explorer, right-click NewStoreItem.vb and click View Code
  2. In the Class Name combo box, select cbxMakes
  3. In the Method Name combo box, select SelectedIndexChanged and implement its event as follows:
     
    Private Sub cbxMakes_SelectedIndexChanged(ByVal sender As Object, _
                                                  ByVal e As System.EventArgs) _
                                                  Handles cbxMakes.SelectedIndexChanged
        cbxModels.Text = ""
        cbxModels.Items.Clear()
        Dim Part As PartDescription
    
        For Each Part In ListOfAutoParts
            If Part.Make = cbxMakes.Text Then
                If Not cbxModels.Items.Contains(Part.Model) Then
                    cbxModels.Items.Add(Part.Model)
                End If
            End If
        Next
    End Sub
  4. In the Solution Explorer, right-click Central.vb and click View Code
  5. In the Class Name, select btnAdd
  6. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnAdd_Click(ByVal sender As Object, _
                                 ByVal e As System.EventArgs) _
                                 Handles btnAdd.Click
            Dim Part As PartDescription
            Dim lviSelectedPart As ListViewItem
    
            REM If the user didn't enter a part number, don't do anything
            If txtPartNumber.Text.Length = 0 Then
                MsgBox("There is no part to be added to the order")
                Exit Sub
            End If
    
            REM Since the user entered a part, check each item in the list of parts
            For Each Part In ListOfAutoParts
                REM If you find a part number that corresponds to the user's entry ...
                If Part.PartNumber = CLng(txtPartNumber.Text) Then
                    REM ... display it in the Selected Parts list view
                    lviSelectedPart = New ListViewItem(Part.PartNumber)
    
                    lviSelectedPart.SubItems.Add(Part.PartName)
                    lviSelectedPart.SubItems.Add(Part.UnitPrice)
                    lviSelectedPart.SubItems.Add(txtQuantity.Text)
                    lviSelectedPart.SubItems.Add(txtSubTotal.Text)
                    lvwSelectedParts.Items.Add(lviSelectedPart)
                End If
            Next
    
            REM Update the order evaluation
            CalculateOrder()
    End Sub
  7. In the Class Name, select btnOpen
  8. In the Method Name combo box, select Click and implement its event as follows:
     
    Private Sub btnOpen_Click(ByVal sender As Object, _
                                  ByVal e As System.EventArgs) _
                                  Handles btnOpen.Click
            Dim Part As PartOrdered
            Dim strFilename As String
            Dim lviReceiptPart As ListViewItem
            Dim ListOfReceipts As List(Of PartOrdered)
            Dim ReceiptsFormatter As BinaryFormatter = New BinaryFormatter()
            Dim StreamReceipts As FileStream = Nothing
    
            REM Identify the folder where the receipts are stored
            Dim FolderName As String = "C:\College Park Auto Parts\Receipts"
    
            REM Get a reference to the receipts
            Dim dirReceipts As DirectoryInfo = New DirectoryInfo(FolderName)
            REM Get the list of receipts in the folder
            Dim fleReceipts() As FileInfo = dirReceipts.GetFiles()
    
            REM Check that the user entered a receipt number
            REM If not, don't do anything
            If txtOpen.Text.Length = 0 Then
                MsgBox("You must enter a receipt number" & vbCrLf & _
                                "There is no receipt number to " & _
                                "open a customer's order")
                txtOpen.Focus()
                Exit Sub
            End If
    
            REM If no receipt was created before, let the user know
            If fleReceipts.Length = 0 Then
                MsgBox("There is no customer order to open")
                txtOpen.Focus()
                Exit Sub
            Else
                REM Since there is at least one receipt,
                REM get ready to use it/them
                lvwAutoParts.Items.Clear()
                lvwSelectedParts.Items.Clear()
    
                REM Create a file name using the path to the folder, 
                REM the receipt number, and the .cap extension
                strFilename = FolderName & "\" & txtOpen.Text & ".cap"
    
                REM Check if there is a file with that receipt number
                If File.Exists(strFilename) Then
                    Try
                        REM If so, retrieve the contents of that file
                        StreamReceipts = New FileStream(strFilename, FileMode.Open)
                        ListOfReceipts = CType(ReceiptsFormatter.Deserialize(StreamReceipts),  _
                                               List(Of PartOrdered))
    
                        REM And display the contents of that receipt number in 
                        REM the Selected Parts list view
                        For Each Part In ListOfReceipts
                            lviReceiptPart = New ListViewItem(Part.PartNumber)
    
                            lviReceiptPart.SubItems.Add(Part.PartName)
                            lviReceiptPart.SubItems.Add(FormatNumber(Part.UnitPrice))
                            lviReceiptPart.SubItems.Add(Part.Quantity)
                            lviReceiptPart.SubItems.Add(FormatNumber(Part.SubTotal))
                            lvwSelectedParts.Items.Add(lviReceiptPart)
                        Next
                    Finally
                        StreamReceipts.Close()
                    End Try
    
                    REM Just in case, update the calculation
                    CalculateOrder()
                    REM In case the user will modify the file that was opened,
                    REM put its receipt number in the Save text box
                    txtSave.Text = txtOpen.Text
                Else
                    REM Since it appears that the user entered an invalid receipt number
                    REM let him/her know
                    MsgBox("There is no customer order with that receipt number")
                End If
            End If
    End Sub
  9. Save the file

Checking the Existence of an Item

Instead of the parentheses that allow you to retrieve a value based on its position, you can look for a value based on its complete definition. You have various options. You can first "build" an item and ask the compiler to check whether any item in the list matches your definition. To perform this search, depending on your class, you can call either the ArrayList.Contains() or the List.Contains() method. The syntax of the System.Collections.ArrayList.Contains() method is:

Public Overridable Function Contains(item As Object) As Boolean

The syntax of the System.Collections.Generic.List.Contains() method is:

Public Function Contains(item As T) As Boolean

The value to look for is passed as argument to the method. The compiler would look for exactly the value, using its definition, in the list. If any detail of the argument fails to match any value of the list, the method would return False. If all characteristics of the argument correspond to a value of the list, the method returns True. Here is an example:

Imports System.Collections

Public Class Exercise
    Private ListOfNames As ArrayList

    Private Sub Exercise_Load(ByVal sender As Object, _
                              ByVal e As System.EventArgs) _
                              Handles Me.Load
        ListOfNames = New ArrayList

        ListOfNames.Add("Christine Kingston")
        ListOfNames.Add("Hermine Paulson")
        ListOfNames.Add("William Harrison")
        ListOfNames.Add("Ursula Morales")
        ListOfNames.Add("Evan Lancos")

        For Each strName As String In ListOfNames
            lbxNames.Items.Add(strName)
        Next
    End Sub

    Private Sub btnResult_Click(ByVal sender As System.Object, _
                                ByVal e As System.EventArgs) _
                                Handles btnResult.Click
        Dim strFind As String = txtLookFor.Text

        If ListOfNames.Contains(strFind) = True Then
            txtResult.Text = "Found"
        Else
            txtResult.Text = "Not Found"
        End If
    End Sub
End Class
Array List
Array List

Practical LearningPractical Learning: Checking the Existence of an Item

  1. In the Solution Explorer, right-click NewStoreItem.vb and click View Code
  2. In the Class Name combo box, select (NewStoreItem Events)
  3. In the Method Name combo box, select Load and implement the event as follows:
     
    Private Sub NewStoreItem_Load(ByVal sender As Object, _
                                      ByVal e As System.EventArgs) _
                                      Handles Me.Load
            REM Since all values seem ready, prepare to process the item
            Dim i As Integer
            Dim Part As PartDescription
            Dim RndNumber As Random = New Random
            Dim StreamAutoParts As FileStream = Nothing
            Dim bfmAutoParts As BinaryFormatter = New BinaryFormatter
    
            ListOfAutoParts = New List(Of PartDescription)
    
            For i = DateTime.Today.Year + 1 To 1960 Step -1
                cbxYears.Items.Add(i)
            Next
    
            REM Create a random number that will be used to identify the item
            txtPartNumber.Text = RndNumber.Next(100000, 999999)
    
            REM This is the file that holds the list of parts
            Dim FileName As String = "C:\College Park Auto Parts\Parts.prs"
    
            If File.Exists(FileName) Then
                StreamAutoParts = New FileStream(FileName, _
                                                        FileMode.Open, _
                                                        FileAccess.Read, _
                                                        FileShare.Read)
                Try
                    REM Retrieve the list of items from file
                    ListOfAutoParts = CType(bfmAutoParts.Deserialize(StreamAutoParts),  _
                                            List(Of PartDescription))
    
                    REM Display the car manufacturers in the Make combo box
                    For i = 0 To ListOfAutoParts.Count - 1
                        Part = CType(ListOfAutoParts(i), PartDescription)
    
                        If Not cbxMakes.Items.Contains(Part.Make) Then
                            cbxMakes.Items.Add(Part.Make)
                        End If
                    Next
    
                    REM Display the pats categories in the Category combo box
                    For i = 0 To ListOfAutoParts.Count - 1
                        Part = CType(ListOfAutoParts(i), PartDescription)
    
                        If Not cbxCategories.Items.Contains(Part.Category) Then
                            cbxCategories.Items.Add(Part.Category)
                        End If
                Next
                Finally
                    StreamAutoParts.Close()
                End Try
            End If
    End Sub
  4. In the Solution Explorer, right-click Central.vb and click View Code
  5. In the Class Name combo box, select txtPartNumber
  6. In the Method name combo box, select Leave and implement the event as follows:
     
    Private Sub txtPartNumber_Leave(ByVal sender As Object, _
                                        ByVal e As System.EventArgs) _
                                        Handles txtPartNumber.Leave
            Dim Part As PartDescription
            ' We will allow the user to enter a part number
            ' In the beginning, we assume that the user 
            ' had entered an invalid number
            Dim Found As Boolean = False
            ' This will represent the part found, if any
            Dim PartFound As PartDescription = Nothing
    
            ' After the user had entered a part number,
            ' check the whole list of parts
            For Each Part In ListOfAutoParts
                ' If you find a part that holds the number the user had entered
                If Part.PartNumber = CLng(txtPartNumber.Text) Then
                    ' Mark that part
                    PartFound = Part
                    ' And update the flag that specifies that the part has been found
                    Found = True
                End If
                ' If the part number was not found, check the next
            Next ' If no part has that number, the found flag keeps marked as False
    
            ' If a part with that number was found...
            If Found = True Then
                ' Show the corresponding part name and unit price
                txtPartName.Text = PartFound.PartName
                txtUnitPrice.Text = FormatNumber(PartFound.UnitPrice)
                txtQuantity.Text = "1"
                txtSubTotal.Text = FormatNumber(PartFound.UnitPrice)
                ' Give focus to the quantity in case the user was to increase it
                txtQuantity.Focus()
            Else
                ' Since no part with that number was found,
                ' reset the text boxes
                txtPartName.Text = ""
                txtUnitPrice.Text = "0.00"
                txtQuantity.Text = "0"
                txtSubTotal.Text = "0.00"
    
                ' Let the user know that the part number that 
                ' was entered is not in the list
                MsgBox("There is no part with that number")
            End If
    End Sub
  7. Under the above End Sub line, create the following procedure:
     
    Public Sub ShowAutoParts()
            Dim Years As Integer
            Dim NodeYear
            Dim NodeMake As TreeNode
            Dim NodeModel As TreeNode
            Dim Part As PartDescription
            Dim StreamAutoParts As FileStream
            Dim bfmAutoParts As BinaryFormatter = New BinaryFormatter
    
            tvwAutoParts.Nodes.Clear()
    
            Dim RootElement As TreeNode = _
              tvwAutoParts.Nodes.Add("College Park Auto-Parts", _
                                     "College Park Auto-Parts", 0, 1)
            ' Show the years nodes
            For Years = DateTime.Today.Year + 1 To 1960 Step -1
                RootElement.Nodes.Add(CStr(Years), CStr(Years), 2, 3)
            Next
    
            tvwAutoParts.SelectedNode = RootElement
            ' Expand the root node
            tvwAutoParts.ExpandAll()
    
            ListOfAutoParts = New List(Of PartDescription)
    
            ' This is the file that holds the list of auto parts
            Dim Filename As String = "C:\College Park Auto Parts\Parts.prs"
    
            If File.Exists(FileName) Then
                StreamAutoParts = New FileStream(Filename, _
                                                 FileMode.Open, _
                                                 FileAccess.Read, _
                                                 FileShare.Read)
                Try
                    ' Retrieve the list of parts from file
                    ListOfAutoParts = CType(bfmAutoParts.Deserialize(StreamAutoParts),  _
                                            List(Of PartDescription))
    
                    ' Show the makes nodes
                    For Each NodeYear In RootElement.Nodes
    
                        Dim ListOfMakes As List(Of String) = New List(Of String)
    
                        For Each Part In ListOfAutoParts
                            If NodeYear.Text = Part.Year.ToString() Then
                                If Not ListOfMakes.Contains(Part.Make) Then
                                    ListOfMakes.Add(Part.Make)
                                End If
                            End If
                        Next
    
                        For Each strMake As String In ListOfMakes
                            NodeYear.Nodes.Add(strMake, strMake, 4, 5)
                        Next
                    Next
    
                    ' Showing the models nodes
                    For Each NodeYear In RootElement.Nodes
    
                        For Each NodeMake In NodeYear.Nodes
    
                            Dim ListOfModels As List(Of String) = New List(Of String)
    
                            For Each Part In ListOfAutoParts
                                If (NodeYear.Text = CStr(Part.Year)) And _
                                    (NodeMake.Text = Part.Make) Then
    
                                    If Not ListOfModels.Contains(Part.Model) Then
                                        ListOfModels.Add(Part.Model)
                                    End If
    
                                End If
                            Next
    
                            For Each strModel As String In ListOfModels
                                NodeMake.Nodes.Add(strModel, strModel, 6, 7)
                            Next
                        Next
                    Next
    
                    ' Showing the categories nodes
                    For Each NodeYear In RootElement.Nodes
                        For Each NodeMake In NodeYear.Nodes
                            For Each NodeModel In NodeMake.Nodes
                                Dim ListOfCategories As List(Of String) = New List(Of String)
    
                                For Each Part In ListOfAutoParts
                                    If (NodeYear.Text = CStr(Part.Year)) And _
                                        (NodeMake.Text = Part.Make) And _
                                        (NodeModel.Text = Part.Model) Then
    
                                        If Not ListOfCategories.Contains(Part.Category) Then
                                            ListOfCategories.Add(Part.Category)
                                        End If
                                    End If
                                Next
    
                                For Each strCategory As String In ListOfCategories
                                    NodeModel.Nodes.Add(strCategory, strCategory, 8, 9)
                                Next
                            Next
                        Next
                    Next
                Finally
                    StreamAutoParts.Close()
                End Try
            End If
    End Sub
  8. In the Class Name combo box, select btnNewAutoPart
  9. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnNewAutoPart_Click(ByVal sender As Object, _
                                         ByVal e As System.EventArgs) _
                                         Handles btnNewAutoPart.Click
            Dim Editor As NewStoreItem = New NewStoreItem
    
            If Editor.ShowDialog() = DialogResult.Cancel Then
                ShowAutoParts()
            End If
    End Sub
  10. In the Class Name combo box, select btnNewCustomerOrder
  11. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnNewCustomerOrder_Click(ByVal sender As Object, _
                                              ByVal e As System.EventArgs) _
                                              Handles btnNewCustomerOrder.Click
            ' We will store our files in the following folder    
            Dim FolderName As String = "C:\College Park Auto Parts\Receipts"
            Dim Folder As DirectoryInfo = Directory.CreateDirectory(FolderName)
    
            ' Get the list of files, if any, from our directory
            Dim ListOfFiles() As FileInfo = Folder.GetFiles()
    
            ' If there is no file in the directory,
            ' then we will use 1000 as the first file name
            If ListOfFiles.Length = 0 Then
                iFileName = 1000
            Else ' If there was at least one file in the directory
                ' Get a reference to the last file
                Dim LastFile As FileInfo = ListOfFiles(ListOfFiles.Length - 1)
                ' Get the name of the last file without its extension
                Dim fwe As String = Path.GetFileNameWithoutExtension(LastFile.FullName)
                ' Increment the name of the file by 1
                iFileName = CInt(fwe) + 1
            End If
    
            txtSave.Text = iFileName.ToString()
    
            lvwAutoParts.Items.Clear()
            lvwSelectedParts.Items.Clear()
    End Sub
  12. In the Class Name combo box, select (Central Events)
  13. In the Method Name combo box, select Load and implement the event as follows:
     
    Private Sub Central_Load(ByVal sender As Object, _
                                 ByVal e As System.EventArgs) _
                                 Handles Me.Load
            ShowAutoParts()
            btnNewCustomerOrder_Click(sender, e)
    End Sub
  14. In the Class Name combo box, select tvwAutoParts
  15. In the Method Name combo box, select NodeMouseClick and implement the event as follows:
     
    Private Sub tvwAutoParts_NodeMouseClick(ByVal sender As Object, _
                  ByVal e As System.Windows.Forms.TreeNodeMouseClickEventArgs) _
                                            Handles tvwAutoParts.NodeMouseClick
        Dim Part As PartDescription
        Dim lviAutoPart As ListViewItem
        Dim NodeClicked As TreeNode = e.Node
    
        If NodeClicked.Level = 4 Then
            lvwAutoParts.Items.Clear()
        End If
    
        Try
            For Each Part In ListOfAutoParts
                If (Part.Category = NodeClicked.Text) And _
                    (Part.Model = NodeClicked.Parent.Text) And _
                    (Part.Make = NodeClicked.Parent.Parent.Text) And _
                    (CStr(Part.Year) = NodeClicked.Parent.Parent.Parent.Text) Then
                    lviAutoPart = New ListViewItem(Part.PartNumber)
    
                    lviAutoPart.SubItems.Add(Part.PartName)
                    lviAutoPart.SubItems.Add(FormatNumber(Part.UnitPrice))
                    lvwAutoParts.Items.Add(lviAutoPart)
                End If
            Next
        Catch Exc As NullReferenceException
    
        End Try
    End Sub
  16. In the Class Name combo box, select btnClose
  17. 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
            End
    End Sub
  18. Execute the application
  19. Click the New Auto Part button and use the Part Editor to create a few parts (let the computer generate the part numbers)
     
    Auto Part
  20. Close the Part Editor
  21. Create a few customer part orders and save them:
     
    College Park Auto Parts: Customer Order
     
    College Park Auto Parts: Part Selection
  22. Close the forms and return to your programming environment
  23. Execute the application again and open a previously saved order
  24. Close the forms and return to your programming environment

Searching for an Item

Another option to look for an item in a list consists of calling the BinarySearch() method of either the ArrayList or the List class. It is overloaded in three versions and one of them uses the following syntax:

Public Overridable Function BinarySearch(value As Object) As Integer
Public Function BinarySearch(item As T) As Integer

The value to look for is passed argument to the method. Here is an example:

Private Sub btnResult_Click(ByVal sender As System.Object, _
                                ByVal e As System.EventArgs) _
                                Handles btnResult.Click
        Dim strFind As String = txtLookFor.Text

        If ListOfNames.BinarySearch(strFind) > 0 Then
            txtResult.Text = "Found"
        Else
            txtResult.Text = "Not Found"
        End If
End Sub

Clearing a List

To remove all items from a list at once, you can call the Clear() method of either the ArrayList or the List class. Its syntax is:

Public Overridable Sub Clear

Deleting an Item

As opposed to adding a value to a list, you may want to remove one. To perform this operation, you have various options. You can ask the compiler to look for an item in the list and if, or once, the compiler finds it, it would delete the value. To perform this type of deletion, you can call the Remove() method of either the ArrayList or the List class. Its syntax is:

Public Overridable Sub Remove(obj As Object)
Public Function Remove(item As T) As Boolean

This method accepts as argument the value that you want to delete from the list. To perform this operation, the list must not be read-only. Here is an example:

Private Sub btnDelete_Click(ByVal sender As System.Object, _
                                ByVal e As System.EventArgs) _
                                Handles btnDelete.Click
        ListOfNames.Remove("Ursula Morales")
        lbxNames.Items.Clear()

        For Each strName As String In ListOfNames
            lbxNames.Items.Add(strName)
        Next
End Sub

The Remove() method allows you to specify the exact value you want to delete from a list. Another option you have consists of deleting a value based on its position. This is done using the RemoveAt() method whose syntax is:

Public Overridable Sub RemoveAt(index As Integer)

With this method, the position of the item is passed as argument. Here is an example:

Private Sub btnDelete_Click(ByVal sender As System.Object, _
                                ByVal e As System.EventArgs) _
                                Handles btnDelete.Click
        ListOfNames.RemoveAt(1)
        lbxNames.Items.Clear()

        For Each strName As String In ListOfNames
            lbxNames.Items.Add(strName)
        Next
End Sub

If the position is not valid because either it is lower or higher than the current Count, the compiler would throw an ArgumentOutOfRangeException exception.

Exercises

 

Musical Instrument Store

  1. Create a Windows Application named MusicInstrumentStore3
  2. Follow the instructions from the previous lesson to design the forms
  3. Use the ArrayList class to create and manage the list of store items
  4. Configure the application so that, if the user double-clicks an object in the Available Items list view:
    1. The Item Editor would open and display the information about the item that was clicked
    2. The Create button would display a caption as Submit
    3. The Close button would display a caption as Cancel
    4. The user can then change any detail about the item and click
    5. If the user clicks Submit, the (same) item would be updated in the database
    6. If the user clicks Cancel, the dialog box would be closed and the item would not receive any change
  5. Configure the Available Items list view so that, if the user clicks an item and presses Delete:
    1. A message box would ask the user, "Are you sure you want to remove this item from the database?" and would display two buttons: Yes and No
    2. If the user clicks Yes, the item would be removed from the database
    3. If the user clicks No, nothing would happen

College Park Auto Parts

  1. Open the CollegeParkAutoParts1 application from this lesson
  2. Add a context menu for the Available Parts list view with the items: Select, Edit..., and Delete
     
    AutoParts
  3. Configure the context menu so that
    1. If the user clicks Select, the behavior would be the same as if the user had double-clicked the item
    2. If the user clicks Edit..., the Part Editor dialog box would display with the part in it. The user can then edit any part (year, make, model, category, part name, or unit price) except the part number. Then the user can save the changed part
    3. If the user clicks Delete, a message box would warn the user and ask for confirmation with Yes/No answers. If the user clicks Yes, the part would be deleted from the list of auto parts
  4. Configure the application so that the user can open an order, add new parts to it, or delete parts from it, then save the order
  5. Extend the application so that the store can also sell items that are, or are not, car-related, such as books, t-shirts, cleaning items, maintenance items (steering oils, brake oils, etc), license plates, etc. Every item in the store should have an item number. The user can enter that item number in the Part # text box and press Tab or Enter. The corresponding item would then be retrieved from the database and displayed on the form. If there is no item with that number, a message box should let the user know

 


Previous Copyright 2008 Yevol Next