Home

Collections: Using IList

 

Locating an Item in the Collection

 

This Default Item of the Collection

While using a list, various operations require that you know the object you are currently accessing. To provide this operation, you must create an indexed property. This property should take an index and return the type of object that makes up the list. Here is an example:

Header File: BookList.h

#pragma once
using namespace System;
using namespace System::Collections;

public ref class CBookList : public IList
{
private:
    int counter;
    array<Object ^> ^ objects;

public:
    . . . No Change

    virtual property Object ^ default[int]
    {
        Object ^ get(int index) { return objects[index]; }

        void set(int index, Object ^ value)
        {
            objects[index] = value;
        }
    }
};

After creating this property, you can then access an item using its index and applying the [] operator on its instance. Remember that if you want to use for each, you must appropriately implement the IEnumerable::GetEnumerator() method.

Practical Learning Practical Learning: Identifying this Item in the Collection

  1. In the Class View, click CStoreItems
  2. In the lower part of the Class View, double-click default[int]
  3. Change the code of the property as follows:
     
    virtual property Object ^ default[int]
    {
        Object ^ get(int index)
        {
            return items[index];
        }
    
        void set(int index, Object ^ value)
        {
    	items[index] = value;
        }
    }
  4. In the Solution Explorer, double-click ItemEditor.h
  5. Double-click an unoccupied area of the form and implement its Load event as follows:
    System::Void ItemEditor_Load(System::Object^  sender, System::EventArgs^  e)
    {
        // Since all values seem ready, prepare to process the item
        CStoreItem ^ item = gcnew CStoreItem;
        CStoreItems ^ items = gcnew CStoreItems;
        BinaryFormatter ^ bfmStoreItem = gcnew BinaryFormatter;
    
        // This is the file that holds the list of items
        String ^ Filename = "C:\\Musical Instrument Store\\StoreItems.mis";
    
        if( File::Exists(Filename))
        {
            FileStream ^ stmStoreItem = gcnew FileStream(Filename,
                                                     FileMode::Open,
                                                     FileAccess::Read,
                                                     FileShare::Read);
    
            try
            {
                // Retrieve the list of items from file
                items = dynamic_cast<CStoreItems ^>
    		(bfmStoreItem->Deserialize(stmStoreItem));
    
                // Display the categories in the combo box
                for(int i = 0; i < items->Count; i++)
                {
                    item = static_cast<CStoreItem ^>(items[i]);
    
                    if (!cbxCategories->Items->Contains(item->Category))
                        cbxCategories->Items->Add(item->Category);
                }
    
                // Display the items types in the combo box
                for(int i = 0; i < items->Count; i++)
                {
                    item = static_cast<CStoreItem ^>(items[i]);
    
                    if (!cbxTypes->Items->Contains(item->Type))
                        cbxTypes->Items->Add(item->Type);
                }
            }
            finally
            {
                stmStoreItem->Close();
            }
        }
        else
        {
            // Create a random number that will be used
    	// to identify the item
            Random ^ rnd = gcnew Random;
            txtItemNumber->Text = rnd->Next(100000, 999999).ToString();
    
            // Make sure the user had selected a category
            cbxCategories->Text = L"";
            cbxTypes->Text = L"";
        }
    }
  6. In the Solution Explorer, right-click Form1.h and click View Code
  7. In the top section of the file, add the following code:
    #pragma once
    
    #include "StoreItems.h"
    #include "StoreItem.h"
    #include "ItemEditor.h"
    
    namespace MusicalInstrumentStore2 {
    
        using namespace System;
        using namespace System::ComponentModel;
        using namespace System::Collections;
        using namespace System::Windows::Forms;
        using namespace System::Data;
        using namespace System::Drawing;
        using namespace System::IO;
        using namespace System::Runtime::Serialization::Formatters::Binary;
    
    	/// <summary>
    	/// Summary for Form1
    	///
    	/// WARNING: If you change the name of this class, you will need to change the
    	///          'Resource File Name' property for the managed resource compiler tool
    	///          associated with all .resx files this class depends on.  Otherwise,
    	///          the designers will not be able to interact properly with localized
    	///          resources associated with this form.
    	/// </summary>
        public ref class Form1 : public System::Windows::Forms::Form
        {
        internal:
            CStoreItems ^ sItems;
            int iFilename;
            bool IsNewCustomerOrder;
    
  8. At the end of the document, create the following method:
    #pragma endregion
    
        internal:
    	void LoadMusicStore()
            {
                // Since all values seem ready, prepare to process the item
                sItems = gcnew CStoreItems;
                BinaryFormatter ^ bfmStoreItem = gcnew BinaryFormatter;
    
                // This is the file that holds the list of items
                String ^ Filename = L"C:\\Musical Instrument Store\\StoreItems.mis";
    
                if( File::Exists(Filename))
                {
                    FileStream ^ stmStoreItem = gcnew FileStream(Filename,
                                                             FileMode::Open,
                                                             FileAccess::Read,
                                                             FileShare::Read);
    
                    try
                    {
                        // Retrieve the list of items from file
                        sItems = dynamic_cast<CStoreItems ^>
    			(bfmStoreItem->Deserialize(stmStoreItem));
    
                        // Display the categories in the combo box
                        for (int i = 0; i < sItems->Count; i++)
                        {
                            CStoreItem ^ item = static_cast<CStoreItem ^>(sItems[i]);
    
                            if (!cbxCategories->Items->Contains(item->Category))
                                cbxCategories->Items->Add(item->Category);
                        }
                    }
                    finally
                    {
                        stmStoreItem->Close();
                    }
                }
            }
        };
    }
  9. Return to the Form1 form
  10. On the form, double-click New Store Item
  11. Implement the event as follows:
    System::Void btnNewStoreItem_Click(System::Object^  sender, System::EventArgs^  e)
    {
        ItemEditor ^ editor = gcnew ItemEditor;
    
        // Create a random number to get it ready for
        // the user creating a new store item
        Random ^ rnd = gcnew Random;
        editor->txtItemNumber->Text = rnd->Next(100000, 999999).ToString();
    
        if (editor->ShowDialog() == System::Windows::Forms::DialogResult::Cancel)
            LoadMusicStore();
    }
  12. Return to the Form1 form
  13. Double-click the Item Category combo box and implement its event as follows:
     
    System::Void cbxCategories_SelectedIndexChanged(System::Object^  sender, 
    				System::EventArgs^  e)
    {
        cbxTypes->Items->Clear();
        cbxTypes->Text = L"";
        lvwStoreItems->Items->Clear();
        pbxStoreItem->Image = nullptr;
    
        // If the current store inventory is empty, don't do anything
        if (sItems->Count == 0)
            return;
    
        // Get the item selected in the combo box
        String ^ strCategory = static_cast<String ^>(cbxCategories->SelectedItem);
    
        // Before doing anything, remove everything from the Types combo box
        // This eliminates the possibility of adding the same item(s) that
        // would exist already in the combo box
        cbxTypes->Items->Clear();
    
        // Check each item from the store inventory
        for(int i = 0; i < sItems->Count; i++)
        {
    	// Get the current item from the store inventory
            CStoreItem ^ item = static_cast<CStoreItem ^>(sItems[i]);
    
    	// If that item is the same as the one selected in the combo box...
            if (item->Category == strCategory)
            {
    	    // ... get ready to add its corresponding type
    	    // But check first that the type is not
    	    // already in the Types combo box
    	    // If it's not yet there, then add it
                if (!cbxTypes->Items->Contains(item->Type))
                    cbxTypes->Items->Add(item->Type);
            }
        }
    }
  14. Return to the Form1 form
  15. Double-click the Item Type combo box and implement its event as follows:
     
    System::Void cbxTypes_SelectedIndexChanged(System::Object^  sender, 
    			System::EventArgs^  e)
    {
        cbxTypes->Text = L"";
        pbxStoreItem->Image = nullptr;
    
        // If the current store inventory is empty, don't do anything
        if (sItems->Count == 0)
            return;
    
        // Get the item selected in the Categories combo box
        String ^ strCategory = static_cast<String ^>(cbxCategories->SelectedItem);
        // Get the item selected in theTypes combo box
        String ^ strType = static_cast<String ^>(cbxTypes->SelectedItem);
    
        // Empty the Available Items list view because 
        // we are about to (re)populate it
        lvwStoreItems->Items->Clear();
    
        // Check each item from the store inventory
        for (int i = 0; i < sItems->Count; i++)
        {
    	// Get the current item from the inventory
            CStoreItem ^ item = static_cast<CStoreItem ^>(sItems[i]);
    
    	// If the category of that item is the same as the one 
    	// selected in the combo box and the type of that item is 
    	// the same as the one selected in the Types combo box...
            if ((item->Category == strCategory) &&
                (item->Type == strType))
            {
    	    // ... then display it in the Available Items list view
                ListViewItem ^ lviStoreItem =
                    lvwStoreItems->Items->Add(item->ItemNumber);
                lviStoreItem->SubItems->Add(item->ItemName);
                lviStoreItem->SubItems->Add(item->UnitPrice.ToString(L"F"));
            }
        }
    }
  16. Return to the Form1 form
  17. On the form, double-click the Available Items list view and implement its SelectedIndexChanged event as follows:
     
    System::Void lvwStoreItems_SelectedIndexChanged(System::Object^  sender, 
    		System::EventArgs^  e)
    {
        CStoreItem ^ item = gcnew CStoreItem;
    
        if ((lvwStoreItems->SelectedItems->Count == 0) ||
            (lvwStoreItems->SelectedItems->Count > 1))
            return;
    
        String ^ strItemNumber =
    	lvwStoreItems->SelectedItems[0]->SubItems[0]->Text;
    
        for (int i = 0; i < sItems->Count; i++)
        {
            CStoreItem ^ itm = static_cast<CStoreItem ^>(sItems[i]);
            if (itm->ItemNumber == strItemNumber)
                item = itm;
        }
    
        // Make a list of the picture files
        String ^ strDirectory = L"C:\\Musical Instrument Store";
        DirectoryInfo ^ dirStoreItems = gcnew DirectoryInfo(strDirectory);
        array<FileInfo ^> ^ PictureFiles = dirStoreItems->GetFiles(L"*.jpg");
    
        // Look for a file that holds the same name as the item number
        for each( FileInfo ^ fle in PictureFiles)
        {
            // Get the name of the file without its extension
            String ^ fwe = Path::GetFileNameWithoutExtension(fle->FullName);
    
            if (fwe == strItemNumber)
                pbxStoreItem->Image = Image::FromFile(strDirectory + 
    		"\\" + item->ItemNumber+ L".jpg");
        }
    }
  18. Return to the Form1 form
  19. Click the first text box under the Item # label
  20. In the Properties window, click the Events button and double-click Leave
  21. Implement the event as follows:
     
    internal:
    void CalculateOrder()
    {
        // Calculate the current total order and update the order
        double subTotal1 = 0.00, subTotal2 = 0.00, subTotal3 = 0.00,
               subTotal4 = 0.00, subTotal5 = 0.00, subTotal6 = 0.00;
        double itemsTotal = 0.00, taxRate = 0.00,
               taxAmount = 0.00, orderTotal = 0.00;
    
        // Retrieve the value of each sub total
        try
        {
            subTotal1 = double::Parse(this->txtSubTotal1->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"Invalid Value");
        }
    
        try
        {
            subTotal2 = double::Parse(this->txtSubTotal2->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"Invalid Value");
        }
    
        try
        {
            subTotal3 = double::Parse(this->txtSubTotal3->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"Invalid Value");
        }
    
        try
        {
            subTotal4 = double::Parse(this->txtSubTotal4->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"Invalid Value");
        }
    
        try
        {
            subTotal5 = double::Parse(this->txtSubTotal5->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"Invalid Value");
        }
    
        try
        {
            subTotal6 = double::Parse(this->txtSubTotal6->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"Invalid Value");
        }
    
        // Calculate the total value of the sub totals
        itemsTotal = subTotal1 + subTotal2 + subTotal3 +
                     subTotal4 + subTotal5 + subTotal6;
    
        // Display the total order in the appropriate text box
        txtItemsTotal->Text = itemsTotal.ToString();
    
        try
        {
            taxRate = double::Parse(txtTaxRate->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"Invalid Tax Rate");
            txtTaxRate->Text = L"7.75";
            txtTaxRate->Focus();
        }
    
        taxAmount = itemsTotal * taxRate / 100;
        orderTotal = itemsTotal + taxAmount;
    
        txtTaxAmount->Text = taxAmount.ToString(L"F");
        txtOrderTotal->Text = orderTotal.ToString(L"F");
    }
    
    private: System::Void txtItemNumber1_Leave(System::Object^  sender, 
    		System::EventArgs^  e)
    {
        bool ItemFound = false;
        CStoreItem ^ sItem = gcnew CStoreItem;
        String ^ strItemNumber = txtItemNumber1->Text;
    
        for(int i = 0; i < sItems->Count; i++)
        {
    		sItem = safe_cast<CStoreItem ^>(sItems[i]);
    
            if (sItem->ItemNumber == strItemNumber)
            {
                ItemFound = true;
                txtDescription1->Text = sItem->ItemName;
                txtUnitPrice1->Text = sItem->UnitPrice.ToString(L"F");
                txtQuantity1->Text = L"1";
                txtSubTotal1->Text = sItem->UnitPrice.ToString(L"F");
    
    	    CalculateOrder();
            }
        }
    
        if (ItemFound == false)
        {
            txtDescription1->Text = L"";
            txtUnitPrice1->Text = L"0.00";
            txtQuantity1->Text = L"0";
            txtSubTotal1->Text = L"0.00";
        }
    }
  22. Return to the Form1 form
  23. On the form, click the top Unit Price text box
  24. Press and hold Shift
  25. Click the top Qty text box and release Shift
  26. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    System::Void txtUnitPrice1_Leave(System::Object^  sender, System::EventArgs^  e)
    {
        int quantity = 0;
        double unitPrice = 0.00, subTotal = 0.00;
    
        // Get the quantity of the current item
        try
        {
            quantity = int::Parse(this->txtQuantity1->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"Invalid quantity value for item 1");
        }
    
        // Get the unit price of the current item
        try
        {
            unitPrice = double::Parse(this->txtUnitPrice1->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"Invalid unit price for item 1");
        }
    
        // Calculate the current sub total
        subTotal = quantity * unitPrice;
    
        // Display the new sub total in the corresponding text box
        txtSubTotal1->Text = subTotal.ToString();
    
        btnRemove1->Enabled = true;
    
        // Update the order
        CalculateOrder();
    }
  27. Return to the Form1 form
  28. On the form, double-click the top Remove button and implement the event as follows:
     
    System::Void btnRemove1_Click(System::Object^  sender, System::EventArgs^  e)
    {
        txtItemNumber1->Text = L"";
        txtDescription1->Text = L"";
        txtUnitPrice1->Text = L"0.00";
        txtQuantity1->Text = L"0";
        txtSubTotal1->Text = L"0.00";
        btnRemove1->Enabled = false;
    
        CalculateOrder();
    }
  29. Return to the Form1 form
  30. On the form, click the second text box under the Item # label
  31. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    System::Void txtItemNumber2_Leave(System::Object^  sender, System::EventArgs^  e)
    {
        bool itemFound = false;
        CStoreItem ^ item = gcnew CStoreItem;
        String ^ strItemNumber = txtItemNumber2->Text;
    
        for (int i = 0; i < sItems->Count; i++ )
        {
            item = static_cast<CStoreItem ^>(sItems[i]);
    
            if (item->ItemNumber == strItemNumber)
            {
                itemFound = true;
                txtDescription2->Text = item->ItemName;
                txtUnitPrice2->Text = item->UnitPrice.ToString(L"F");
                txtQuantity2->Text = L"1";
                txtSubTotal2->Text = item->UnitPrice.ToString(L"F");
    
                CalculateOrder();
            }
        }
    
        if (itemFound == false)
        {
            txtDescription2->Text = L"";
            txtUnitPrice2->Text = L"0.00";
            txtQuantity2->Text = L"0";
            txtSubTotal2->Text = L"0.00";
        }
    }
  32. Return to the Form1 form
  33. On the form, click the second Unit Price text box
  34. Press and hold Shift
  35. Click the second Qty text box and release Shift
  36. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    System::Void txtUnitPrice2_Leave(System::Object^  sender, System::EventArgs^  e)
    {
        int qty = 0;
        double unitPrice = 0.00, subTotal = 0.00;
    
        try
        {
            qty = int::Parse(this->txtQuantity2->Text);
        }
        catch(FormatException ^)
        {
            // MessageBox::Show(L"Invalid quantity value for item 2");
        }
    
        try
        {
            unitPrice = double::Parse(this->txtUnitPrice2->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"Invalid unit price for item 2");
        }
    
        subTotal = qty * unitPrice;
        this->txtSubTotal2->Text = subTotal.ToString();
    
        btnRemove2->Enabled = true;
        CalculateOrder();
    }
  37. Return to the Form1 form
  38. On the form, double-click the second Remove button and implement the event as follows:
     
    System::Void btnRemove2_Click(System::Object^  sender, System::EventArgs^  e)
    {
        txtItemNumber2->Text = L"";
        txtDescription2->Text = L"";
        txtUnitPrice2->Text = L"0.00";
        txtQuantity2->Text = L"0";
        txtSubTotal2->Text = L"0.00";
        btnRemove2->Enabled = false;
    
        CalculateOrder();
    }
  39. Return to the Form1 form
  40. On the form, click the third text box under the Item # label
  41. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    System::Void txtItemNumber3_Leave(System::Object^  sender, System::EventArgs^  e)
    {
        bool ItemFound = false;
        CStoreItem ^ item = gcnew CStoreItem;
        String ^ strItemNumber = txtItemNumber3->Text;
    
        for (int i = 0; i < sItems->Count; i++ )
        {
            item = static_cast<CStoreItem ^>(sItems[i]);
    
            if (item->ItemNumber == strItemNumber)
            {
                ItemFound = true;
                txtDescription3->Text = item->ItemName;
                txtUnitPrice3->Text = item->UnitPrice.ToString(L"F");
                txtQuantity3->Text = L"1";
                txtSubTotal3->Text = item->UnitPrice.ToString(L"F");
    
                CalculateOrder();
            }
        }
    
        if (ItemFound == false)
        {
            txtDescription3->Text = L"";
            txtUnitPrice3->Text = L"0.00";
            txtQuantity3->Text = L"0";
            txtSubTotal3->Text = L"0.00";
        }
    }
  42. Return to the Form1 form
  43. On the form, click the third Unit Price text box
  44. Press and hold Shift
  45. Click the third Qty text box and release Shift
  46. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    System::Void txtUnitPrice3_Leave(System::Object^  sender, System::EventArgs^  e)
    {
        int qty = 0;
        double unitPrice = 0.00, subTotal = 0.00;
    
        try
        {
            qty = int::Parse(this->txtQuantity3->Text);
        }
        catch(FormatException ^)
        {
            // MessageBox::Show(L"Invalid quantity value for item 3");
        }
    
        try
        {
            unitPrice = double::Parse(this->txtUnitPrice3->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"Invalid unit price for item 3");
        }
    
        subTotal = qty * unitPrice;
        this->txtSubTotal3->Text = subTotal.ToString();
    
        btnRemove3->Enabled = true;
        CalculateOrder();
    }
  47. Return to the Form1 form
  48. On the form, double-click the third Remove button and implement the event as follows:
     
    System::Void btnRemove3_Click(System::Object^  sender, System::EventArgs^  e)
    {
        txtItemNumber3->Text = L"";
        txtDescription3->Text = L"";
        txtUnitPrice3->Text = L"0.00";
        txtQuantity3->Text = L"0";
        txtSubTotal3->Text = L"0.00";
        btnRemove3->Enabled = false;
    
        CalculateOrder();
    }
  49. Return to the Form1 form
  50. On the form, click the fourth text box under the Item # label
  51. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    System::Void txtItemNumber4_Leave(System::Object^  sender, System::EventArgs^  e)
    {
        bool ItemFound = false;
        CStoreItem ^ item = gcnew CStoreItem;
        String ^ strItemNumber = txtItemNumber4->Text;
    
        for (int i = 0; i < sItems->Count; i++ )
        {
            item = static_cast<CStoreItem ^>(sItems[i]);
    
            if (item->ItemNumber == strItemNumber)
            {
                ItemFound = true;
                txtDescription4->Text = item->ItemName;
                txtUnitPrice4->Text = item->UnitPrice.ToString(L"F");
                txtQuantity4->Text = L"1";
                txtSubTotal4->Text = item->UnitPrice.ToString(L"F");
    
                CalculateOrder();
            }
        }
    
        if (ItemFound == false)
        {
            txtDescription4->Text = L"";
            txtUnitPrice4->Text = L"0.00";
            txtQuantity4->Text = L"0";
            txtSubTotal4->Text = L"0.00";
        }
    }
  52. Return to the Form1 form
  53. On the form, click the fourth Unit Price text box
  54. Press and hold Shift
  55. Click the fourth Qty text box and release Shift
  56. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    System::Void txtUnitPrice4_Leave(System::Object^  sender, System::EventArgs^  e)
    {
        int qty = 0;
        double unitPrice = 0.00, subTotal = 0.00;
    
        try
        {
            qty = int::Parse(this->txtQuantity4->Text);
        }
        catch(FormatException ^)
        {
            // MessageBox::Show(L"Invalid quantity value for item 4");
        }
    
        try
        {
            unitPrice = double::Parse(this->txtUnitPrice4->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"Invalid unit price for item 4");
        }
    
        subTotal = qty * unitPrice;
        this->txtSubTotal4->Text = subTotal.ToString();
    
        btnRemove4->Enabled = true;
        CalculateOrder();
    }
  57. Return to the Form1 form
  58. On the form, double-click the fourth Remove button and implement the event as follows:
     
    System::Void btnRemove4_Click(System::Object^  sender, System::EventArgs^  e)
    {
        txtItemNumber4->Text = L"";
        txtDescription4->Text = L"";
        txtUnitPrice4->Text = L"0.00";
        txtQuantity4->Text = L"0";
        txtSubTotal4->Text = L"0.00";
        btnRemove4->Enabled = false;
    
        CalculateOrder();
    }
  59. Return to the Form1 form
  60. On the form, click the fifth text box under the Item # label
  61. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    System::Void txtItemNumber5_Leave(System::Object^  sender, System::EventArgs^  e)
    {
        bool ItemFound = false;
        CStoreItem ^ item = gcnew CStoreItem;
        String ^ strItemNumber = txtItemNumber5->Text;
    
        for (int i = 0; i < sItems->Count; i++ )
        {
            item = static_cast<CStoreItem ^>(sItems[i]);
    
            if (item->ItemNumber == strItemNumber)
            {
                ItemFound = true;
                txtDescription5->Text = item->ItemName;
                txtUnitPrice5->Text = item->UnitPrice.ToString(L"F");
                txtQuantity5->Text = L"1";
                txtSubTotal5->Text = item->UnitPrice.ToString(L"F");
    
                CalculateOrder();
            }
        }
    
        if (ItemFound == false)
        {
            txtDescription5->Text = L"";
            txtUnitPrice5->Text = L"0.00";
            txtQuantity5->Text = L"0";
            txtSubTotal5->Text = L"0.00";
        }
    }
  62. Return to the Form1 form
  63. On the form, click the fifth Unit Price text box
  64. Press and hold Shift
  65. Click the fifth Qty text box and release Shift
  66. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    System::Void txtUnitPrice5_Leave(System::Object^  sender, System::EventArgs^  e)
    {
        int qty = 0;
        double unitPrice = 0.00, subTotal = 0.00;
    
        try
        {
            qty = int::Parse(this->txtQuantity5->Text);
        }
        catch(FormatException ^)
        {
            // MessageBox::Show(L"Invalid quantity value for item 5");
        }
    
        try
        {
            unitPrice = double::Parse(this->txtUnitPrice5->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"Invalid unit price for item 5");
        }
    
        subTotal = qty * unitPrice;
        this->txtSubTotal5->Text = subTotal.ToString();
    
        btnRemove5->Enabled = true;
        CalculateOrder();
    }
  67. Return to the Form1 form
  68. On the form, double-click the fifth Remove button and implement the event as follows:
     
    System::Void btnRemove5_Click(System::Object^  sender, System::EventArgs^  e)
    {
        txtItemNumber5->Text = L"";
        txtDescription5->Text = L"";
        txtUnitPrice5->Text = L"0.00";
        txtQuantity5->Text = L"0";
        txtSubTotal5->Text = L"0.00";
        btnRemove5->Enabled = false;
    
        CalculateOrder();
    }
  69. Return to the Form1 form
  70. On the form, click the last text box under the Item # label
  71. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    System::Void txtItemNumber6_Leave(System::Object^  sender, System::EventArgs^  e)
    {
        bool ItemFound = false;
        CStoreItem ^ item = gcnew CStoreItem;
        String ^ strItemNumber = txtItemNumber6->Text;
    
        for (int i = 0; i < sItems->Count; i++ )
        {
            item = static_cast<CStoreItem ^>(sItems[i]);
    
            if (item->ItemNumber == strItemNumber)
            {
                ItemFound = true;
                txtDescription6->Text = item->ItemName;
                txtUnitPrice6->Text = item->UnitPrice.ToString(L"F");
                txtQuantity6->Text = L"1";
                txtSubTotal6->Text = item->UnitPrice.ToString(L"F");
    
                CalculateOrder();
            }
        }
    
        if (ItemFound == false)
        {
            txtDescription6->Text = L"";
            txtUnitPrice6->Text = L"0.00";
            txtQuantity6->Text = L"0";
            txtSubTotal6->Text = L"0.00";
        }
    }
  72. Return to the Form1 form
  73. On the form, click the sixth Unit Price text box
  74. Press and hold Shift
  75. Click the sixth Qty text box and release Shift
  76. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    System::Void txtUnitPrice6_Leave(System::Object^  sender, System::EventArgs^  e)
    {
        int qty = 0;
        double unitPrice = 0.00, subTotal = 0.00;
    
        try
        {
            qty = int::Parse(this->txtQuantity6->Text);
        }
        catch(FormatException ^)
        {
            // MessageBox::Show(L"Invalid quantity value for item 6");
        }
    
        try
        {
            unitPrice = double::Parse(this->txtUnitPrice6->Text);
        }
        catch(FormatException ^)
        {
            MessageBox::Show(L"Invalid unit price for item 6");
        }
    
        subTotal = qty * unitPrice;
        this->txtSubTotal6->Text = subTotal.ToString();
    
        btnRemove6->Enabled = true;
        CalculateOrder();
    }
  77. Return to the Form1 form
  78. On the form, double-click the sixth Remove button and implement the event as follows:
     
    System::Void btnRemove6_Click(System::Object^  sender, System::EventArgs^  e)
    {
        txtItemNumber6->Text = L"";
        txtDescription6->Text = L"";
        txtUnitPrice6->Text = L"0.00";
        txtQuantity6->Text = L"0";
        txtSubTotal6->Text = L"0.00";
        btnRemove6->Enabled = false;
    
        CalculateOrder();
    }
  79. Return to the Form1 form
  80. On the form, click the Tax Rate text box
  81. In the Events section of the Properties window, double-click Leave and implement the event as follows:
     
    System::Void txtTaxRate_Leave(System::Object^  sender, System::EventArgs^  e)
    {
        CalculateOrder();
    }
  82. Return to the Form1 form
  83. Double-click the New Order button and implement its event as follows:
     
    System::Void btnNewCustomerOrder_Click(System::Object^  sender, 
    			System::EventArgs^  e)
    {
        // We will store our files in the following folder    
        String ^ strDirectory = L"C:\\Musical Instrument Store\\Receipts";
        DirectoryInfo ^ dirInfo = Directory::CreateDirectory(strDirectory);
    
        // Get the list of files, if any, from our directory
        array<FileInfo ^> ^ fleList = dirInfo->GetFiles();
        String ^ Filename = L"";
    
        // If there is no file in the directory,
        // then we will use 1000 as the first file name
        if (fleList->Length == 0)
        {
            iFilename = 1000;
        }
        else // If there was at least one file in the directory
        {
            // Get a reference to the last file
            FileInfo ^ LastFile = fleList[fleList->Length - 1];
            // Get the name of the last file without its extension
            String ^ fwe = Path::GetFileNameWithoutExtension(LastFile->FullName);
            // Increment the name of the file by 1
            iFilename = int::Parse(fwe) + 1;
        }
    
        // Update our global name of the file
        Filename = strDirectory + L"\\" + iFilename.ToString() + L".cos";
        txtReceiptNumber->Text = iFilename.ToString();
    
        cbxCategories->Text = L"";
        cbxTypes->Text = L"";
        lvwStoreItems->Items->Clear();
    
        txtItemNumber1->Text = L"";
        txtDescription1->Text = L"";
        txtUnitPrice1->Text = L"0.00";
        txtQuantity1->Text = L"0";
        txtSubTotal1->Text = L"0.00";
    
        txtItemNumber2->Text = L"";
        txtDescription2->Text = L"";
        txtUnitPrice2->Text = L"0.00";
        txtQuantity2->Text = L"0";
        txtSubTotal2->Text = L"0.00";
    
        txtItemNumber3->Text = L"";
        txtDescription3->Text = L"";
        txtUnitPrice3->Text = L"0.00";
        txtQuantity3->Text = L"0";
        txtSubTotal3->Text = L"0.00";
    
        txtItemNumber4->Text = L"";
        txtDescription4->Text = L"";
        txtUnitPrice4->Text = L"0.00";
        txtQuantity4->Text = L"0";
        txtSubTotal4->Text = L"0.00";
    
        txtItemNumber5->Text = L"";
        txtDescription5->Text = L"";
        txtUnitPrice5->Text = L"0.00";
        txtQuantity5->Text = L"0";
        txtSubTotal5->Text = L"0.00";
    
        txtItemNumber6->Text = L"";
        txtDescription6->Text = L"";
        txtUnitPrice6->Text = L"0.00";
        txtQuantity6->Text = L"0";
        txtSubTotal6->Text = L"0.00";
    
        txtItemsTotal->Text = L"0.00";
        txtTaxRate->Text = L"7.75";
        txtTaxAmount->Text = L"0.00";
        txtOrderTotal->Text = L"0.00";
    }
  84. Return to the Form1 form
  85. Double-click the Save button and implement the event as follows:
     
    System::Void btnSave_Click(System::Object^  sender, System::EventArgs^  e)
    {
        // We will store our files in the following folder    
        String ^ strDirectory = L"C:\\Musical Instrument Store\\Receipts";
        DirectoryInfo ^ dirInfo = Directory::CreateDirectory(strDirectory);
    
        // Get the list of files, if any, from our directory
        array<FileInfo ^> ^ fleList = dirInfo->GetFiles();
        String ^ Filename = L"";
    
        // If this is a new customer order,
        // get ready to create a name for the file
        if (IsNewCustomerOrder == true)
        {
            // If there is no file in the directory,
            // then we will use 1000 as the first file name
            if (fleList->Length == 0)
            {
                iFilename = 1000;
            }
            else // If there was at least one file in the directory
            {
                // Get a reference to the last file
                FileInfo ^ LastFile = fleList[fleList->Length - 1];
                // Get the name of the last file without its extension
                String ^ fwe = Path::GetFileNameWithoutExtension(LastFile->FullName);
                // Increment the name of the file by 1
                iFilename = int::Parse(fwe) + 1;
            }
    
            // Update our global name of the file
            Filename = strDirectory + L"\\" + iFilename.ToString() + L".cos";
            txtReceiptNumber->Text = iFilename.ToString();
    
            IsNewCustomerOrder = false;
        } // If a cleaning order was already opened, we will simply update it
        else
            Filename = L"C:\\Musical Instrument Store\\Receipts\\" +
                        txtReceiptNumber->Text+ L".cos";
    
        StreamWriter ^ wrtCustomerOrder = gcnew StreamWriter(Filename);
    
        try {
            wrtCustomerOrder->WriteLine(txtItemNumber1->Text);
            wrtCustomerOrder->WriteLine(txtDescription1->Text);
            wrtCustomerOrder->WriteLine(txtUnitPrice1->Text);
            wrtCustomerOrder->WriteLine(txtQuantity1->Text);
    
            wrtCustomerOrder->WriteLine(txtItemNumber2->Text);
            wrtCustomerOrder->WriteLine(txtDescription2->Text);
            wrtCustomerOrder->WriteLine(txtUnitPrice2->Text);
            wrtCustomerOrder->WriteLine(txtQuantity2->Text);
    
            wrtCustomerOrder->WriteLine(txtItemNumber3->Text);
            wrtCustomerOrder->WriteLine(txtDescription3->Text);
            wrtCustomerOrder->WriteLine(txtUnitPrice3->Text);
            wrtCustomerOrder->WriteLine(txtQuantity3->Text);
    
            wrtCustomerOrder->WriteLine(txtItemNumber4->Text);
            wrtCustomerOrder->WriteLine(txtDescription4->Text);
            wrtCustomerOrder->WriteLine(txtUnitPrice4->Text);
            wrtCustomerOrder->WriteLine(txtQuantity4->Text);
    
            wrtCustomerOrder->WriteLine(txtItemNumber5->Text);
            wrtCustomerOrder->WriteLine(txtDescription5->Text);
            wrtCustomerOrder->WriteLine(txtUnitPrice5->Text);
            wrtCustomerOrder->WriteLine(txtQuantity5->Text);
    
            wrtCustomerOrder->WriteLine(txtItemNumber6->Text);
            wrtCustomerOrder->WriteLine(txtDescription6->Text);
            wrtCustomerOrder->WriteLine(txtUnitPrice6->Text);
            wrtCustomerOrder->WriteLine(txtQuantity6->Text);
    
            wrtCustomerOrder->WriteLine(txtItemsTotal->Text);
            wrtCustomerOrder->WriteLine(txtTaxRate->Text);
        }
        finally
        {
            wrtCustomerOrder->Close();
        }
    }
  86. Return to the Form1 form
  87. Double-click the Open button and implement its event as follows:
     
    System::Void btnOpen_Click(System::Object^  sender, System::EventArgs^  e)
    {
        String ^ strDirectory = L"C:\\Musical Instrument Store\\Receipts";
        String ^ strFilename  = 
    		L"C:\\Musical Instrument Store\\Receipts\\1000.cos";
    
        if (txtReceiptNumber->Text == L"")
            return;
        else
        {
            try {
                strFilename = strDirectory+ L"\\" +
                                      txtReceiptNumber->Text+ L".cos";
    
                StreamReader ^ rdrCustomerOrder = gcnew StreamReader(strFilename);
    
                try {
                    txtItemNumber1->Text = rdrCustomerOrder->ReadLine();
                    txtDescription1->Text = rdrCustomerOrder->ReadLine();
                    txtUnitPrice1->Text = rdrCustomerOrder->ReadLine();
                    txtQuantity1->Text = rdrCustomerOrder->ReadLine();
                    txtUnitPrice1_Leave(sender, e);
    
                    txtItemNumber2->Text = rdrCustomerOrder->ReadLine();
                    txtDescription2->Text = rdrCustomerOrder->ReadLine();
                    txtUnitPrice2->Text = rdrCustomerOrder->ReadLine();
                    txtQuantity2->Text = rdrCustomerOrder->ReadLine();
                    txtUnitPrice2_Leave(sender, e);
    
                    txtItemNumber3->Text = rdrCustomerOrder->ReadLine();
                    txtDescription3->Text = rdrCustomerOrder->ReadLine();
                    txtUnitPrice3->Text = rdrCustomerOrder->ReadLine();
                    txtQuantity3->Text = rdrCustomerOrder->ReadLine();
                    txtUnitPrice3_Leave(sender, e);
    
                    txtItemNumber4->Text = rdrCustomerOrder->ReadLine();
                    txtDescription4->Text = rdrCustomerOrder->ReadLine();
                    txtUnitPrice4->Text = rdrCustomerOrder->ReadLine();
                    txtQuantity4->Text = rdrCustomerOrder->ReadLine();
                    txtUnitPrice4_Leave(sender, e);
    
                    txtItemNumber5->Text = rdrCustomerOrder->ReadLine();
                    txtDescription5->Text = rdrCustomerOrder->ReadLine();
                    txtUnitPrice5->Text = rdrCustomerOrder->ReadLine();
                    txtQuantity5->Text = rdrCustomerOrder->ReadLine();
                    txtUnitPrice5_Leave(sender, e);
    
                    txtItemNumber6->Text = rdrCustomerOrder->ReadLine();
                    txtDescription6->Text = rdrCustomerOrder->ReadLine();
                    txtUnitPrice6->Text = rdrCustomerOrder->ReadLine();
                    txtQuantity6->Text = rdrCustomerOrder->ReadLine();
                    txtUnitPrice6_Leave(sender, e);
    
                    txtItemsTotal->Text = rdrCustomerOrder->ReadLine();
                    txtTaxRate->Text = rdrCustomerOrder->ReadLine();
    
                    CalculateOrder();
                    IsNewCustomerOrder = false;
                }
                finally
                {
                    rdrCustomerOrder->Close();
                }
            }
            catch (FileNotFoundException ^)
            {
                MessageBox::Show(L"There is no customer order " 
    			                 L"with that receipt number");
            }
        }
    }
  88. Return to the Form1 form
  89. Double-click an unoccupied area of the form and implement the event as follows:
     
    System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e)
    {
        btnNewCustomerOrder_Click(sender, e);
        LoadMusicStore();
        IsNewCustomerOrder = true;
    }
  90. Return to the Form1 form
  91. Double-click the Close and implement its Click event as follows:
     
    System::Void btnClose_Click(System::Object^  sender, System::EventArgs^  e)
    {
        Close();
    }
  92. Execute the application to test it
  93. Access the Item Editor dialog box and create a few items as follows (let the computer create the item numbers):
     
    Category Type Item Name Unit Price Picture
    Guitars Electric Gibson Les Paul Vintage Mahogany Electric Guitar 745.95 Picture
    Bass Electric 4-String Epiphone Thunderbird IV Bass 325.85 Picture
    Keyboards Synthesizers Alesis QS8.2 88 Key Synthesizer 825.50 Picture
    Guitars Acoustic Gretsch Guitars G100 Synchromatic Archtop Acoustic Guitar 595.95 Picture
    Drums Drum Set Pulse Pro 5-Piece Drum Set with Cymbals 395.95 Picture
    Keyboards Pianos Roland RD-700SX Digital Piano 2195.00  
    Accessories Cables Mogami Gold AES/EBU Interconnect Cable with Neutrik XLR 45.85  
    Guitars Acoustic-Electric Ibanez V Series V70CE Dreadnought Cutaway Acoustic-Electric Guitar 225.50  
    Guitars Electric Schecter C-1 Hellraiser Electric Guitar 650.00 Picture
    Keyboards Synthesizers Roland V Synth GT Elastic Audio Synthesizer Keyboard 2895.50 Picture
    Bass Electric 5-String Fender Jazz Bass 24 V 5-String Bass Guitar 825.50 Picture
    Guitars Electric Fender Standard Stratocaster Left-Handed Electric Guitar 425.85 Picture
    Recording Microphone MXL V63M Studio Condenser Microphone 72.95 Picture
    Guitars Acoustic Yamaha FD01S Acoustic Folk Guitar 185.95  
    Book/CD/DVD Instructional Hal Leonard Amazing Phrasing - Alto Sax (Book/CD) 18.00  
    Guitars Classical & Nylon Alvarez Artist Series AC60S Classical Acoustic Guitar 275.95 Picture
    Guitars Acoustic Washburn D100DL Acoustic Guitar 150.50 Picture
    Drums Electronic Percussion Boss DR-670 Dr. Rhythm Drum Machine 275.85 Picture
    Recording Microphone Shure SM58 Mic 95.95 Picture
    Accessories Cables Live Wire HPE325 Headphone and Extension Cable 10.95 Picture
    Bass Acoustic Fretted Ibanez AEB10E Acoustic-Electric Bass Guitar with Onboard Tuner 350.00 Picture
    Drums World Percussion Latin Percussion Conga 3-Pack with Bongos 595.95 Picture
    Keyboards Synthesizers Roland JUNO-D 61-Key Synthesizer 595.95 Picture
    Drums World Percussion Latin Percussion Aspire Conga Set with Bongos and Stand 425.50 Picture
    Recording Microphone AKG Perception 200 Condenser Microphone 160.00 Picture
     
    Musical Instrument Store: Item Category
    Music Store
  94. Close the Item Editor form
  95. Create a few customers' orders and click Save then New Order each time. Here are examples:
     
    Musical Instrument Store: Customer Order
    Musical Instrument Store: Customer Order
  96. Close the form and return to your programming environment
 

 

 

Enumerating the Collection for each Item

One of the most valuables features of the C# is the ability to use the for each loop to enumerate the members of a collection. To make this possible, you must implement the IEnumerator interface in your collection class. Following the rules of interface implementation, you must override the members of IEnumerator

Checking the Existence of an Item

One of the routine operations you can perform on a list is to find out whether it contains a certain value. To assist you with this operation, the System::Collections::IList interface is equipped with a method named Contains. Its syntax is:

bool Contains(object value);

This method takes as argument the value to look for. If the value is found in the list, the method returns true. If no value is found in the collection, this method returns false.

Here is an example of implementing this method:

Header File: BookList.h

#pragma once
using namespace System;
using namespace System::Collections;

public ref class CBookList : public IList
{
private:
    int counter;
    array<Object ^> ^ objects;

public:
    . . . No Change

    virtual bool Contains(Object ^ value);
};

Source File: BookList.cpp

#include "BookList.h"

. . . No Change

bool CBookList::Contains(Object ^ value)
{
    for (int i = 0; i < Count; i++)
        if (objects[i] == value)
            return true;
    return false;
}

This method calls the Equals() method of the objects that make up the list to find out whether the value argument exists in the collection. If this method produces a wrong result, especially if you are using your own class to represent the item, you may have to override your own Equals() method.

Getting the Index of an Item

The System::Collections::IList::Contains() method is used to check whether a particular value (already) exists in the collection. If you know that a certain item exists in the collection but you don't know its index inside the list, the IList interface can assist you through a method named IndexOf. Its syntax is:

int IndexOf(Object^ value);

This method takes as argument the value to look for in the list. If the value is found in the collection, the method returns its index. If there is no value defined like that, the method returns -1. Here is an example of implementing this method:

Header File: BookList.h

#pragma once
using namespace System;
using namespace System::Collections;

public ref class CBookList : public IList
{
private:
    int counter;
    array<Object ^> ^ objects;

public:
    . . . No Change

    virtual bool Contains(Object ^ value);
    virtual int IndexOf(Object ^ value);
};

Source File: BookList.cpp

#include "BookList.h"

. . . No Change

int CBookList::IndexOf(Object ^ value)
{
    for (int i = 0; i < Count; i++)
        if (objects[i] == value)
            return i;
    return -1;
}
 

This method calls the Equals() method of the objects that make up the collection to find out whether the value argument exists in the list. If this method produces a wrong result, especially if you are using your own class to represent the value, you may have to override your own Equals() method.

Deleting Values in the List

 

Deleting a Value by its Index

If a value is not necessary in your list, you can delete it. Probably the simplest way to delete a value is to specify its position in the list. To support this operation, both the System::Collections::IList and the System::Collections::Generic::IList interfaces are equipped with a method named RemoveAt. The syntax of the RemoveAt() method is is the same for both interfaces and it is:

void RemoveAt(int index);

This method takes as argument the index of the value to be removed. Here is an example:

Header File: BookList.h

#pragma once
using namespace System;
using namespace System::Collections;

public ref class CBookList : public IList
{
private:
    int counter;
    array<Object ^> ^ objects;

public:
    . . . No Change

    virtual bool Contains(Object ^ value);
    virtual int IndexOf(Object ^ value);
    virtual void RemoveAt(int index);
};

Source File: BookList.cpp

#include "BookList.h"

. . . No Change

void CBookList::RemoveAt(int index)
{
    if ((index >= 0) && (index < Count))
    {
        for (int i = index; i < Count - 1; i++)
            objects[i] = objects[i + 1];
        counter--;
    }
}

Deleting an Item by its Value

The problem with deleting a value based on its index is that, if you are not sure, you could delete the wrong value. An alternative is to first precisely define the value you want to get rid of, and then hand the value itself to the compiler that would remove it. To support this approach, the System::Collections::IList interface is equipped with a method named Remove() and whose syntax is:

void Remove(Object^ value);

This method takes as argument the value to be deleted. This means that the compiler will first look for the value in the list. If it finds that value, it removes it. If there is no value like that, nothing happens (the compiler doesn't throw an exception. Here is an example of implementing this method:

Header File: BookList.h

#pragma once
using namespace System;
using namespace System::Collections;

public ref class CBookList : public IList
{
private:
    int counter;
    array<Object ^> ^ objects;

public:
    . . . No Change

    virtual bool Contains(Object ^ value);
    virtual int IndexOf(Object ^ value);
    virtual void RemoveAt(int index);
    virtual void Remove(Object ^ value);
};

Source File: BookList.cpp

#include "BookList.h"

. . . No Change

void CBookList::Remove(Object ^ value)
{
    RemoveAt(IndexOf(value));
}

Clearing a Collection

To remove all value from a list at once, you can implement Clear() method of the System::Collections::IList interface. Its syntax is:

void Clear();

Here is an example of implementing it:

Header File: BookList.h

#pragma once
using namespace System;
using namespace System::Collections;

public ref class CBookList : public IList
{
private:
    int counter;
    array<Object ^> ^ objects;

public:
    CBookList(void);

    virtual property int Count
    {
        int get() { return counter; }
    }

    virtual property bool IsSynchronized
    {
        bool get() { return false; }
    }

    virtual property Object ^ SyncRoot
    {
        Object ^ get() { return this; }
    }

    virtual void CopyTo(Array ^ ary, int index);
    virtual IEnumerator ^ GetEnumerator();

    virtual property bool IsFixedSize
    {
        bool get() { return false; }
    }

    virtual property bool IsReadOnly
    {
        bool get() { return false; }
    }

    virtual int Add(Object ^ value);
    virtual void Insert(int index, Object ^ value);

    virtual property Object ^ default[int]
    {
        Object ^ get(int index) { return objects[index]; }

        void set(int index, Object ^ value)
        {
            objects[index] = value;
        }
    }

    virtual bool Contains(Object ^ value);
    virtual int IndexOf(Object ^ value);
    virtual void RemoveAt(int index);
    virtual void Remove(Object ^ value);
    virtual void Clear();
};

Source File: BookList.cpp

#include "BookList.h"

CBookList::CBookList(void)
	: counter(0),
      objects(gcnew array<Object ^>(5))
{
}

void CBookList::CopyTo(Array ^ ary, int index)
{
}

IEnumerator ^ CBookList::GetEnumerator()
{
    return nullptr;
}

int CBookList::Add(Object ^ value)
{
    // Check whether there is still room in
    // the array to add a new item
    if (counter < objects->Length)
    {
        // Since there is room, put the new item to the end
        objects[counter] = value;
        // increase the number of items
        counter++;
        // Return the index of the item that was added
        return counter - 1;
    } // Since the item could not be added, return a negative index
    else
        return -1;
}

void CBookList::Insert(int index, Object ^ value)
{
}

bool CBookList::Contains(Object ^ value)
{
    for (int i = 0; i < Count; i++)
        if (objects[i] == value)
            return true;
    return false;
}

int CBookList::IndexOf(Object ^ value)
{
    for (int i = 0; i < Count; i++)
        if (objects[i] == value)
            return i;
    return -1;
}

void CBookList::RemoveAt(int index)
{
    if ((index >= 0) && (index < Count))
    {
        for (int i = index; i < Count - 1; i++)
            objects[i] = objects[i + 1];
        counter--;
    }
}

void CBookList::Remove(Object ^ value)
{
    RemoveAt(IndexOf(value));
}

void CBookList::Clear()
{
    counter = 0;
}

Download:

Musical Instrument Store2

 
 
   
 

Previous Copyright © 2009-2016, FunctionX, Inc. Home