Home

Example Application: Solo Music Store

     

Introduction

This application applies the concept of implementing a collection class using the techniques of the .NET Framework. It is a fictitious company that sells musical instruments such as keyboards, pianos, drums, and related accessories (books, software, hardware, etc).

.

Practical LearningPractical Learning: Creating the Application

  1. Start Microsoft Visual Studio
  2. Create a new Windows Application named SoloMusicStore1
  3. To save the project, on the Standard toolbar, click the Save All button Save All
  4. Accept all options and click Save
  5. To create a dialog box, on the main menu, click Project -> Add Windows Form...
  6. Set the name to ItemCategory and click Add
  7. Design the form as follows:
     
    Item Category
    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
  8. To create a dialog box, on the main menu, click Project -> Add Windows Form...
  9. Set the name to ItemType and click Add
  10. Design the form as follows:
     
    Musical Store Item Type
    Control Text Name Other Properties
    Label &Item Type:    
    TextBox   txtItemType Modifiers: Public
    Button OK btnOK DialogResult: OK
    Button Cancel btnCancel DialogResult: Cancel
    Form Property Value
    FormBorderStyle FixedDialog
    Text Type Editor
    StartPosition CenterScreen
    AcceptButton btnOK
    CancelButton btnCancel
    MaximizeBox False
    MinimizeBox False
    ShowInTaskbar False
  11. To create a dialog box, in the Solution Explorer, right-click SoloMusic1 -> Add -> Windows Form...
  12. Set the name to ItemEditor and click Add
  13. Design the form as follows:
     
    Musical Store Item
     
    Control Text Name Other Properties
    Label &Item #:    
    TextBox   txtItemNumber  
    Label &Category:    
    ComboBox   cbxCategories  
    Button New C&ategory... btnNewCategory  
    Label &Item Type:    
    ComboBox   cbxItemTypes  
    Button New &Item Type... btnNewItemType  
    Label Item &Name:    
    TextBox   txtItemName  
    Label &Unit Price:    
    TextBox 0.00 txtUnitPrice TextAlign: Right
    Button Picture... btnPicture  
    TextBox   txtPicturePath  
    PictureBox   pbxPicturePath SizeMode: Zoom
    Button Create btnCreate  
    Button Close btnClose DialogResult: Cancel
    OpenFileDialog (Name): dlgOpen
    Title: Select Item Picture
    DefaultExt: jpg
    Filter: JPEG Files (*.jpg,*.jpeg)|*.jpg|GIF Files (*.gif)|*.gif|Bitmap Files (*.bmp)|*.bmp|PNG Files (*.png)|*.png
    Form Property Value
    FormBorderStyle FixedDialog
    Text Musical Instrument Store - Item Editor
    StartPosition CenterScreen
    MaximizeBox False
    MinimizeBox False
    ShowInTaskbar False
  14. Double-click the New Category button and implement it as follows:
    private void btnNewCategory_Click(object sender, EventArgs e)
    {
        var editor = new ItemCategory();
    
        if (editor.ShowDialog() == DialogResult.OK)
        {
            if (editor.txtCategory.Text.Length > 0)
            {
                var NewCategory = editor.txtCategory.Text;
    
                // Make sure the category is not yet in the list
                if (cbxCategories.Items.Contains(NewCategory))
                    MessageBox.Show(NewCategory + " is already in the list");
                else
                {
                    // Since this is a new category, add it to the combox box
                    cbxCategories.Items.Add(NewCategory);
                    // Just in case the user wanted to use this new category
                    // select it
                    cbxCategories.Text = NewCategory;
                }
            }
        }
    }
  15. Return to the Item Editor dialog box and double-click the New Item Type button
  16. Implement the event as follows:
    private void btnNewItemType_Click(object sender, EventArgs e)
    {
        var editor = new ItemType();
    
        if (editor.ShowDialog() == DialogResult.OK)
        {
            if (editor.txtItemType.Text.Length > 0)
            {
                string NewType = editor.txtItemType.Text;
    
                // Make sure the type is not yet in the list
                if (cbxTypes.Items.Contains(NewType))
                    MessageBox.Show("The list already contains " +
                                    NewType);
                else
                {
                    cbxTypes.Items.Add(NewType);
                    cbxTypes.Text = NewType;
                 }
            }
        }
    }
  17. Return to the Item Editor dialog box and double-click the Picture button
  18. Implement the event as follows:
    private void btnPicture_Click(object sender, EventArgs e)
    {
        if (dlgPicture.ShowDialog() == DialogResult.OK)
        {
            txtPicturePath.Text = dlgPicture.FileName;
            pbxStoreItem.Image = Image.FromFile(txtPicturePath.Text);
        }
    }
  19. In the Solution Explorer, right-click Form1.cs and click Rename
  20. Type MusicStore.cs and press Enter twice (to display the form)
  21. Design the form as follows:
     
    Musical Instrument Store
     
    Control Text Name Other Properties
    Label Label Item Category:    
    ComboBox ComboBox   cbxCategories  
    Label Label Items Type:    
    ComboBox ComboBox   cbxTypes  
    Label Label Available Items    
    Button Button New Store Item... btnNewStoreItem  
    ListView ListView   lvwStoreItems View: Details
    FullRowSelect: True
    GridLines: True
    Columns
    (Name) Text TextAlign Width
    colItemNumber Item #    
    colItemName Item Name/Description   320
    colUnitPrice Unit Price Right  
    PictureBox   pbxStoreItem SizeMode: Zoom
    Label Label Selected Items    
    DataGridView DataGridView Item #    
    Label Label Description    
    Columns
    (Name) HeaderText Width ReadOnly
    dgvItemNumber Item # 65  
    dgvItemName Item Name/Description 220  
    dgvUnitPrice Unit Price 70  
    dgvQuantity Qty 40  
    dgvSubTotal Sub-Total 80 True
    GroupBox GroupBox Order Summary    
    Label Label Items Total:    
    TextBox TextBox 0.00 txtItemsTotal TextAlign: Right
    Label Label Tax Rate:    
    TextBox TextBox 7.75   TextAlign: Right
    Label Label %    
    Label Label Tax Amount:    
    TextBox TextBox 0.00 txtTaxAmount TextAlign: Right
    Label Label Order Total:    
    TextBox TextBox 0.00 txtOrderTotal TextAlign: Right
    Button Button Save btnSave  
    Label Label Receipt #:    
    TextBox TextBox 0.00 txtReceiptNumber  
    Button Button &Open btnOpen  
    Button Button New Order btnNewOrder  
    Button Button Close btnClose  
  22. Double-click the New Store Item button
  23. Implement the event as follows:
    private void btnNewStoreItem_Click(object sender, EventArgs e)
    {
        var editor = new ItemEditor();
    
        // Create a random number to get it ready for
        // the user creating a new store item
        var rndNumber = new Random();
        editor.txtItemNumber.Text = rndNumber.Next(100000, 999999).ToString();
    
        editor.ShowDialog();
    }
  24. To create a new class, in the Class View, right-click SoloMusicStore1 -> Add -> Class...
  25. Set the Name to StoreItem and press Enter
  26. Change the file as follows:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace SoloMusic1
    {
        [Serializable]
        public class StoreItem
        {
            private string nbr;
            private string cat;
            private string tp;
            private string nm;
            private double prc;
    
            public string ItemNumber
            {
                get { return nbr; }
                set { nbr = value; }
            }
    
            public string Category
            {
                get { return cat; }
                set { cat = value; }
            }
    
            public string Type
            {
                get { return tp; }
                set { tp = value; }
            }
    
            public string ItemName
            {
                get { return nm; }
                set { nm = value; }
            }
    
            public double UnitPrice
            {
                get { return prc; }
                set { prc = value; }
            }
    
            public virtual bool Equals(StoreItem same)
            {
                if( (nbr == same.nbr) &&
                    (cat == same.cat) &&
                    (tp  == same.tp) &&
                    (nm  == same.nm) &&
                    (prc == same.prc))
                    return true;
                else
                    return false;
            }
    
            public StoreItem()
            {
                nbr = "000000";
                cat = "Accessories";
                tp  = "Accessories";
                nm  = "Unknown";
                prc = 0.00;
            }
    
            public StoreItem(string itmNumber)
            {
                nbr = itmNumber;
                cat = "Accessories";
                tp  = "Accessories";
                nm  = "Unknown";
                prc = 0.00;
            }
    
            public StoreItem(string itmNumber, string category,
                      string type, string name, double price)
            {
                nbr = itmNumber;
                cat = category;
                tp  = type;
                nm  = name;
                prc = price;
            }
    
            public override string ToString()
            {
                return string.Format("Item #:\t{0}\nCategory:\t{1}\n" +
                                     "Item Type:\t{2}\nItem Name:\t{3}\n" +
                                     "Unit Price:\t{4}", nbr, cat, tp, nm, prc);
            }
        }
    }
  27. To create a new class, in the Class View, right-click SoloMusic1 -> Add -> Class...
  28. Set the Name to SoldItem and press Enter
  29. Change the file as follows:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace SoloMusic1
    {
        [Serializable]
        public class SoldItem
        {
            private string nbr;
            private string nm;
            private double prc;
            private int count;
            private double total;
    
            public string ItemNumber
            {
                get { return nbr; }
                set { nbr = value; }
            }
    
            public string ItemName
            {
                get { return nm; }
                set { nm = value; }
            }
    
            public double UnitPrice
            {
                get { return prc; }
                set { prc = value; }
            }
    
            public int Quantity
            {
                get { return count; }
                set { count = value; }
            }
    
            public double  SubTotal
            {
                get { return total; }
                set { total = value; }
            }
    
            public virtual bool Equals(SoldItem same)
            {
                if( (nbr == same.nbr) &&
                    (nm  == same.nm) &&
                    (prc == same.prc) &&
                    (count == same.count) &&
                    (total  == same.total))
                    return true;
                else
                    return false;
            }
    
            public SoldItem()
            {
                nbr = "000000";
                nm  = "Unknown";
                prc = 0.00;
                count = 0;
                total  = 0.00D;
            }
    
            public SoldItem(string itmNumber, string name,
                             double price, int qty,
                double sub)
            {
                nbr = itmNumber;
                nm  = name;
                prc = price;
                count = qty;
                total   = sub;
            }
    
            public override string ToString()
            {
                return string.Format("Item #:\t{0}\nItem Name:\t{1}\n" +
                                 "Unit Price:\t{2}\nQuantity:\t{3}\nSub-Total:\t{4}",
                                     nbr, nm, prc, count, total);
            }
        }
    }
  30. Save all
 

Practical LearningPractical Learning: Starting an IList Implementation

  1. To create a new class, in the Class View, right-click SoloMusicStore1 -> Add -> Class...
  2. Set the Name to StoreItems and press Enter
  3. Change the file as follows:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace MusicStore1
    {
        [Serializable]
        public class StoreItems<T> : IList<T>
        {
        }
    }
  4. In the Code Editor, right-click IList<>, position the mouse on Implement Interface, and click Implement Interface
     
    Implement Interface
  5. Based on issues we have already studied, change the document as follows:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace MusicStore1
    {
        [Serializable]
        public class StoreItems<T> : IList<T>
        {
            // This field will be used to keeep a count of
            // the items as they are added or removed
            int counter;
            // This array holds the items of the collection
            private T[] objects;
    
            // The default constructor is used to initialize the collection
            public StoreItems()
            {
                counter = 0;
                objects = new T[10];
            }
    
    // This method makes it possible to have a collection whose size can increase.
    	// This method checks the size of the array.
    	// If it is too small, its size gets increase.
            private void CheckToIncreaseSize()
            {
                if (counter >= objects.Length)
                    Array.Resize<T>(ref objects, objects.Length + 5);
            }
    
            #region IList<T> Members
    
            // This method is used to check whether the item passed as
            // argument exists in the collection. If so, it returns its index
            public int IndexOf(T item)
            {
                throw new NotImplementedException();
            }
    
            // This method can be used to insert an item at 
            // a certain position inside the collection
            public void Insert(int index, T item)
            {
                throw new NotImplementedException();
            }
    
            // This method is used to delete the item positioned 
            // at the index passed as argument
            public void RemoveAt(int index)
            {
                throw new NotImplementedException();
            }
    
            // This indexed property is used to represent an item based on its index
    	public T this[int index]
    	{
        	    // The get accessor is used to access the item at a specific index
        	    get
    	    {
    	        return objects[index];
    	    }
    	    // The set accessor can be used to replace the item at a specific index
    	    // or to add a new item to the end of the collection
    	    set
                {
            	objects[index] = value;
        	    }
    	}
    
            #endregion
    
            #region ICollection<T> Members
    
            // This method is used to add a new item to the collection
            public void Add(T item)
            {
                // Find out if the array is getting too small for the next item(s)
                // If it is, increase its size by 5
                CheckToIncreaseSize();
    
                // Add the item at the end
                this.objects[this.counter] = item;
                // Increase the current number of items
                this.counter++;
            }
    
            // This methods deletes all items from the collection
            public void Clear()
            {
                throw new NotImplementedException();
            }
    
            // This method is used to find out whether the item 
            // passed as argument exists in the collection
            public bool Contains(T item)
            {
                throw new NotImplementedException();
            }
    
            // This method is used to copy the items of this collection
            // to another variable passed as argument
            public void CopyTo(T[] array, int arrayIndex)
            {
                T[] values = new T[arrayIndex];
    
                for (int i = 0; i < counter; i++)
                    values[i] = objects[i];
    
                array = values;
            }
    
            // This read-only property holds
            // the total number of items in the collection
            public int Count
            {
                get { return counter; }
            }
    
            // This property indicates whether the collection can receive new items
            public bool IsReadOnly
            {
                get { throw new NotImplementedException(); }
            }
    
            // This method first checks the existence of the item passed 
            //  as argument. If the item exists, the method deletes it
            public bool Remove(T item)
            {
                throw new NotImplementedException();
            }
    
            #endregion
    
            #region IEnumerable<T> Members
    
            public IEnumerator<T> GetEnumerator()
            {
                int number = 0;
    
                while (number < Count)
                {
                    yield return objects[number];
                    number++;
                }
            }
    
            #endregion
    
            #region IEnumerable Members
    
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                int number = 0;
    
                while (number < Count)
                {
                    yield return objects[number];
                    number++;
                }
            }
    
            #endregion
        }
    }
  6. Save the file
 

Practical LearningPractical Learning: Adding an Item to the Collection

  1. In the Class View, expand SoloMusicStore1 followed by SoloMusicStore1. Double-click ItemEditor
  2. In the top section of the file, add the following:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
  3. In the Solution Explorer, double-click ItemEditor.cs
  4. On the form, double-click the Create button
  5. Implement the event as follows:
    private void btnCreate_Click(object sender, EventArgs e)
    {
        FileStream stmStoreItem = null;
        var item = new StoreItem();
        var items = new StoreItems<StoreItem>();
        var bfmStoreItem = new BinaryFormatter();
    
        // If this directory doesn't exist, create it
        Directory.CreateDirectory(@"C:\Solo Music Store");
        // This is the file that holds the list of items
        var Filename = @"C:\Solo Music Store\StoreItems.slm";
    
        // Create a random number that will be used to identify the item
        var rnd = new Random();
        txtItemNumber.Text = rnd.Next(100000, 999999).ToString();
    
        // Make sure the user had selected a category
        if (cbxCategories.Text.Length == 0)
        {
            MessageBox.Show("You must specify the item's category");
            cbxCategories.Focus();
            return;
        }
    
        // Make sure the user had selected a type
        if (cbxTypes.Text.Length == 0)
        {
            MessageBox.Show("You must specify the item's type");
            cbxTypes.Focus();
            return;
        }
    
        // Make sure the user had entered a name/description
        if (txtItemName.Text.Length == 0)
        {
             MessageBox.Show("You must enter the name (or a " +
                             "short description) for the item");
             txtItemName.Focus();
             return;
        }
    
        // Make sure the user had typed a price for the item
        if (txtUnitPrice.Text.Length == 0)
        {
             MessageBox.Show("You must enter the price of the item");
             txtUnitPrice.Focus();
             return;
        }
    
        // Before saving the new item, find out if there was
        // already a file that holds the list of items
        // If that file exists, open it and store its items 
        // in our StoreItems list
        if (File.Exists(Filename))
        {
             stmStoreItem = new FileStream(Filename,
                                           FileMode.Open,
                                           FileAccess.Read,
                                           FileShare.Read);
    
             try
             {
                  // Retrieve the list of items from file
                  items = (StoreItems<StoreItem>)bfmStoreItem.Deserialize(stmStoreItem);
             }
             finally
             {
                 stmStoreItem.Close();
             }
        }
    
        // Create the music item
        item.ItemNumber = txtItemNumber.Text;
        item.Category = cbxCategories.Text;
        item.Type = cbxTypes.Text;
        item.ItemName = txtItemName.Text;
        item.UnitPrice = double.Parse(txtUnitPrice.Text);
    
        // Call the Add method of our collection class to add the item
        items.Add(item);
    
        // Save the list
        stmStoreItem = new FileStream(Filename,
                                      FileMode.Create,
                                      FileAccess.Write,
                                      FileShare.Write);
    
        try
        {
              bfmStoreItem.Serialize(stmStoreItem, items);
    
              if (txtPicturePath.Text.Length != 0)
              {
                    FileInfo flePicture = new FileInfo(txtPicturePath.Text);
                    flePicture.CopyTo(@"C:\Solo Music Store\" +
                                      txtItemNumber.Text + flePicture.Extension);
              }
    
              // After saving the item, reset the form
              txtItemNumber.Text = rnd.Next(100000, 999999).ToString();
              cbxCategories.Text = "";
              cbxTypes.Text = "";
              txtItemName.Text = "";
              txtUnitPrice.Text = "0.00";
              txtPicturePath.Text = "";
              pbxStoreItem.Image = null;
        }
        finally
        {
            stmStoreItem.Close();
        }
    }
  6. Save the file

Practical LearningPractical Learning: Identifying this Item in the Collection

  1. In the Solution Explorer, double-click ItemEditor.cs
  2. Double-click an unoccupied area of the form to generate its Load event/li>
  3. Implement the event as follows:
    private void ItemEditor_Load(object sender, EventArgs e)
    {
        // Since all values seem ready, prepare to process the item
        var item = new StoreItem();
        var items = new StoreItems<StoreItem>();
        var bfmStoreItem = new BinaryFormatter();
    
        // This is the file that holds the list of items
        var Filename = @"C:\Solo Music Store\StoreItems.slm";
    
        if (File.Exists(Filename))
        {
            var stmStoreItem = new FileStream(Filename,
                                              FileMode.Open,
                                              FileAccess.Read,
                                              FileShare.Read);
    
            try
            {
                // Retrieve the list of items from file
                items = (StoreItems<StoreItem>)bfmStoreItem.Deserialize(stmStoreItem);
    
                // Display the categories in the combo box
                for (var i = 0; i < items.Count; i++)
                {
                    item = (StoreItem)items[i];
    
                    if (!cbxCategories.Items.Contains(item.Category))
                        cbxCategories.Items.Add(item.Category);
                }
    
                // Display the items types in the combo box
                for (var i = 0; i < items.Count; i++)
                {
                    item = (StoreItem)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
            var rnd = new Random();
            txtItemNumber.Text = rnd.Next(100000, 999999).ToString();
    
            // Make sure the user had selected a category
            cbxCategories.Text = "";
            cbxTypes.Text = "";
        }
    }
  4. Execute the application to test it
  5. 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
     
  6. Close the forms and return to your programming environment
  7. In the Solution Explorer, right-click MusicStore.cs and click View Code
  8. Make the following changes:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace SoloMusic1
    {
        public partial class MusicStore : Form
        {
            StoreItems<StoreItem> items;
            int iFilename;
            bool IsNewCustomerOrder;
    
            public MusicStore()
            {
                InitializeComponent();
            }
    
            private void btnNewStoreItem_Click(object sender, EventArgs e)
            {
                var editor = new ItemEditor();
    
                // Create a random number to get it ready for
                // the user creating a new store item
                var rnd = new Random();
                editor.txtItemNumber.Text = rnd.Next(100000, 999999).ToString();
    
                if (editor.ShowDialog() == DialogResult.Cancel)
                    LoadMusicStore();
            }
    
            internal void LoadMusicStore()
            {
                // Since all values seem ready, prepare to process the item
                items = new StoreItems<StoreItem>();
                var bfmStoreItem = new BinaryFormatter();
    
                // This is the file that holds the list of items
                var Filename = @"C:\Solo Music Store\StoreItems.slm";
    
                if (File.Exists(Filename))
                {
                    FileStream stmStoreItem = new FileStream(Filename,
                                                             FileMode.Open,
                                                             FileAccess.Read,
                                                             FileShare.Read);
    
                    try
                    {
                        // Retrieve the list of items from file
                        items = (StoreItems<StoreItem>)bfmStoreItem.Deserialize(stmStoreItem);
    
                        // Display the categories in the combo box
                        for (int i = 0; i < items.Count; i++)
                        {
                            StoreItem item = (StoreItem)items[i];
    
                            if (!cbxCategories.Items.Contains(item.Category))
                                cbxCategories.Items.Add(item.Category);
                        }
                    }
                    finally
                    {
                        stmStoreItem.Close();
                    }
                }
            }
        }
    }
  9. In the Solution Explorer, double-click MusicStore.cs to open the form
  10. On the form, double-click the Item Category combo box
  11. Implement the SelectedIndexChanged event as follows:
    private void cbxCategories_SelectedIndexChanged(object sender, EventArgs e)
    {
        cbxTypes.Items.Clear();
        cbxTypes.Text = "";
        lvwStoreItems.Items.Clear();
        pbxStoreItem.Image = null;
    
        // If the current store inventory is empty, don't do anything
        if (items.Count == 0)
            return;
    
        // Get the item selected in the combo box
        var strCategory = (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 (var i = 0; i < items.Count; i++)
        {
    	// Get the current item from the store inventory
            var item = (StoreItem)items[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);
            }
        }
    }
  12. Return to the Music Store form
  13. Double-click the Item Type combo box
  14. Implement the SelectedIndexChanged event as follows:
    private void cbxTypes_SelectedIndexChanged(object sender, EventArgs e)
    {
        cbxTypes.Text = "";
        pbxStoreItem.Image = null;
    
        // If the current store inventory is empty, don't do anything
        if (items.Count == 0)
            return;
    
        // Get the item selected in the Categories combo box
        string strCategory = (string)cbxCategories.SelectedItem;
        // Get the item selected in theTypes combo box
        string strType = (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 < items.Count; i++)
        {
    	// Get the current item from the inventory
            StoreItem item = (StoreItem)items[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("F"));
            }
        }
    }
  15. Return to the Music Store form
  16. On the form, double-click the Available Items list view
  17. Implement its SelectedIndexChanged event as follows:
    private void lvwStoreItems_SelectedIndexChanged(object sender, EventArgs e)
    {
        StoreItem item = new StoreItem();
    
        if ((lvwStoreItems.SelectedItems.Count == 0) ||
            (lvwStoreItems.SelectedItems.Count > 1))
            return;
    
        string strItemNumber =
    	lvwStoreItems.SelectedItems[0].SubItems[0].Text;
    
        for (int i = 0; i < items.Count; i++)
        {
            StoreItem itm = (StoreItem)items[i];
            if (itm.ItemNumber == strItemNumber)
                item = itm;
        }
    
        // Make a list of the picture files
        string strDirectory = @"C:\Solo Music Store";
        DirectoryInfo dirStoreItems = new DirectoryInfo(strDirectory);
        FileInfo[] PictureFiles = dirStoreItems.GetFiles("*.jpg");
    
        // Look for a file that holds the same name as the item number
        foreach (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 + ".jpg");
        }
    }
  18. Return to the Music Store form and click the list view under Available Items if necessary
  19. In the Properties window, click the Events button and double-click DoubleClick
  20. Implement the event as follows:
    internal void CalculateOrder()
    {
        double itemsTotal = 0.00D, taxRate = 0.00D,
                 taxAmount = 0.00D, orderTotal = 0.00D;
    
        // Check each row of the data grid view.
        // Get the sub-total values and add them
        for (int i = 0; i < dgvSelectedItems.Rows.Count - 1; i++)
            itemsTotal += double.Parse(dgvSelectedItems.Rows[i].Cells[4].Value.ToString());
    
        // Display the total in the Items Total text box
        txtItemsTotal.Text = itemsTotal.ToString("F");
    
        // Get the tax rate
        taxRate = double.Parse(txtTaxRate.Text);
    
        // Calculate the tax
        taxAmount = itemsTotal * taxRate / 100;
        // Add the tax amount to the items total to get the total of the order
        orderTotal = itemsTotal + taxAmount;
    
        // Display the amount collected for taxes
        txtTaxAmount.Text = taxAmount.ToString("F");
    
        // Display the order total
        txtOrderTotal.Text = orderTotal.ToString("F");
    }
            
    private void lvwStoreItems_DoubleClick(object sender, EventArgs e)
    {
        // Get a reference to the row that was double-clicked
        ListViewItem lviMusicItem = lvwStoreItems.SelectedItems[0];
    
        // If no item exists or no row was double-selected, don't do anything
        if (lvwStoreItems.SelectedItems.Count == 0)
            return;
    
        // If a row was double-clicked, transfer its values to the data grid view
        dgvSelectedItems.Rows[dgvSelectedItems.Rows.Count - 1].Cells[0].Value = lviMusicItem.Text;
        dgvSelectedItems.Rows[dgvSelectedItems.Rows.Count - 1].Cells[1].Value = lviMusicItem.SubItems[1].Text;
        dgvSelectedItems.Rows[dgvSelectedItems.Rows.Count - 1].Cells[2].Value = lviMusicItem.SubItems[2].Text;
        dgvSelectedItems.Rows[dgvSelectedItems.Rows.Count - 1].Cells[3].Value = "1";
        dgvSelectedItems.Rows[dgvSelectedItems.Rows.Count - 1].Cells[4].Value = lviMusicItem.SubItems[2].Text;
    
        string[] recMusicItem = { lviMusicItem.Text,
                                  lviMusicItem.SubItems[1].Text,
                                  lviMusicItem.SubItems[2].Text, "1",
                                  lviMusicItem.SubItems[2].Text };
        int r = dgvSelectedItems.Rows.Add(recMusicItem);
    
        // Reset the lastly added row to get it ready to receive another record
        dgvSelectedItems.Rows[dgvSelectedItems.Rows.Count - 1].Cells[0].Value = "";
        dgvSelectedItems.Rows[dgvSelectedItems.Rows.Count - 1].Cells[1].Value = "";
        dgvSelectedItems.Rows[dgvSelectedItems.Rows.Count - 1].Cells[2].Value = "";
        dgvSelectedItems.Rows[dgvSelectedItems.Rows.Count - 1].Cells[3].Value = "";
        dgvSelectedItems.Rows[dgvSelectedItems.Rows.Count - 1].Cells[4].Value = "";
    
        CalculateOrder();
    }
  21. Return to the Music Store form
  22. Click the data grid view under Selected Items
  23. In the Events section of the Properties window, double-click CellLeave
  24. Implement the event as follows:
    private void dgvSelectedItems_CellLeave(object sender, DataGridViewCellEventArgs e)
    {
        decimal unitPrice = 0.00M;
        int quantity = 0;
        decimal subTotal = 0.00M;
    
        // Find out if the user was changing the quantity value on the row that has focus
        if (e.ColumnIndex == 3)
        {
            // Get the unit price of the current row
            unitPrice = decimal.Parse(dgvSelectedItems.Rows[e.RowIndex].Cells[2].EditedFormattedValue.ToString());
            // Get the quantity value of the current row
            quantity = int.Parse(dgvSelectedItems.Rows[e.RowIndex].Cells[3].EditedFormattedValue.ToString());
            // Calculate the sub-total
            subTotal = unitPrice * quantity;
            // Display the sub-total on the current row
            dgvSelectedItems.Rows[e.RowIndex].Cells[4].Value = subTotal.ToString();
    
            // Update the calculations
            CalculateOrder();
        }
    }
  25. Return to the Music Store form
  26. On the form, click the Tax Rate text box
  27. In the Events section of the Properties window, double-click Leave
  28. Implement the event as follows:
    private void txtTaxRate_Leave(object sender, EventArgs e)
    {
        CalculateOrder();
    }
  29. Return to the Music Store form
  30. Double-click the New Order button and implement its event as follows:
    private void btnNewCustomerOrder_Click(object sender, EventArgs e)
    {
        // We will store our files in the following folder    
        var strDirectory = @"C:\Solo Music Store\Receipts";
        var dirInfo = Directory.CreateDirectory(strDirectory);
    
        // Get the list of files, if any, from our directory
        var fleList = dirInfo.GetFiles();
        var Filename = "";
    
        // 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
            var LastFile = fleList[fleList.Length - 1];
            // Get the name of the last file without its extension
            var 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 + "\\" + iFilename.ToString() + ".its";
        txtReceiptNumber.Text = iFilename.ToString();
    
        // Reset the form
        cbxCategories.Text = "";
        cbxTypes.Text = "";
        
        lvwStoreItems.Items.Clear();
        dgvSelectedItems.Rows.Clear();
    
        txtItemsTotal.Text = "0.00";
        txtTaxRate.Text = "7.75";
        txtTaxAmount.Text = "0.00";
        txtOrderTotal.Text = "0.00";
    }
  31. Return to the Music Store form
  32. Double-click the Save button and implement the event as follows:
    private void btnSave_Click(object sender, EventArgs e)
    {
        if (dgvSelectedItems.Rows.Count == 0)
        {
            MessageBox.Show("There is no customer order to save.");
            return;
        }
    
        // We will store our files in the following folder    
        var strSelectedItems = @"C:\Solo Music Store\Receipts\Selected Items";
        var strTotals = @"C:\Solo Music Store\Receipts\Totals";
        var dirSelectedItems = Directory.CreateDirectory(strSelectedItems);
        var dirTotals = Directory.CreateDirectory(strTotals);
    
        // Get the list of files, if any, from our directory
        FileInfo[] fleSelectedItems = dirSelectedItems.GetFiles();
        var FilenameSelectedItem = "";
        var FilenameTotal = "";
    
        // 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 (fleSelectedItems.Length == 0)
            {
                iFilename = 1000;
            }
            else // If there was at least one file in the directory
            {
                // Get a reference to the last file
                var LastFile = fleSelectedItems[fleSelectedItems.Length - 1];
                // Get the name of the last file without its extension
                var 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
            FilenameSelectedItem = strSelectedItems + "\\" + iFilename.ToString() + ".its";
            FilenameTotal = strTotals + "\\" + iFilename.ToString() + ".ttl";
            txtReceiptNumber.Text = iFilename.ToString();
    
            IsNewCustomerOrder = false;
        } // If a cleaning order was already opened, we will simply update it
        else
        {
            FilenameSelectedItem = @"C:\Solo Music Store\Receipts\Selected Items\" +
                        txtReceiptNumber.Text + ".its";
            FilenameTotal = @"C:\Solo Music Store\Receipts\Totals\" +
                        txtReceiptNumber.Text + ".ttl";
        }
    
        StoreItems<SoldItem> lstSelectedItems = new StoreItems<SoldItem>();
    
        using (FileStream fsSelectedItems = new FileStream(FilenameSelectedItem, FileMode.Create))
        {
            // Get the items of each row and write its values to the selected items file
            for (int i = 0; i < dgvSelectedItems.Rows.Count - 1; i++)
            {
                SoldItem si = new SoldItem();
    
                si.ItemNumber = dgvSelectedItems.Rows[i].Cells[0].Value.ToString();
                si.ItemName   = dgvSelectedItems.Rows[i].Cells[1].Value.ToString();
                si.UnitPrice  = double.Parse(dgvSelectedItems.Rows[i].Cells[2].Value.ToString());
                si.Quantity   = int.Parse( dgvSelectedItems.Rows[i].Cells[3].Value.ToString());
                si.SubTotal   = double.Parse(dgvSelectedItems.Rows[i].Cells[4].Value.ToString());
                lstSelectedItems.Add(si);
            }
    
            BinaryFormatter bfSelectedItems = new BinaryFormatter();
            bfSelectedItems.Serialize(fsSelectedItems, lstSelectedItems);
        }
    
        using (StreamWriter wrtTotals = new StreamWriter(FilenameTotal))
        {
            wrtTotals.WriteLine(txtItemsTotal.Text);
            wrtTotals.WriteLine(txtTaxRate.Text);
            wrtTotals.WriteLine(txtTaxAmount.Text);
            wrtTotals.WriteLine(txtOrderTotal.Text);
        }
    
        // Reset the form
        btnNewCustomerOrder_Click(sender, e);
    }
  33. Return to the Music Store Form
  34. Double-click the Open button and implement its event as follows:
    private void btnOpen_Click(object sender, EventArgs e)
    {
        var strDirSelectedItems  = @"C:\Solo Music Store\Receipts\Selected Items";
        var strFileSelectedItems = 
        	@"C:\Solo Music Store\Receipts\Selected Items\1000.its";
    
        var strDirTotals  = @"C:\Solo Music Store\Receipts\Totals";
        var strFileTotals = @"C:\Solo Music Store\Receipts\Totals\1000.ttl";
    
        if (txtReceiptNumber.Text == "")
            return;
        else
        {
            strFileSelectedItems = strDirSelectedItems + 
            	"\\" + txtReceiptNumber.Text + ".its";
            
            if (File.Exists(strFileSelectedItems))
            {
                using (FileStream fsSavedItems = 
                	new FileStream(strFileSelectedItems, FileMode.Open))
                {
                    BinaryFormatter bfSaveItems = new BinaryFormatter();
                    StoreItems<SoldItem> lstSavedItems = 
                        (StoreItems<SoldItem>)bfSaveItems.Deserialize(fsSavedItems);
    
                    dgvSelectedItems.Rows.Clear();
    
                    for(int i = 0; i < lstSavedItems.Count; i++)
                    {
                        dgvSelectedItems.Rows.Add();
                        SoldItem si = (SoldItem)lstSavedItems[i];
    
                        dgvSelectedItems.Rows[i].Cells[0].Value = si.ItemNumber;
                        dgvSelectedItems.Rows[i].Cells[1].Value = si.ItemName;
                        dgvSelectedItems.Rows[i].Cells[2].Value = 
                        	si.UnitPrice.ToString();
                        dgvSelectedItems.Rows[i].Cells[3].Value = si.Quantity;
                        dgvSelectedItems.Rows[i].Cells[4].Value = si.SubTotal;
                    }
                }
    
                strFileTotals = strDirTotals + "\\" + txtReceiptNumber.Text + ".ttl";
    
                try
                {
                    var rdrTotals = new StreamReader(strFileTotals);
    
                    try
                    {
                        txtItemsTotal.Text = rdrTotals.ReadLine();
                        txtTaxRate.Text = rdrTotals.ReadLine();
                        txtTaxAmount.Text = rdrTotals.ReadLine();
                        txtOrderTotal.Text = rdrTotals.ReadLine();
    
                        IsNewCustomerOrder = false;
                    }
                    finally
                    {
                        rdrTotals.Close();
                    }
                }
                catch (FileNotFoundException)
                {
                    MessageBox.Show("There is no customer order " +
                        "with that receipt number");
                }
            }
        }
    }
  35. Return to the Music Store form
  36. Double-click an unoccupied area of the form
  37. Implement the event as follows:
    private void MusicStore_Load(object sender, EventArgs e)
    {
        btnNewCustomerOrder_Click(sender, e);
        LoadMusicStore();
        IsNewCustomerOrder = true;
    }
  38. Return to the Music Store form
  39. Double-click the Close and implement its Click event as follows:
    private void btnClose_Click(object sender, EventArgs e)
    {
        Close();
    }
  40. Execute the application
  41. Access the Item Editor dialog box and create a few more items as follows (let the computer create the item numbers):
     
    Category Type Item Name Unit Price 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
     
  42. 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
  43. Close the form and return to your programming environment
 

Home Copyright © 2010-2011 C#Key