Introduction

There are many options to create a database. One of the most basic options is a text-based repository. Even then, you have many options, such as JSON. A good solution for a database application is to create it as XML. The .NET Framework supports XML through various classes. These classes allow you to create a fully functional database application.

Practical LearningPractical Learning: Starting the Project

  1. If you are using Microsoft Windows, on the C: drive, create a folder (or directory) namedSolo Music Store (or you can create the folder in another drive of your choice; you can also use another name of folder or directory if you want, in the case, in the sections of code in this project, make sure you change "C:\Solo Music Store" to a path of your choice)
  2. Save the following illustration in that folder:

    Home

  3. Start Microsoft Visual Studio
  4. On the Visual Studio 2022 dialog box, click Create a New Project
  5. In the Create a New Project dialog box, make sure All Languages or C# is selected in the languages combo box. In the list of projects templates, click Windows Forms App
  6. Click Next
  7. Set the Propect Name to SoloMusicStore
  8. Click Next
  9. In the Additional Information wizard page, in the Framework combo box, select the latest version (.NET 8.0 (Long-Term Support)).
    Click Create

A Store Item

A database is made of objects. For our application, a store item is an object that identifies the main object of the business. We will use a form in which the user can type or select the neessary parts of a store item.

Practical LearningPractical Learning: Creating a Store Item

  1. On the main menu of Microsoft Visual Studio, click Project and click Add Form (Windows Forms...)
  2. Set the file Name to StoreItemNew
  3. Click Add
  4. Design the form as follows:

    Solo Music Store - New Store Item

    Control (Name) Text Other Properties
    Label Label   &Item #:  
    Text Box Text Box txtItemNumber    
    Label Label   C&tegory:  
    Combo Box Combo Box cbxCategories    
    Button Button btnNewCategory N&ew  
    Label Label   S&ub-Ctegory:  
    Combo Box Combo Box cbxSubCategories    
    Button Button btnNewSubCategory Ne&w  
    Label Label   Item &Name:  
    Text Box Text Box txtItemNumber   ScrollBars: Vertical
    Multiline: True
    Label Label   &Unit Price:  
    Text Box Text Box txtUnitPrice    
    Label Label   ________________________________  
    Button Button btnSaveStoreItem Sa&ve Store Item  
    Button Button btnClose &Close  
  5. Double-click an unoccupied area of the form to create its Load event
  6. Return to the form and click the Item Number text box to select it
  7. In the Properties window, click the Events button Button
  8. In the Events section of the Properties window, double-click Leave
  9. Return to the form and double-click the Categories combo box to generate the SelectedIndexChanged event
  10. Return to the form and double-click the New Category button
  11. Return to the form and double-click the New Sub-Category button
  12. Return to the form and double-click the Save Store Item button
  13. Return to the form and double-click the Close button
  14. Change the document as follows:
    using System.Xml;
    
    namespace SoloMusicStore
    {
        public partial class StoreItemNew : Form
        {
            public StoreItemNew()
            {
                InitializeComponent();
            }
    
            private void InitializeStoreItem()
            {
                // Initialize the XML DOM
                XmlDocument xdStoreItems = new XmlDocument();
                // Identify the file that contains the records for this project
                string strFileName = @"C:\Solo Music Store\StoreItems.xml";
    
                // If that file was already created, ...
                if (File.Exists(strFileName))
                {
                    // (before going any further, reset the controls on the form)
                    cbxCategories.Items.Clear();
                    cbxSubCategories.Items.Clear();
                    txtItemName.Text = string.Empty;
                    txtUnitPrice.Text = string.Empty;
                    txtItemNumber.Text = string.Empty;
    
                    // open the file and put its records in the XML DOM
                    xdStoreItems.Load(strFileName);
                    // Get a list of nodes that are named "category".
                    XmlNodeList xnlCategories = xdStoreItems.DocumentElement!.GetElementsByTagName("category");
    
                    // Visit each node
                    foreach (XmlNode xnCategory in xnlCategories)
                    {
                        /* If the value of that node is already in the Categories combo box,
                         * don't add it. If that value is not yet in the combo box, add it. */
                        if (!cbxCategories.Items.Contains(xnCategory.FirstChild!.InnerText))
                            cbxCategories.Items.Add(xnCategory.FirstChild.InnerText);
                    }
    
                    // At this time, no real item has been selected. Therefore, display the default picture
                    pbxSelectedItem.Image = Image.FromFile(@"C:\Solo Music Store\Generic.png");
    
                    /* Every time throughout this project, we will resize the form
                     * to display the complete picture of a store item. */
                    Width  = pbxSelectedItem.Right  + 40;
                    Height = pbxSelectedItem.Bottom + 75;
                }
            }
    
            private void StoreItemNew_Load(object sender, EventArgs e)
            {
                InitializeStoreItem();
            }
    
            private void txtItemNumber_Leave(object sender, EventArgs e)
            {
                if(string.IsNullOrEmpty(txtItemNumber.Text))
                    return;
    
                if (File.Exists(@"C:\Solo Music Store\" + txtItemNumber.Text + ".png"))
                    pbxSelectedItem.Image = Image.FromFile(@"C:\Solo Music Store\" + txtItemNumber.Text + ".png");
                else
                    pbxSelectedItem.Image = Image.FromFile(@"C:\Solo Music Store\Generic.png");
    
                Width  = pbxSelectedItem.Right  + 40;
                Height = pbxSelectedItem.Bottom + 75;
            }
    
            private void cbxCategories_SelectedIndexChanged(object sender, EventArgs e)
            {
                XmlDocument xdStoreItems = new XmlDocument();
                string strFileName = @"C:\Solo Music Store\StoreItems.xml";
    
                if (File.Exists(strFileName))
                {
                    xdStoreItems.Load(strFileName);
                    XmlElement xeStoreItem = xdStoreItems.DocumentElement!;
                    XmlNodeList xnlCategories = xeStoreItem.GetElementsByTagName("category");
    
                    cbxSubCategories.Text = "";
                    cbxSubCategories.Items.Clear();
    
                    // Display the sub-categories in the combo box
                    foreach (XmlNode xnCategory in xnlCategories)
                    {
                        // Get only the sub-categories of the selected category
                        if (xnCategory.InnerText == cbxCategories.Text)
                        {
                            if (!cbxSubCategories.Items.Contains(xnCategory.NextSibling!.InnerText))
                                cbxSubCategories.Items.Add(xnCategory.NextSibling.InnerText);
                        }
                    }
                }
            }
    
            private void btnNewCategory_Click(object sender, EventArgs e)
            {
                Category editor = new Category();
    
                if (editor.ShowDialog() == DialogResult.OK)
                {
                    if (!string.IsNullOrEmpty(editor.txtCategory.Text))
                    {
                        string strCategory = editor.txtCategory.Text;
    
                        // Make sure the category is not yet in the list
                        if (cbxCategories.Items.Contains(strCategory))
                        {
                            MessageBox.Show(strCategory + " is already in the list.",
                                            "Solo Music Store",
                                            MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                        else
                        {
                            // Since this is a new category, add it to the combox box
                            cbxCategories.Items.Add(strCategory);
                            // Just in case the user wanted to use this new category
                            // select it
                            cbxCategories.Text = strCategory;
                        }
                    }
                }
            }
    
            private void btnNewSubCategory_Click(object sender, EventArgs e)
            {
                SubCategory editor = new();
    
                if (editor.ShowDialog() == DialogResult.OK)
                {
                    if (!string.IsNullOrEmpty(editor.txtSubCategory.Text))
                    {
                        string strSubCategory = editor.txtSubCategory.Text;
    
                        if (cbxSubCategories.Items.Contains(strSubCategory))
                        {
                            MessageBox.Show(strSubCategory + " exists already.",
                                            "Solo Music Store",
                                            MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                        else
                        {
                            cbxSubCategories.Items.Add(strSubCategory);
                            cbxSubCategories.Text = strSubCategory;
                        }
                    }
                }
            }
    
            private void btnSaveStoreItem_Click(object sender, EventArgs e)
            {
                XmlDocument xdStoreItems = new XmlDocument();
                string strFileName = @"C:\Solo Music Store\StoreItems.xml";
    
                /* Make sure the user provides the item number, the category, the sub-category,
                 * the name (or short description), and the price of the item. */
                if( string.IsNullOrEmpty(txtItemNumber.Text)    ||
                    string.IsNullOrEmpty(cbxCategories.Text)    ||
                    string.IsNullOrEmpty(cbxSubCategories.Text) ||
                    string.IsNullOrEmpty(txtItemName.Text) )
                {
                    MessageBox.Show("You must provide all the information about the new item. " +
                                    "This includes the item number, its category, its sub-category, " +
                                    "its name (or short description), and its price.",
                                    "Solo Music Store",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);    
                    return;
                }
                
                // Get the values that were provided for the new store item
                int    itemNumber  =    int.Parse(txtItemNumber.Text);
                string category    =              cbxCategories.Text.Replace("&", "&");
                string subCategory =              cbxSubCategories.Text.Replace("&", "&");
                string itemName    =              txtItemName.Text.Replace("&", "&");
                double unitPrice   = double.Parse(txtUnitPrice.Text);
                
                /* Find out if the file exists already.
                 * If it doesn't, then create it. */
                if (!File.Exists(strFileName))
                {
                    xdStoreItems.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                         "<store-items></store-items>");
                    xdStoreItems.Save(strFileName);
                }
                
                // Open the XML file of the store items
                xdStoreItems.Load(strFileName);
    
                /* We will use this variable to find out whether the category
                 * being added exists already in the Store Items document. */
                bool categoryFound = false;
                // Get all the store items that have a Category node
                XmlNodeList xnlCategories = xdStoreItems.DocumentElement!.GetElementsByTagName("category");
                
                // Since we will create a new store item, let's initialize its new node
                XmlElement xeStoreItem = xdStoreItems.CreateElement("store-item");
    
                xeStoreItem.InnerXml = "<item-number>"  + itemNumber  + "</item-number>"  +
                                       "<category>"     + category    + "</category>"     +
                                       "<sub-category>" + subCategory + "</sub-category>" +
                                       "<item-name>"    + itemName    + "</item-name>"    +
                                       "<unit-price>"   + unitPrice   + "</unit-price>";
                
                // Check each store item
                foreach (XmlNode xnCategory in xnlCategories)
                {
                    // If you find the same category, ...
                    if (xnCategory.InnerText == category)
                    {
                        /* Now that we found a category, check the categories.
                         * If you find the same sub-category, ... */
                        if (xnCategory.NextSibling!.InnerText == subCategory)
                        {
                            /* Now that we have the same sub-category, compare it to the current sub-category.
                             * If the current sub-category alphabetically comes before the sub-category
                             * of the new store item, insert the new one before the existing one */
                            if (string.Compare(xnCategory.InnerText, category) < 0)
                                xdStoreItems.DocumentElement.InsertBefore(xeStoreItem, xnCategory.ParentNode);
                            else // Otherwise, add it after
                                xdStoreItems.DocumentElement.InsertAfter(xeStoreItem, xnCategory.ParentNode);
                        }
                        else
                        {
                            /* If the new sub-category was not found in the document, compare its item number
                             * to that of the existing store item.
                             * If the item number of the existing store item is higher than that of 
                             * the new store item, add the new store item before the existing one */
                            if (int.Parse(xnCategory.PreviousSibling!.InnerText) > itemNumber)
                                xdStoreItems.DocumentElement.InsertBefore(xeStoreItem, xnCategory.ParentNode);
                            else // Otherwise, add it after
                                xdStoreItems.DocumentElement.InsertAfter(xeStoreItem, xnCategory.ParentNode);
                        }
                        
                        categoryFound = true;
                        break;
                    }
                }
                
                // If the new category was not found, ...
                if (categoryFound == false)
                {
                    /* If there are already five store items in the document,
                     * add the new one as the first */
                    if (xdStoreItems.ChildNodes.Count < 5)
                        xdStoreItems.DocumentElement.PrependChild(xeStoreItem);
                    else // Otherwise, add the new store item the the last element
                        xdStoreItems.DocumentElement.AppendChild(xeStoreItem);
                }
                
                // Now the the new store item has been added or inserted, save the XML file
                xdStoreItems.Save(strFileName);
    
                InitializeStoreItem();
            }
        
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }

Editing or Updating a Store Item

Once you have created some records for a database, some time to time, you may need to change some or more records. We will provide a form to do that.

Practical LearningPractical Learning: Updating a Record

  1. On the main menu of Microsoft Visual Studio, click Project and click Add Form (Windows Forms...)
  2. Set the file Name to StoreItemEditor
  3. Click Add
  4. Resize the form so it would have the same size as the New Store Item form
  5. Display the New Store Item form
  6. Press Ctrl + A to select everything on it, then press Ctrl + C to copy
  7. Display the Store Item Editor form and press Ctrl + V to paste
  8. Change the design of the form as follows:

    Solo Music Store - New Store Item

    Control (Name) Text
    Button Button btnFind &Find
    Button Button btnUpdateStoreItem Up&date Store Item
  9. Double-click an unoccupied area of the form to create its Load event
  10. Return to the form and double-click the Find button
  11. Return to the form and double-click the Categories combo box
  12. Return to the form and double-click the New Category button
  13. Return to the form and double-click the New Sub-Category button
  14. Return to the form and double-click the Update Store Item button
  15. Return to the form and double-click the Close button
  16. Change the document as follows:
    using System.Xml;
    
    namespace SoloMusicStore
    {
        public partial class StoreItemEditor : Form
        {
            public StoreItemEditor()
            {
                InitializeComponent();
            }
    
            private void InitializeStoreItem()
            {
                XmlDocument xdStoreItems = new XmlDocument();
                string strFileName = @"C:\Solo Music Store\StoreItems.xml";
    
                if (File.Exists(strFileName))
                {
                    cbxCategories.Items.Clear();
                    cbxSubCategories.Items.Clear();
                    txtItemName.Text = string.Empty;
                    txtUnitPrice.Text = string.Empty;
                    txtItemNumber.Text = string.Empty;
    
                    xdStoreItems.Load(strFileName);
                    XmlNodeList xnlCategories = xdStoreItems.DocumentElement!.GetElementsByTagName("category");
    
                    foreach (XmlNode xnCategory in xnlCategories)
                    {
                        if (!cbxCategories.Items.Contains(xnCategory.FirstChild!.InnerText))
                            cbxCategories.Items.Add(xnCategory.FirstChild.InnerText);
                    }
    
                    pbxSelectedItem.Image = Image.FromFile(@"C:\Solo Music Store\Generic.png");
    
                    Width  = pbxSelectedItem.Right + 40;
                    Height = pbxSelectedItem.Bottom + 75;
                }
            }
    
            private void StoreItemEditor_Load(object sender, EventArgs e)
            {
                InitializeStoreItem();
            }
    
            private void btnFind_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(txtItemNumber.Text))
                {
                    MessageBox.Show("You must enter a store item number.",
                                    "Solo Music Store",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
    
                bool storeItemFound = false;
                XmlDocument xdStoreItems = new XmlDocument();
                string strFileName    = @"C:\Solo Music Store\StoreItems.xml";
                string strPictureFile = @"C:\Solo Music Store\" + txtItemNumber.Text + ".png";
    
                if (File.Exists(strFileName))
                {
                    xdStoreItems.Load(strFileName);
                    XmlElement xeStoreItem = xdStoreItems.DocumentElement!;
                    XmlNodeList xnlStoreItems = xeStoreItem.GetElementsByTagName("item-number");
    
                    // Check each store item
                    foreach (XmlNode xnStoreItem in xnlStoreItems)
                    {
                        // Check the item number of each store item
                        if (xnStoreItem.InnerText == txtItemNumber.Text)
                        {
                            // If you find the store item, display its values in the controls
                            cbxCategories.Text = xnStoreItem?.NextSibling?.InnerText;
                            cbxSubCategories.Text = xnStoreItem?.NextSibling?.NextSibling?.InnerText;
                            txtItemName.Text = xnStoreItem?.NextSibling?.NextSibling?.NextSibling?.InnerText;
                            txtUnitPrice.Text = xnStoreItem?.NextSibling?.NextSibling?.NextSibling?.NextSibling?.InnerText;
    
                            if (File.Exists(strPictureFile))
                                pbxSelectedItem.Image = Image.FromFile(strPictureFile);
                            else
                                pbxSelectedItem.Image = Image.FromFile(@"C:\Solo Music Store\Generic.png");
    
                            Width = pbxSelectedItem.Right + 40;
                            Height = pbxSelectedItem.Bottom + 75;
    
                            storeItemFound = true;
                            break;
                        }
                    }
                }
    
                if (storeItemFound == false)
                {
                    MessageBox.Show("There is no store item with that number.",
                                    "Solo Music Store",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
    
            private void cbxCategories_SelectedIndexChanged(object sender, EventArgs e)
            {
                XmlDocument xdStoreItems = new XmlDocument();
                string strFileName = @"C:\Solo Music Store\StoreItems.xml";
    
                if (File.Exists(strFileName))
                {
                    xdStoreItems.Load(strFileName);
                    XmlElement xeStoreItem = xdStoreItems.DocumentElement!;
                    XmlNodeList xnlCategories = xeStoreItem.GetElementsByTagName("category");
    
                    cbxSubCategories.Text = "";
                    cbxSubCategories.Items.Clear();
    
                    // Display the sub-categories in the combo box
                    foreach (XmlNode xnCategory in xnlCategories)
                    {
                        // Get only the sub-categories of the selected category
                        if (xnCategory.InnerText == cbxCategories.Text)
                        {
                            if (!cbxSubCategories.Items.Contains(xnCategory.NextSibling!.InnerText))
                                cbxSubCategories.Items.Add(xnCategory.NextSibling.InnerText);
                        }
                    }
                }
            }
    
            private void btnNewCategory_Click(object sender, EventArgs e)
            {
                Category editor = new Category();
    
                if (editor.ShowDialog() == DialogResult.OK)
                {
                    if (!string.IsNullOrEmpty(editor.txtCategory.Text))
                    {
                        string strCategory = editor.txtCategory.Text;
    
                        // Make sure the category is not yet in the list
                        if (cbxCategories.Items.Contains(strCategory))
                        {
                            MessageBox.Show(strCategory + " is already in the list.",
                                            "Solo Music Store",
                                            MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                        else
                        {
                            // Since this is a new category, add it to the combox box
                            cbxCategories.Items.Add(strCategory);
                            // Just in case the user wanted to use this new category
                            // select it
                            cbxCategories.Text = strCategory;
                        }
                    }
                }
            }
    
            private void btnNewSubCategory_Click(object sender, EventArgs e)
            {
                SubCategory editor = new();
    
                if (editor.ShowDialog() == DialogResult.OK)
                {
                    if (!string.IsNullOrEmpty(editor.txtSubCategory.Text))
                    {
                        string strSubCategory = editor.txtSubCategory.Text;
    
                        if (cbxSubCategories.Items.Contains(strSubCategory))
                        {
                            MessageBox.Show(strSubCategory + " exists already.",
                                            "Solo Music Store",
                                            MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                        else
                        {
                            cbxSubCategories.Items.Add(strSubCategory);
                            cbxSubCategories.Text = strSubCategory;
                        }
                    }
                }
            }
    
            private void btnUpdateStoreItem_Click(object sender, EventArgs e)
            {
                int itemNumber;
                double unitPrice;
                string category, subCategory, itemName;
    
                XmlDocument xdStoreItems = new XmlDocument();
                string strFileName = @"C:\Solo Music Store\StoreItems.xml";
                
                if( string.IsNullOrEmpty(txtItemNumber.Text)    |
                    string.IsNullOrEmpty(cbxCategories.Text)    |
                    string.IsNullOrEmpty(cbxSubCategories.Text) |
                    string.IsNullOrEmpty(txtItemName.Text))
                {
                    MessageBox.Show("You must provide all the information about the store item to be updated.",
                                    "Solo Music Store", MessageBoxButtons.OK, MessageBoxIcon.Information);
                   return;
                }
    
                    // Get the values that were provided for the new store item
                    itemNumber  =    int.Parse(txtItemNumber.Text);
                    category    =              cbxCategories.Text.Replace("&", "&amp;"); ;
                    subCategory =              cbxSubCategories.Text.Replace("&", "&amp;"); ;
                    itemName    =              txtItemName.Text.Replace("&", "&amp;"); ;
                    unitPrice   = double.Parse(txtUnitPrice.Text);
    
                    // Find out if the file exists already
                    // If it doesn't, then create it
                    if(!File.Exists(strFileName))
                    {
                        MessageBox.Show("There is no store items inventory to update.",
                                        "Solo Music Store",
                                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return;
                    }
    
                    // Open the XML file of the store items
                    xdStoreItems.Load(strFileName);
    
                    // Get all the store items that have a Category node
                    XmlNodeList xnlItemNumbers = xdStoreItems.DocumentElement!.GetElementsByTagName("item-number");
    
                    // Since we will create a new store item, let's initialize its new node
                    XmlElement xeStoreItem = xdStoreItems.CreateElement("store-item");
    
                    xeStoreItem.InnerXml = "<item-number>"  + itemNumber  + "</item-number>" +
                                           "<category>"     + category    + "</category>"    +
                                           "<sub-category>" + subCategory + "</sub-category>" +
                                           "<item-name>"    + itemName    + "</item-name>"    +
                                           "<unit-price>"   + unitPrice   + "</unit-price>";
    
                    // Check each store item
                    foreach (XmlNode xnStoreItem in xnlItemNumbers)
                    {
                        // If you find the same item number, ...
                        if (int.Parse(xnStoreItem.InnerText) == itemNumber)
                        {
                            xdStoreItems.DocumentElement.ReplaceChild(xeStoreItem, xnStoreItem.ParentNode!);
                            break;
                        }
                    }
    
                    // Now the the new store item has been added or inserted, save the XML file
                    xdStoreItems.Save(strFileName);
    
                    InitializeStoreItem();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }

Deleting a Store Item

In your application, if you have a record you don't need anymore, you can remove it. We will provide a form to support this operation.

Practical LearningPractical Learning: Updating a Record

  1. On the main menu of Microsoft Visual Studio, click Project and click Add Form (Windows Forms...)
  2. Set the file Name to StoreItemDelete
  3. Click Add
  4. Resize the form so it would have the same size as the Store Item Editor form
  5. Display the Store Item Editor form
  6. Press Ctrl + A to select everything on it, then press Ctrl + C to copy
  7. Display the Store Item Delete form and press Ctrl + V to paste
  8. Change the design of the form as follows:

    Solo Music Store - Deleting Store Item

    Control (Name) Text
    Text Box Combo Box txtCategory  
    Text Box Combo Box txtSubCategory  
    Button Button btnDeleteStoreItem &Delete Store Item
  9. Double-click an unoccupied area of the form to create its Load event
  10. Return to the form and double-click the Find button
  11. Return to the form and double-click the Delete Store Item button
  12. Return to the form and double-click the Close button
  13. Change the document as follows:
    using System.Xml;
    
    namespace SoloMusicStore
    {
        public partial class StoreItemDelete : Form
        {
            public StoreItemDelete()
            {
                InitializeComponent();
            }
    
            private void InitializeStoreItem()
            {
                txtCategory.Text      = string.Empty;
                txtSubCategory.Text   = string.Empty;
                txtItemName.Text      = string.Empty;
                txtUnitPrice.Text     = string.Empty;
                txtItemNumber.Text    = string.Empty;
                pbxSelectedItem.Image = Image.FromFile(@"C:\Solo Music Store\Generic.png");
                
                Width  = pbxSelectedItem.Right  + 40;
                Height = pbxSelectedItem.Bottom + 75;
            }
    
            private void StoreItemDelete_Load(object sender, EventArgs e)
            {
                InitializeStoreItem();
            }
    
            private void btnFind_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(txtItemNumber.Text))
                {
                    MessageBox.Show("You must enter a store item number.",
                                    "Solo Music Store",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
    
                bool storeItemFound = false;
                XmlDocument xdStoreItems = new XmlDocument();
                string strFileName = @"C:\Solo Music Store\StoreItems.xml";
                string strPictureFile = @"C:\Solo Music Store\" + txtItemNumber.Text + ".png";
    
                if (File.Exists(strFileName))
                {
                    xdStoreItems.Load(strFileName);
                    XmlElement xeStoreItem = xdStoreItems.DocumentElement!;
                    XmlNodeList xnlStoreItems = xeStoreItem.GetElementsByTagName("item-number");
    
                    // Check each store item
                    foreach (XmlNode xnStoreItem in xnlStoreItems)
                    {
                        // Check the item number of each store item
                        if (xnStoreItem.InnerText == txtItemNumber.Text)
                        {
                            // If you find the store item, display its values in the controls
                            txtCategory.Text    = xnStoreItem?.NextSibling?.InnerText;
                            txtSubCategory.Text = xnStoreItem?.NextSibling?.NextSibling?.InnerText;
                            txtItemName.Text    = xnStoreItem?.NextSibling?.NextSibling?.NextSibling?.InnerText;
                            txtUnitPrice.Text   = xnStoreItem?.NextSibling?.NextSibling?.NextSibling?.NextSibling?.InnerText;
    
                            if (File.Exists(strPictureFile))
                                pbxSelectedItem.Image = Image.FromFile(strPictureFile);
                            else
                                pbxSelectedItem.Image = Image.FromFile(@"C:\Solo Music Store\Generic.png");
    
                            Width  = pbxSelectedItem.Right  + 40;
                            Height = pbxSelectedItem.Bottom + 75;
    
                            storeItemFound = true;
                            break;
                        }
                    }
                }
    
                if (storeItemFound == false)
                {
                    MessageBox.Show("There is no store item with that number.",
                                    "Solo Music Store",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
    
            private void btnDeleteStoreItem_Click(object sender, EventArgs e)
            {
                XmlDocument xdStoreItems = new XmlDocument();
                string strFileName = @"C:\Solo Music Store\StoreItems.xml";
    
                if( string.IsNullOrEmpty(txtItemNumber.Text) )
                {
                    MessageBox.Show("You must type the number of the store item you want to delete.",
                                    "Solo Music Store", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
    
                if (!File.Exists(strFileName))
                {
                    MessageBox.Show("There is no store items inventory to update.",
                                    "Solo Music Store",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
    
                // Open the XML file of the store items
                xdStoreItems.Load(strFileName);
    
                // Get all the store items that have a Category node
                XmlNodeList xnlItemNumbers = xdStoreItems.DocumentElement!.GetElementsByTagName("item-number");
    
                // Check each store item
                foreach (XmlNode xnStoreItem in xnlItemNumbers)
                {
                    // If you find the same item number, ...
                    if (xnStoreItem.InnerText == txtItemNumber.Text)
                    {
                        if (MessageBox.Show("Are you sure you want to remove this item from the store inventory?",
                                        "Solo Music Store",
                                        MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
                        {
                            xdStoreItems.DocumentElement.RemoveChild(xnStoreItem.ParentNode!);
                            break;
                        }
                    }
                }
    
                // Now the the new store item has been added or inserted, save the XML file
                xdStoreItems.Save(strFileName);
    
                InitializeStoreItem();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }

The Central Object of a Database

An application should have an object from which the user can select the operations to perform. For that purpose, we will use the first form that was created in the project.

Practical LearningPractical Learning: Using the Central Form of the Project

  1. In the Solution Explorer, right-click Form1.cs and click Rename
  2. Type StoreInventory (to get StoreInventory.cs)
  3. Press Enter three times to accept the name and display the form
  4. Design the form as follows:

    Solo Music Store - Deleting Store Item

    Control (Name) Text Other Properties
    Label Label   Item Category Font: Garamond, 14.25pt, style=Bold
    Label Label   Item Sub-Category Font: Garamond, 14.25pt, style=Bold
    Label Label   Available Items Font: Garamond, 14.25pt, style=Bold
    List Box List Box lbxCategories   Font: Garamond, 12pt, style=Bold
    List Box List Box lbxSubCategories   Font: Garamond, 12pt, style=Bold
    List View List View lvwAvailableItems   Font: Garamond, 12pt

    Columns

    (Name) Text TextAlign Width
    colItemNumber Item #   90
    colItemName Item Name   500
    colUnitPrice Unit Price Right 105
    Picture Box Picture Box pbxSelectedItem   BorderStyle: Fixed3D
    SizeMode: AutoSize
    Button Button btnNewStoreItem New Store Item...  
    Button Button btnUpdateStoreItem Update Store Item...  
    Button Button btnDeleteStoreItem Delete Store Item...  
    Button Button btnClose &Close  
  5. Double-click an unoccupied area of the form to create its Load event
  6. Return to the form and double-click the Item Category list box to generate the SelectedIndexChanged event
  7. Return to the form and double-click the Item Sub-Category list box
  8. Return to the form and click the Available Items list view to select it
  9. In the Properties window, click the Events button Button
  10. In the Events section of the Properties window for the list view, double-click ItemSelectionChanged
  11. Return to the form and double-click the New Store Item button
  12. Return to the form and double-click the Update Store Item button
  13. Return to the form and double-click the Delete Store Item button
  14. Return to the form and double-click the Close button
  15. Change the document as follows:
    using System.Xml;
    
    namespace SoloMusicStore
    {
        public partial class StoreInventory : Form
        {
            public StoreInventory()
            {
                InitializeComponent();
            }
    
            // This function is used to reset the form when necessary
            private void InitializeStoreItems()
            {
                XmlDocument xdStoreItems = new XmlDocument();
                string strFileName = @"C:\Solo Music Store\StoreItems41.xml";
    
                // If a file for the records in this project was created already, ...
                if (File.Exists(strFileName))
                {
                    // before doing anything, reset/empty the list boxes and the list view. 
                    lbxCategories.Items.Clear();
                    lbxSubCategories.Items.Clear();
                    lvwAvailableItems.Items.Clear();
    
                    // Open the file that contains the records of this project, ...
                    using (FileStream fsStoreItems = new FileStream(strFileName, FileMode.Open, FileAccess.Read))
                        // ... put those records in the XML DOM
                        xdStoreItems.Load(fsStoreItems);
        
                    // Get a reference to the XML DOM
                    XmlElement xeStoreItem = xdStoreItems.DocumentElement!;
                    // Get a list of all the nodes in the XML document
                    XmlNodeList xnlStoreItems = xeStoreItem.ChildNodes;
    
                    // Prepare toisplay the categories in the left list box
                    for (int i = 0; i < xnlStoreItems.Count; i++)
                    {
                        // Make sure the list box doesn't yet have the category being added
                        if (!lbxCategories.Items.Contains(xnlStoreItems[i]!["category"]!.InnerText))
                            lbxCategories.Items.Add(xnlStoreItems[i]!["category"]!.InnerText);
                    }
                }
    
                /* Since the form is likely being reset, no store item is selected at this time.
                 * Therefore, display the default picture of the store items. */
                pbxSelectedItem.Image = Image.FromFile(@"C:\Solo Music Store\Generic.png");
    
                /* Every time throughout this project, we will resize the form
                 * to display the complete picture of a store item. */
                Width = pbxSelectedItem.Right  + 40;
                Height = pbxSelectedItem.Bottom + 75;
            }
    
            private void StoreInventory_Load(object sender, EventArgs e)
            {
                InitializeStoreItems();
            }
    
            private void lbxCategories_SelectedIndexChanged(object sender, EventArgs e)
            {
                lbxSubCategories.Items.Clear();
                lvwAvailableItems.Items.Clear();
                XmlDocument xdStoreItems = new XmlDocument();
                string strFileName = @"C:\Solo Music Store\StoreItems41.xml";
    
                if (File.Exists(strFileName))
                {
                    xdStoreItems.Load(strFileName);
    
                    XmlElement xeStoreItem = xdStoreItems.DocumentElement!;
                    XmlNodeList xnlStoreItems = xeStoreItem.ChildNodes;
    
                    // Display the sub-categories in the combo box
                    for (int i = 0; i < xnlStoreItems.Count; i++)
                    {
                        // Get only the sub-categories of the selected category
                        if (xnlStoreItems[i]?["category"]?.InnerText == lbxCategories.SelectedItem.ToString())
                        {
                            if (!lbxSubCategories.Items.Contains(xnlStoreItems[i]!["sub-category"]!.InnerText))
                                lbxSubCategories.Items.Add(xnlStoreItems[i]!["sub-category"]!.InnerText);
                        }
                    }
                }
            }
    
            private void lbxSubCategories_SelectedIndexChanged(object sender, EventArgs e)
            {
                XmlDocument xdStoreItems = new XmlDocument();
                string strFileName = @"C:\Solo Music Store\StoreItems41.xml";
    
                /* When the user clicks an item in the sub-categories combo box,
                 * remove everything in the list view because it is about to be populated. */
                lvwAvailableItems.Items.Clear();
    
                // Make sure the file that contains the store items was already created...
                if (File.Exists(strFileName))
                {
                    // ... It that's the case, open it and put its records in the XML DOM
                    xdStoreItems.Load(strFileName);
    
                    // Get a reference to the XML DOM
                    XmlElement xeStoreItem = xdStoreItems.DocumentElement!;
    
                    // Get a list of nodes named "sub-category"
                    XmlNodeList xnlSubCategories = xeStoreItem.GetElementsByTagName("sub-category");
    
                    // Visit each "sub-category" node 
                    foreach (XmlNode xnSubCategory in xnlSubCategories)
                    {
                        /* If you find a "category" node (which is the node previous to the 
                         * selected "sub-category" node) whose value is the same as the selected Category,
                         * and you find a "sub-category" node whose value is the same as the selected sub-category... */
                        if ( (xnSubCategory.PreviousSibling?.InnerText == lbxCategories.SelectedItem.ToString()) & 
                            (xnSubCategory.InnerText == lbxSubCategories.SelectedItem.ToString()) )
                        {
                            // ... display the values of the corresponding item in the Available Store Items list view
                            ListViewItem lviStoreItem = new ListViewItem(xnSubCategory?.PreviousSibling?.PreviousSibling?.InnerText);
                            lviStoreItem.SubItems.Add(xnSubCategory?.NextSibling?.InnerText);
                            lviStoreItem.SubItems.Add(double.Parse(xnSubCategory!.NextSibling!.NextSibling!.InnerText).ToString("F"));
    
                            lvwAvailableItems.Items.Add(lviStoreItem);
                        }
                    }
                }
            }
    
            private void lvwAvailableItems_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
            {
                if (File.Exists(@"C:\Solo Music Store\" + e.Item.Text + ".png"))
                    pbxSelectedItem.Image = Image.FromFile(@"C:\Solo Music Store\" + e.Item.Text + ".png");
                else
                    pbxSelectedItem.Image = Image.FromFile(@"C:\Solo Music Store\Generic.png");
    
                Width  = pbxSelectedItem.Right  + 40;
                Height = pbxSelectedItem.Bottom + 75;
            }
    
            private void btnNewStoreItem_Click(object sender, EventArgs e)
            {
                // When the user clicks the New Store Item button, ...
                StoreItemNew sin = new StoreItemNew();
                // display the corresponding form as a dialog box
                sin.ShowDialog();
                // When the user has finished using the dialog box, reset the current form
                InitializeStoreItems();
            }
    
            private void btnUpdateStoreItem_Click(object sender, EventArgs e)
            {
                StoreItemEditor sie = new StoreItemEditor();
    
                sie.ShowDialog();
    
                InitializeStoreItems();
            }
    
            private void btnDeleteStoreItem_Click(object sender, EventArgs e)
            {
                StoreItemDelete sid = new StoreItemDelete();
    
                sid.ShowDialog();
    
                InitializeStoreItems();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }

Executing and Testing the Application

After creating the project, you can test it with sample values and operations

Practical LearningPractical Learning: Executing and Testing the Application

  1. To execute the application, on the main manu, click Debug and click Start Without Debugging:

    Solo Music Store

  2. Click New Store Item...:

    Solo Music Store - New Store Item

  3. Create the following store items:

    Solo Music Store - New Store Item

    Item # Category Sub-Category Item Name Unit Price
    759240 Guitars Electric EART E-335 6 String Semi-Hollow-Body Electric Guitar, Stainless Steel Frets 444.86
    184920 Band & Orchestra Violins Mendini By Cecilio Violin - MV500+92D - Size 4/4 (Full Size), Black Solid Wood - Flamed, 1-Piece Violins w/Case, Tuner, Shoulder Rest, Bow, Rosin, Bridge & Strings 164.82
    824083 Keyboards Synthesizers Yamaha MX88 88-Key Weighted Action Synthesizer 1224.74
    302805 Amplifiers & Effects Guitar & Bass AmplifiersFender Rumble 25 V3 Bass Amplifier 124.95
    517279 Drum Sets Acoustic Rise by Sawtooth Full Size 5-Piece Student Drum Set with Hardware and Cymbals, Pitch Black 426.92
    729704 Keyboards Digital Pianos LAGRIMA Digital Piano with Bench, 88 Key Electric Piano for Beginner/Adults with Padded Piano Bench+Music Stand+Power Adapter+3-Pedal Board+Instruction Book+Headphone Jack 379.37
    828384 Concert Percussion Xylophones Voodans 32 Note Xylophone Professional Wooden Glockenspiel Xylophone with Mallet and Adjustable Stand 247.68
    280483 Guitars Bass Ibanez 4 String Bass Guitar, Right Handed, Black 234.95
    926082 Wind & Woodwind Instruments Clarinets Glory GLY-PBK Professional Ebonite Bb Clarinet with 10 Reeds, Stand, Hard Case, Cleaning Cloth, Cork Grease, Mouthpiece Brush and Pad Brush, Black 164.69
    420304 Keyboards Synthesizers Yamaha MX49 Music Production Synthesizer, Black 555.55
    695381 Guitars Acoustic YAMAHA FG800 Solid Top Acoustic Guitar 234.97
    828479 Wind & Woodwind Instruments Clarinets Wilmington Clarinet 442.94
    329374 Keyboards Synthesizers Roland JD-XI 37-Key Interactive Analog/Digital Crossover Synthesizer, Black 626.84
    148048 Band & Orchestra Saxophones E Flat Alto Saxophone495.95
    649273 Drum Sets Electric Alesis Drums Surge Mesh Kit - Electric Drum Set with USB MIDI Connectivity, Mesh Heads, Solid Rack and Drum Module Including 40 Kits and 385 Sounds 617.82
    302830 Keyboards Digital Pianos ZHRUNS Digital Piano,88 Heavy Hammer Piano Keys with Touch Response Electric Keyboard Piano/Music Stand+Power Adapter+3 Metal Pedals+Instruction Book,Headphone Jack/MIDI Input/Outputp 578.95
    937304 Guitars Bass Ibanez SR Premium 4-String Electric Bass Guitar (Right-Hand, Magic Wave Low Gloss) 1428.88
    492947 Band & Orchestra Flutes SLADE Closed Hole C Flute with Gloves, Tuning Rod, Carrying Case, Joint Grease and Cleaning Kit, 16 Key Student Flute Nickel plated flute, Beginner Flute in Band & Orchestra, Silver 124.86
    408384 Keyboards Digital Pianos Kawai ES110 88-Key Portable Digital Piano, Stylish Black, Bundle with H&A Monitor Headphones & H&A Keyboard Stand Bench Pedal 721.62
    688047 Concert Percussion Xylophones TNZMART 32 Key Xylophone Set with Adjustable Stand Wooden Glockenspiel Percussion 244.47
    384083 Guitars Electric Guild Guitars Starfire I DC Semi-Hollow Body Electric Guitar, Vintage Walnut, Double-Cut 555.75
    179274 Keyboards Digital Pianos Yamaha P-45 Compact 88-Key Portable Digital Piano + Keyboard Stand + Keyboard Bench + Keyboard Pedal + Studio Monitor Headphones 598.98
    849684 Drum Sets Acoustic Ashthorpe 5-Piece Complete Full Size Adult Drum Set with Remo Batter Heads - Silver 386.64
    505840 Band & Orchestra Mandolins Donner A Style Mandolin Instrument Sunburst Beginner Adult Acoustic Mandolin Musical Instrument Mahogany 8 String, Bundle With Tuner String Bag Guitar Picks,DML-1 128.86
    593577 Keyboards Digital Pianos ZHRUNS Digital Piano,88 Heavy Hammer Piano Keys with Touch Response Electric Keyboard Piano/Music Stand+Power Adapter+3 Metal Pedals+Instruction Book,Headphone Jack/MIDI Input/Outputp 579.93
    300530 Guitars Acoustic Donner 39 Inch Classical Guitar Full Size Brown Acoustic Guitar Beginner Bundle Kit Spruce Mahogany with Gig Bag Nylon Strings Capo Tuner 154.55
    184028 Band & Orchestra Saxophones YAMAHA YAS-280 Saxophones 1255.85
    538508 Keyboards Synthesizers Roland SYSTEM-8 PLUG-OUT Synthesizer, 49-key 1828.66
    257208 Drum Sets Electric Donner Electronic Drum Kit Adult with 5 Drums 4 Cymbals, 225 Sounds,Audio Line/Drum Stick 422.82
    927948 Keyboards Digital Pianos Donner DDP-100 88-Key Weighted Action Digital Piano, Beginner Bundle with Furniture Stand, Power Adapter, Triple Pedals, MP3 Function 605.05

    Solo Music Store - Store Items

  4. Make different selections in the list boxes and the list view:

    Solo Music Store - Store Ites

    Solo Music Store - Store Items

    Solo Music Store - Store Items

  5. Click the Update Store Item button:

    Solo Music Store - Update Store Ites

  6. Click the Item # text box and type 420304
  7. Click the Find button

    Solo Music Store - Update Store Ites

  8. Change the Item Name to Yamaha MX49 Music Production Synthesizer, Black
  9. Change the Unit Price to 555.55
  10. Click the Update Store Item button
  11. Close the Update Store Item form

    Solo Music Store - Store Ites


Home Copyright © 2001-2022, C# Key Wednesday 08 December 2022 Home