Introduction

Hi, for our exercise, we will create a text-based database Windows Forms application. We will us XML to store the records of our database.

Practical LearningPractical Learning: Introducing the Application

  1. Start Microsoft Visual Studio
  2. Create a Windows Forms App named StellarWaterPoint1

The Main Form of the Application

Our application will use a central form to access the other form. We will use the default form for that purpose. Our application will use records for water meters, customers, and water bills. Therefore, we will add some buttons for the forms related to those records.

Practical LearningPractical Learning: Preparing the Central Form of the Application

  1. In the Solution Explorer, right-click Form1.cs and click Rename
  2. Type WaterDistribution (to get WaterDistribution.cs) and press Enter
  3. If necessary, click the body of the form to make sure it is selected.
    In the Properties window, change the following characteristics:
    Text: Stellar Water Point
    StartPosition: CenterScreen
    MaximizeBox: False
  4. Complete the design of the form as follows:

    Stellar Water Point

    Control (Name) Text Font
    Button Button btnProcessingWaterBill &Water Bill Processing... Times New Roman, 24pt, style=Bold
    Button Button btnViewWaterBill &View Water Bill... Times New Roman, 24pt, style=Bold
    Button Button btnEditWaterBill &Edit Water Bill... Times New Roman, 24pt, style=Bold
    Button Button btnDeleteWaterBill &Delete Water Bill... Times New Roman, 24pt, style=Bold
    Button Button btnCustomers C&ustomers... Times New Roman, 24pt, style=Bold
    Button Button btnWaterMeters &Water Meters... Times New Roman, 24pt, style=Bold
    Button Button btnClose &Close Times New Roman, 24pt, style=Bold
  5. Double-click an unoccupied area of the form to generate its Load event
  6. Return to the Stellar Water Point form and double-click the &Water Bill Processing button
  7. Return to the Stellar Water Point form and double-click the &View Water Bill button
  8. Return to the Stellar Water Point form and double-click the &Edit Water Bill button
  9. Return to the Stellar Water Point form and double-click the &Delete Water Bill button
  10. Return to the Stellar Water Point form and double-click the C&ustomers button
  11. Return to the Stellar Water Point form and double-click the &Water Meters button
  12. Return to the Stellar Water Point form and double-click the Close button
  13. Change the document as follows:
    namespace StellarWaterPoint1
    {
        public partial class WaterDistribution : Form
        {
            public Switchboard()
            {
                InitializeComponent();
            }
    
            private void Switchboard_Load(object sender, EventArgs e)
            {
                Directory.CreateDirectory(@"C:\Stellar Water Point");
            }
    
            private void btnProcessingWaterBill_Click(object sender, EventArgs e)
            {
                
            }
    
            private void btnViewWaterBill_Click(object sender, EventArgs e)
            {
                
            }
    
            private void btnEditWaterBill_Click(object sender, EventArgs e)
            {
                
            }
    
            private void btnDeleteWaterBill_Click(object sender, EventArgs e)
            {
                
            }
    
    
            private void btnWaterMeters_Click(object sender, EventArgs e)
            {
                
            }
    
            private void btnCustomers_Click(object sender, EventArgs e)
            {
                
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  14. To execute the application and create a folder that will hold the records of this project, on the main menu, click Debug -> Start Without Debugging
  15. To close the form and return to your programming environment, click the Close button

Water Meters

Introduction

Our application will use forms to create water meter records, to view a record of a water meter, to edit or to delete the record of a water meter.

A Sample XML File

The primary way we can preview our data is to create a sample XML and show the structure of data we are expecting.

Practical LearningPractical Learning: Creating a Sample XML File

  1. Start a text editor such as Notepad
  2. In the empty document, type the following lines:
    <?xml version="1.0" encoding="utf-8"?>
    <water-meters>
      <water-meter>
        <meter-number>111-22-333</meter-number>
        <make>Manufacturer</make>
        <model>A1000</model>
        <meter-size>1 Inch</meter-size>
      </water-meter>
      <water-meter>
        <meter-number>444-55-666</meter-number>
        <make>Company</make>
        <model>B2000</model>
        <meter-size>2 Inches</meter-size>
      </water-meter>
    </water-meters>
  3. Save the file as Preview.xml in the directory that was created for the records of this project (C:\Stellar Water Point)

Displaying Water Meters

To let the user see a list of the water meters in the database, we will use a form equipped with a list view.

Practical LearningPractical Learning: Displaying Water Meters

  1. To create a folder, in the Solution Explorer, right-click the StellarWaterPoint1 project -> Add -> New Folder
  2. Type WaterMeters as the name of the folder
  3. To create a form, in the Solution Explorer, right-click WaterMeters -> Add -> Form (Windows Forms)...
  4. Type Central
  5. Press Enter
  6. In the Toolbox, click the ListView button and click the form
  7. On the form, right-click the list view and click Edit Columns...
  8. Create the columns as follows:
    (Name) Text Width
    colWaterMeterId Id 40
    colMeterNumber Meter # 150
    colMake Make 300
    colModel Model 150
    colMeterSize Meter Size 175
  9. Click OK
  10. Complete the design of the form as follows:

    Stellar Water Point - Water Meters

    Control (Name) Other Properties
    ListView List View lvwWaterMeters FullRowSelect: True
    GridLines: True
    View: Details
    Anchor: Top, Bottom, Left, Right
    Button Button btnNewWaterMeter &New Water Meter...
    Button Button btnViewWaterMeter &View Water Meter...
    Button Button btnEditWaterMeter &Edit Water Meter...
    Button Button btnDeleteWateMeter &Delete Water Meter...
  11. Doubte-click an unoccupied area of the form to generate its Load event
  12. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint1.WaterMeters
    {
        public partial class Central : Form
        {
            public Central()
            {
                InitializeComponent();
            }
    
            private void ShowWaterMeters()
            {
                XmlDocument xdWaterMeters = new XmlDocument();
                string? strWaterMeters = @"C:\Stellar Water Point\Preview.xml";
    
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
                
                using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open))
                {
                    xdWaterMeters.Load(fsWaterMeters);
                    XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.ChildNodes;
                    
                    int i = 1;
                    
                    foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                    {
                        ListViewItem lviWaterMeter = new ListViewItem(i++.ToString());
                        
                        lviWaterMeter.SubItems.Add(xnWaterMeter.FirstChild!.InnerText);
                        lviWaterMeter.SubItems.Add(xnWaterMeter.FirstChild.NextSibling!.InnerText);
                        lviWaterMeter.SubItems.Add(xnWaterMeter.FirstChild.NextSibling.NextSibling!.InnerText);
                        lviWaterMeter.SubItems.Add(xnWaterMeter.FirstChild.NextSibling.NextSibling.NextSibling!.InnerText);
                        
                        lvwWaterMeters.Items.Add(lviWaterMeter);
                    }
                }
            }
    
            private void Central_Load(object sender, EventArgs e)
            {
                ShowWaterMeters();
            }
        }
    }
  13. Return to the code of the WaterDistribution.cs file and change the event that displays the water meters as follows:
    namespace StellarWaterPoint1
    {
        public partial class Switchboard : Form
        {
            public Switchboard()
            {
                InitializeComponent();
            }
            
            . . .
    
            private void btnWaterMeters_Click(object sender, EventArgs e)
            {
                WaterMeters.Central central = new WaterMeters.Central();
    
                central.ShowDialog();
            }
            
            . . .
        }
    }
  14. To execute the application, on the main menu, click Debug -> Start Without Debugging
  15. On the Central form, click the Water Meters button:

    Stellar Water Point - Water Meters

  16. Close the forms and return to your programming environment

A Water Meter Record

Our application will have a list of water meters. A record for each water meter must be created. To make this happen, we will equip the application with an appropriate form.

Practical LearningPractical Learning: Creating a Water Meter Record

  1. To create a form, in the Solution Explorer, right-click the WaterMeters folder -> Add -> Form (Windows Forms)...
  2. Type Create
  3. Click Add
  4. Design the form as follows:

    Stellar Water Point - New Water Meter

    Control (Name) Text Other Properties
    Label Label   &Meter #:  
    MaskedTextBox Masked Text Box mtbMeterNumber   Masked: 000-00-000
    Anchor: Bottom, Right
    Label Label   M&ake:  
    TextBox Text Box txtMake   Modifiers: Public
    Anchor: Bottom, Right
    Label Label   M&odel:  
    TextBox Text Box txtModel   Modifiers: Public
    Anchor: Bottom, Right
    Label Label   Me&ter Size:  
    TextBox Text Box txtMeterSize   Modifiers: Public
    Anchor: Bottom, Right
    Button Button btnOK &OK DialogResult: OK
    Button Button btnCancel &Cancel DialogResult: Cancel
  5. Using the Properties window, change some characteristics of the form as follows:
    FormBorderStyle: FixedDialog
    Text:            Stellar Water Point - Water Meter Setup
    StartPosition:   CenterScreen
    AcceptButton:    btnOK
    CancelButton:    btnCancel
  6. Display the Central form under the WaterMeters folder of the Solution Explorer
  7. On the Central form, double-click the New Water Meter button
  8. Implement the event as follows:
    using System.Xml;
    
    namespace StellarWaterPoint10.WaterMeters
    {
        public partial class Central : Form
        {
            public Central()
            {
                InitializeComponent();
            }
    
            private void ShowWaterMeters()
            {
                // Create an XML Dom reference
                XmlDocument xdWaterMeters = new XmlDocument();
                // Declare a string variable to have the file that holds a list of water meters
                string? strWaterMeters = @"C:\Stellar Water Point1\WaterMeters.xml";
    
                // Create a FileInfo object that holds a reference to the file of water meters
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
    
                // If you are about to display a list of water meters, first empty the list view
                lvwWaterMeters.Items.Clear();
    
                // Check whether a file for water meters was previously created.
                if (fiWaterMeters.Exists)
                {
                    // If such a file exists, create a Stream for it
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        // Store the stream of water meters into the XML Dom that was created earlier
                        xdWaterMeters.Load(fsWaterMeters);
                        // Get a list of the water meter elements from the XML Dom object
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.ChildNodes;
    
                        int i = 1;
    
                        // Check each water meter
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            // Create a list view item to hold a record of a water meter
                            ListViewItem lviWaterMeter = new ListViewItem(i.ToString());
    
                            lviWaterMeter.SubItems.Add(xnWaterMeter.FirstChild!.InnerText);
                            lviWaterMeter.SubItems.Add(xnWaterMeter.FirstChild.NextSibling!.InnerText);
                            lviWaterMeter.SubItems.Add(xnWaterMeter.FirstChild.NextSibling.NextSibling!.InnerText);
                            lviWaterMeter.SubItems.Add(xnWaterMeter.FirstChild.NextSibling.NextSibling.NextSibling!.InnerText);
    
                            // Pass the list view item to the list view object on the form
                            lvwWaterMeters.Items.Add(lviWaterMeter);
    
                            i++;
                        }
                    }
                }
            }
    
            private void Central_Load(object sender, EventArgs e)
            {
                // When the open opens, make an attempt to display a list of water meters.
                ShowWaterMeters();
            }
    
            private void btnNewWaterMeter_Click(object sender, EventArgs e)
            {
                // Get a reference to the form used to add a water meter
                Create wm = new();
                // Create a FileInfo object
                FileInfo? fiWaterMeters = null;
                // Create a file stream object
                FileStream? fsWaterMeters = null;
                // Create an XML Dom object
                XmlDocument xdWaterMeters = new XmlDocument();
                // Declare a string for a file to hold a list of water meters
                string? strWaterMeters = @"C:\Stellar Water Point1\WaterMeters.xml";
    
                /* Display the form used to create a water meter. 
                 * If the user finishes using that form and click the OK button... */
                if (wm.ShowDialog() == DialogResult.OK)
                {
                    // Store the file of water meters into the FileInfo object that was previously created.
                    fiWaterMeters = new FileInfo(strWaterMeters);
    
                    /* Find out whether a list of water meters was previously created 
                     * and was stored in the string file declared above. */
                    if (fiWaterMeters.Exists)
                    {
                        /* If that file exists already, create a Stream object 
                         * for it with a read-only status. */
                        using (fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open,
                                                              FileAccess.Read, FileShare.Read))
                        {
                            // Pass the list of water meters to the XML Dom object created earlier
                            xdWaterMeters.Load(fsWaterMeters);
                        }
                    }
                    else
                    {
                        // If a file for water meters was not previously created, create it now...
                        using (fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Create,
                                                              FileAccess.Write, FileShare.Write))
                        {
                            // and create the root XML element for it
                            xdWaterMeters.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                                  "<water-meters></water-meters>");
                            // Make sure you save the new file
                            xdWaterMeters.Save(fsWaterMeters);
                        }
                    }
    
                    // Now that the file exists, open it
                    using (fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.OpenOrCreate, 
                                                          FileAccess.ReadWrite, FileShare.ReadWrite))
                    {
                        // Start creating a new Water Meter XML element
                        XmlElement xeWaterMeter = xdWaterMeters.CreateElement("water-meter");
    
                        /* Use the values that the user had typed in the Create form.
                         * Use those values to create the child elements of the new water meter node.
                         * Assign the combination of child elements to the new water meter node. */
                        xeWaterMeter.InnerXml = "<meter-number>" + wm.mtbMeterNumber.Text + "</meter-number>" +
                                                "<make>" + wm.txtMake.Text + "</make>" +
                                                "<model>" + wm.txtModel.Text + "</model>" +
                                                "<meter-size>" + wm.txtMeterSize.Text + "</meter-size>";
                        // Once the XML element is ready, add/append it to the XML Dom that was previously created.
                        xdWaterMeters.DocumentElement!.AppendChild(xeWaterMeter);
                        // Once the new element has been created and add it to the file, save that file
                        xdWaterMeters.Save(fsWaterMeters);
                    }
                }
    
                /* Whenever the user has finished using the Create form, 
                 * make an attempt to display the list of water meters. */
                ShowWaterMeters();
            }
        }
    }
  9. To execute the application, on the main menu, click Debug -> Start Without Debugging
  10. On the Central form, click the Water Meters button
  11. Click the New Water Meter button:

    Stellar Water Point - New Water Meter

  12. Enter the value for each of the following records and click OK (or press Enter) for each:
    Meter # Make Model Meter Size
    392-44-572 Constance Technologies TG-4822 5/8 Inches
    938-75-869 Stanford Trend 266G 1 1/2 Inches
    588-29-663 Estellano NCF-226 3/4 Inches
    186-92-805 Lansome 2800 1 1/2 Inches
    799-28-461 Kensa Sons K-584-L 3/4 Inches
    386-48-057 Estellano NCF-226 3/4 Inches
    837-06-836 Lansome 7400 5/8 Inches
    207-94-835 Constance Technologies TG-6220 5/8 Inches
    592-84-957 Kensa Sons D-497-H 3/4 Inches
    374-06-284 Raynes Energica i2022 3/4 Inches
    186-99-757 Fansa Sun A-BBB-C 1/2 Inch
    630-07-055 Lansome 2800 3/4 Inches
    827-50-248 Standard Trend 428T 3/4 Inches
    470-68-850 Estellano WRT-482 3/4 Inches
    649-33-505 Constance Technologies BD-7000 5/8 Inches
    306-82-497 Lansome 9000 3/4 Inches

    Stellar Water Point - Water Meters

  13. Close the forms and return to your programming environment

Water Meter Details

Once a database exists, sometimes a use mmay want to check the values of a water meter record. To support this, we will add an appropriate form to our application.

Practical LearningPractical Learning: Creating a Water Meter Record

  1. To create a form, in the Solution Explorer, right-click WaterMeters -> Add -> Form (Windows Forms)...
  2. Type Details
  3. Press Enter
  4. Resize the Editor form to have the same size as the Create form
  5. Copy everything from the Create form and paste it in the Editor form
  6. Delete the bottom two buttons and add a new button
  7. Change the design of the form as follows:

    Stellar Water Point - New Water Meter

    Control (Name) Text
    Button Button btnFindWateMeter &Find Water Meter
    Button Button btnClose &Close
  8. On the form, double-click the Find button
  9. Return to the form and double-click the Close button
  10. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint10.WaterMeters
    {
        public partial class Details : Form
        {
            public Details()
            {
                InitializeComponent();
            }
    
            private void btnFindWateMeter_Click(object sender, EventArgs e)
            {
                /* If the user clicks the Find button, 
                 * make sure there is a meter number in the top text box. */
                if (string.IsNullOrEmpty(mtbMeterNumber.Text))
                {
                    /* If the user didn't type a meter number, 
                     * display a message box to inform the user. */
                    MessageBox.Show("You must type a meter number and then click the Find button.",
                                    "Stellar Water Point", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    // If the user didn't type a meter number but clicked Find, don't do anything
                    return;
                }
    
                // We will need a reference to an XML Dom object as an XmlDocument variable
                XmlDocument xdWaterMeters = new XmlDocument();
                // This is the name and path of the file that holds the records of water meters
                string? strWaterMeters = @"C:\Stellar Water Point1\WaterMeters.xml";
                // We will process the file of water meters using a FileInfo object
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
    
                // We need to find out whether a file for water meters was previously created.
                if (fiWaterMeters.Exists)
                {
                    // If that file exists, create a stream of it. Open that file with a read-only status
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        // Get the list of water meter records and put those records in the XML Dom object created earlier.
                        xdWaterMeters.Load(fsWaterMeters);
                        /* Use XPath to locate the water meter that has 
                         * the same meter number as the one in the Meter # text box.
                         * Store the water meter in an XmlNodeList variable. */
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + mtbMeterNumber.Text + "']")!;
    
                        /* If there is a water meter in the database with 
                         * the number that the user typed, locate that water meter 
                         * and display each of its values in the appropriate text box. */
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            txtMake.Text = xnWaterMeter.NextSibling!.InnerText;
                            txtModel.Text = xnWaterMeter.NextSibling.NextSibling!.InnerText;
                            txtMeterSize.Text = xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText;
                        }
                    }
                }
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  11. Display the Central form of the WaterMeters folder
  12. Double-click the View Water Meter button
  13. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint1.WaterMeters
    {
        public partial class Central : Form
        {
            public Central()
            {
                InitializeComponent();
            }
    
            private void ShowWaterMeters()
            {
                . . .
            }
    
            private void Central_Load(object sender, EventArgs e)
            {
                // When the open opens, make an attempt to display a list of water meters.
                ShowWaterMeters();
            }
    
            private void btnNewWaterMeter_Click(object sender, EventArgs e)
            {
                . . .
            }
    
            private void btnViewWaterMeter_Click(object sender, EventArgs e)
            {
                /* Get a reference to the dialog box that is used 
                 * to view information about a water meter. */
                Details view = new();
                // Display that dialog box
                view.ShowDialog();
    
                // After using the dialog box, make an attempt to display the list of water meters.
                ShowWaterMeters();
            }
        }
    }
  14. To execute the application, on the main menu, click Debug -> Start Without Debugging
  15. On the Water Distribution form, click the Water Meters button
  16. On the Central form of water meters, click the View Water Meter button:

    Stellar Water Point - View Water Meter

  17. In the Meter # text, type 186-99-757
  18. Click the Find button:

    Stellar Water Point - View Water Meter

  19. Close the forms and return to your programming environment

Updating a Water Meter Details

One of the routine operations performed on a database is to change the details of a record. To support this operation for a water meter, we will create a form that can be used to update the information of a water meter.

Practical LearningPractical Learning: Updating a Water Meter

  1. To create a form, in the Solution Explorer, right-click WaterMeters -> Add -> Form (Windows Forms)...
  2. Type Editor
  3. Press Enter
  4. Resize the Editor form to have the same size as the Details form
  5. Copy everything from the Details form and paste it in the Editor form
  6. Change the design of the form as follows:

    Stellar Water Point - New Water Meter

    Control (Name) Text
    Button Button btnUpdateWateMeter &Update Water Meter
  7. On the form, double-click the Find button
  8. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint1.WaterMeters
    {
        public partial class Editor : Form
        {
            public Editor()
            {
                InitializeComponent();
            }
    
            private void btnFind_Click(object sender, EventArgs e)
            {
                XmlDocument xdWaterMeters = new XmlDocument();
                string? strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
    
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists)
                {
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterMeters.Load(fsWaterMeters);
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + mtbMeterNumber.Text + "']")!;
    
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            txtMake.Text = xnWaterMeter.NextSibling!.InnerText;
                            txtModel.Text = xnWaterMeter.NextSibling.NextSibling!.InnerText;
                            txtMeterSize.Text = xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText;
                        }
                    }
                }
            }
        }
    }
  9. Return to the form and double-click the Update Water Meter button
  10. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint1.WaterMeters
    {
        public partial class Editor : Form
        {
            public Editor()
            {
                InitializeComponent();
            }
    
            . . .
    
            private void btnUpdateWaterMeter_Click(object sender, EventArgs e)
            {
                XmlDocument xdWaterMeters = new XmlDocument();
                string? strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
    
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists)
                {
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterMeters.Load(fsWaterMeters);
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + mtbMeterNumber.Text + "']")!;
    
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            xnWaterMeter.ParentNode!.InnerXml = "<meter-number>" + mtbMeterNumber.Text + "</meter-number>" +
                                                                "<make>" + txtMake.Text + "</make>" +
                                                                "<model>" + txtModel.Text + "</model>" +
                                                                "<meter-size>" + txtMeterSize.Text + "</meter-size>";
                        }
                    }
    
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
                    {
                        xdWaterMeters.Save(fsWaterMeters);
                    }
                }
    
                Close();
            }
        }
    }
  11. Return to the form and double-click the Close button
  12. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint10.WaterMeters
    {
        public partial class Editor : Form
        {
            public Editor()
            {
                InitializeComponent();
            }
    
            private void btnFindWateMeter_Click(object sender, EventArgs e)
            {
                /* If the user clicks the Find button, 
                 * make sure there is a meter number in the top text box. */
                if (string.IsNullOrEmpty(mtbMeterNumber.Text))
                {
                    /* If the user didn't type a meter number, 
                     * display a message box to inform the user. */
                    MessageBox.Show("You must type a meter number and then click the Find button.",
                                    "Stellar Water Point", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    // If the user didn't type a meter number but clicked Find, don't do anything
                    return;
                }
    
                // We will need a reference to an XML Dom object as an XmlDocument variable
                XmlDocument xdWaterMeters = new XmlDocument();
                // This is the name and path of the file that holds the records of water meters
                string? strWaterMeters = @"C:\Stellar Water Point1\WaterMeters.xml";
                // We will process the file of water meters using a FileInfo object
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
    
                // We need to find out whether a file for water meters was previously created.
                if (fiWaterMeters.Exists)
                {
                    // If that file exists, create a stream of it. Open that file with a read-only status
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        /* Get the list of water meter records 
                         * and put those records in the XML Dom object created earlier. */
                        xdWaterMeters.Load(fsWaterMeters);
                        /* Use XPath to locate the water meter that has 
                         * the same meter number as the one in the Meter # text box.
                         * Store the water meter in an XmlNodeList variable. */
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + mtbMeterNumber.Text + "']")!;
    
                        /* If there is a water meter in the database with 
                         * the number that the user typed, locate that water meter 
                         * and display each of its values in the appropriate text box. */
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            txtMake.Text = xnWaterMeter.NextSibling!.InnerText;
                            txtModel.Text = xnWaterMeter.NextSibling.NextSibling!.InnerText;
                            txtMeterSize.Text = xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText;
                        }
                    }
                }
            }
    
            private void btnUpdateWaterMeter_Click(object sender, EventArgs e)
            {
                // We will need a reference to an XML Dom object as an XmlDocument variable
                XmlDocument xdWaterMeters = new();
                // This is the name and path of the file that holds the records of water meters
                string? strWaterMeters = @"C:\Stellar Water Point1\WaterMeters.xml";
                // We will process the file of water meters using a FileInfo object
                FileInfo? fiWaterMeters = new(strWaterMeters);
    
                // We need to find out whether a file for water meters was previously created.
                if (fiWaterMeters.Exists)
                {
                    // If that file exists, create a stream of it. Open that file with a read-only status
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        /* Get the list of water meter records 
                         * and put those records in the XML Dom object created earlier. */
                        xdWaterMeters.Load(fsWaterMeters);
                        /* Use XPath to locate the water meter that has 
                         * the same meter number as the one in the Meter # text box.
                         * Store the water meter in an XmlNodeList variable. */
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + mtbMeterNumber.Text + "']")!;
    
                        // Check each record of the water meters.
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            /* If you find a record whose water meter is 
                             * the same as the meter number that the user typed,
                             * change the values of the Make, the Model, 
                             * and the Meter Size based on the values 
                             * the user typed in the corresponding text boxes. */
                            xnWaterMeter.ParentNode!.InnerXml = "<meter-number>" + mtbMeterNumber.Text + "</meter-number>" +
                                                                "<make>" + txtMake.Text + "</make>" +
                                                                "<model>" + txtModel.Text + "</model>" +
                                                                "<meter-size>" + txtMeterSize.Text + "</meter-size>";
                        }
                    }
    
                    /* Now that a water meter has been changed/update 
                     * (and the file of water meters has changed), save the new version of the file. */
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
                    {
                        xdWaterMeters.Save(fsWaterMeters);
                    }
                }
    
                /* If the user has updated a record, we will assume that, 
                 * in most cases (such as usually in real life), 
                 * a user updates one record and moves to other activities.
                 * For this record, after the user has updated a record, 
                 * we will clode the form. */
                Close();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  13. Display the Central form of the WaterMeters folder
  14. Double-click the Update Water Meter button
  15. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint1.WaterMeters
    {
        public partial class Central : Form
        {
            public Central()
            {
                InitializeComponent();
            }
    
            private void ShowWaterMeters()
            {
                . . .
            }
    
            private void Central_Load(object sender, EventArgs e)
            {
                // When the open opens, make an attempt to display a list of water meters.
                ShowWaterMeters();
            }
    
            private void btnNewWaterMeter_Click(object sender, EventArgs e)
            {
                . . .
            }
    
            private void btnViewWaterMeter_Click(object sender, EventArgs e)
            {
                . . .
            }
    
            private void btnEditWaterMeter_Click(object sender, EventArgs e)
            {
                /* Get a reference to the dialog box that is used 
                 * to update the details of a water meter. */
                Editor editor = new();
                // Display that dialog box
                editor.ShowDialog();
    
                // After using the dialog box, make an attempt to display the list of water meters.
                ShowWaterMeters();
            }
        }
    }
  16. To execute the application, on the main menu, click Debug -> Start Without Debugging
  17. On the Central form, click the Water Meters button
  18. Click the Edit Water Meter button:

    Stellar Water Point - Water Meter Editor

  19. In the Meter # text, type 186-99-757
  20. Click the Find button:

    Stellar Water Point - Water Meter Details

  21. Change the values as follows:
    Make: Kensa Sons
    Model: M-686-G
    Meter Size: 1 1/2 Inches
    :

    Stellar Water Point - New Water Meter

  22. Click the Update button:

    Stellar Water Point - Water Meters

  23. Close the forms and return to your programming environment

Removing a Water Meter from the Database

If a record is not necessary anymore on a database, the user may want to remove it. To assist the user with this operation, we will create a form withe necessary buttons.

Practical LearningPractical Learning: Deleting a Water Meter Record

  1. To create a form, in the Solution Explorer, right-click WaterMeters -> Add -> Form(Windows Forms)...
  2. Type Delete
  3. Press Enter
  4. Resize the Editor form to have the same size as the Editor form
  5. Copy everything from the Editor form and paste it in the Delete form
  6. Change the bottom button as follows:

    Stellar Water Point - New Water Meter

    Control (Name) Text
    Button Button btnDeleteWateMeter &Delete Water Meter
  7. On the form, double-click the Find button
  8. Change the document as tollows:
    using System.Xml;
    
    namespace StellarWaterPoint1.WaterMeters
    {
        public partial class Delete : Form
        {
            public Delete()
            {
                InitializeComponent();
            }
    
            private void btnFind_Click(object sender, EventArgs e)
            {
                XmlDocument xdWaterMeters = new XmlDocument();
                string? strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
    
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists)
                {
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterMeters.Load(fsWaterMeters);
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + mtbMeterNumber.Text + "']")!;
    
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            txtMake.Text = xnWaterMeter.NextSibling!.InnerText;
                            txtModel.Text = xnWaterMeter.NextSibling.NextSibling!.InnerText;
                            txtMeterSize.Text = xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText;
                        }
                    }
                }
            }
        }
    }
  9. Return to the form and double-click the Delete Water Meter button
  10. Change the document as tollows:
    using System.Xml;
    
    namespace StellarWaterPoint1.WaterMeters
    {
        public partial class Delete : Form
        {
            public Delete()
            {
                InitializeComponent();
            }
    
            . . .
    
            private void btnDeleteWaterMeter_Click(object sender, EventArgs e)
            {
                XmlDocument xdWaterMeters = new XmlDocument();
                string? strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
    
                if (string.IsNullOrEmpty(mtbMeterNumber.Text))
                {
                    MessageBox.Show("You must type a water meter number if you want to delete one.",
                                    "Stellar Water Point", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
    
                if (!File.Exists(strWaterMeters))
                {
                    MessageBox.Show("There is no file for the water meters in the system.",
                                    "Stellar Water Point",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
    
                xdWaterMeters.Load(strWaterMeters);
    
                XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.GetElementsByTagName("meter-number");
    
                foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                {
                    if (xnWaterMeter.InnerText == mtbMeterNumber.Text)
                    {
                        if (MessageBox.Show("Are you sure you want to delete this water meter record from the system?",
                                        "Stellar Water Point",
                                        MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                        {
                            xdWaterMeters.DocumentElement.RemoveChild(xnWaterMeter.ParentNode!);
                            break;
                        }
                    }
                }
    
                xdWaterMeters.Save(strWaterMeters);
    
                Close();
            }
        }
    }
  11. Return to the form and double-click the Close button
  12. Change the document as tollows:
    using System.Xml;
    
    namespace StellarWaterPoint10.WaterMeters
    {
        public partial class Delete : Form
        {
            public Delete()
            {
                InitializeComponent();
            }
    
            private void btnFindWateMeter_Click(object sender, EventArgs e)
            {
                /* If the user clicks the Find button, 
                 * make sure there is a meter number in the top text box. */
                if (string.IsNullOrEmpty(mtbMeterNumber.Text))
                {
                    /* If the user didn't type a meter number, 
                     * display a message box to inform the user. */
                    MessageBox.Show("You must type a meter number and then click the Find button.",
                                    "Stellar Water Point", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    // If the user didn't type a meter number but clicked Find, don't do anything
                    return;
                }
    
                // We will need a reference to an XML Dom object as an XmlDocument variable
                XmlDocument xdWaterMeters = new XmlDocument();
                // This is the name and path of the file that holds the records of water meters
                string? strWaterMeters = @"C:\Stellar Water Point1\WaterMeters.xml";
                // We will process the file of water meters using a FileInfo object
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
    
                // We need to find out whether a file for water meters was previously created.
                if (fiWaterMeters.Exists)
                {
                    // If that file exists, create a stream of it. Open that file with a read-only status
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        /* Get the list of water meter records 
                         * and put those records in the XML Dom object created earlier. */
                        xdWaterMeters.Load(fsWaterMeters);
                        /* Use XPath to locate the water meter that has 
                         * the same meter number as the one in the Meter # text box.
                         * Store the water meter in an XmlNodeList variable. */
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + mtbMeterNumber.Text + "']")!;
    
                        /* If there is a water meter in the database with 
                         * the number that the user typed, locate that water meter 
                         * and display each of its values in the appropriate text box. */
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            txtMake.Text = xnWaterMeter.NextSibling!.InnerText;
                            txtModel.Text = xnWaterMeter.NextSibling.NextSibling!.InnerText;
                            txtMeterSize.Text = xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText;
                        }
                    }
                }
            }
    
            private void btnDeleteWaterMeter_Click(object sender, EventArgs e)
            {
                /* If the user clicks the Delete button, make sure that 
                 * the right text box contains a meter number */
                if (string.IsNullOrEmpty(mtbMeterNumber.Text))
                {
                    // If the user didn't provide a meter number, display a message box ...
                    MessageBox.Show("You must type a water meter number if you want to delete one.",
                                    "Stellar Water Point", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    // .. and stop the operation.
                    return;
                }
    
                // Create an XML Dom object
                XmlDocument xdWaterMeters = new XmlDocument();
                /* Get the file that holds a list of water meters
                 * and assign that file to a string variable. */
                string? strWaterMeters = @"C:\Stellar Water Point1\WaterMeters.xml";
    
                /* If the user provided a meter number and clicked the Find button,
                 * check whether a file for water meters was previously created. */
                if (!File.Exists(strWaterMeters))
                {
                    // If a file for water meters was not created already, display a message box...
                    MessageBox.Show("There is no file for the water meters in the system.",
                                    "Stellar Water Point",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                    // .. and stop the operation.
                    return;
                }
    
                /* Since a file of water meters exists, open it.
                 * Store the list of water meters in the XML Dom object that was previously created. */
                xdWaterMeters.Load(strWaterMeters);
    
                /* From the list of XML elements, get a list of elements based one named meter-number. */
                XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.GetElementsByTagName("meter-number");
    
                // Visit each XML node from the list
                foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                {
                    /* When you get to an element, check whether its meter number is 
                     * the same number the user had typed. */
                    if (xnWaterMeter.InnerText == mtbMeterNumber.Text)
                    {
                        /* If you find that meter number, enquire from 
                         * the user if the water meter must be deleted. 
                         * To get that information, display a message box with a Yes and a No buttons. */
                        if (MessageBox.Show("Are you sure you want to delete this water meter record from the system?",
                                        "Stellar Water Point",
                                        MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                        {
                            // If the user had clicked Yes, delete the water meter.
                            xdWaterMeters.DocumentElement.RemoveChild(xnWaterMeter.ParentNode!);
                            break;
                        }
                    }
                }
    
                // Since the list of water meters has been changed, save its new version
                xdWaterMeters.Save(strWaterMeters);
    
                /* After the deletion operation, close the dialog box and
                 * return to the Central form of water meters. */
                Close();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  13. Display the Central form of the WaterMeters folder
  14. Double-click the Delete Water Meter button
  15. Return to the Central form of the water meters and double-click the Delete Water Meter button
  16. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint10.WaterMeters
    {
        public partial class Central : Form
        {
            public Central()
            {
                InitializeComponent();
            }
    
            private void ShowWaterMeters()
            {
                // Create an XML Dom reference
                XmlDocument xdWaterMeters = new XmlDocument();
                // Declare a string variable to have the file that holds a list of water meters
                string? strWaterMeters = @"C:\Stellar Water Point1\WaterMeters.xml";
    
                // Create a FileInfo object that holds a reference to the file of water meters
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
    
                // If you are about to display a list of water meters, first empty the list view
                lvwWaterMeters.Items.Clear();
    
                // Check whether a file for water meters was previously created.
                if (fiWaterMeters.Exists)
                {
                    // If such a file exists, create a Stream for it
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        // Store the stream of water meters into the XML Dom that was created earlier
                        xdWaterMeters.Load(fsWaterMeters);
                        // Get a list of the water meter elements from the XML Dom object
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.ChildNodes;
    
                        int i = 1;
    
                        // Check each water meter
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            // Create a list view item to hold a record of a water meter
                            ListViewItem lviWaterMeter = new ListViewItem(i.ToString());
    
                            lviWaterMeter.SubItems.Add(xnWaterMeter.FirstChild!.InnerText);
                            lviWaterMeter.SubItems.Add(xnWaterMeter.FirstChild.NextSibling!.InnerText);
                            lviWaterMeter.SubItems.Add(xnWaterMeter.FirstChild.NextSibling.NextSibling!.InnerText);
                            lviWaterMeter.SubItems.Add(xnWaterMeter.FirstChild.NextSibling.NextSibling.NextSibling!.InnerText);
    
                            // Pass the list view item to the list view object on the form
                            lvwWaterMeters.Items.Add(lviWaterMeter);
    
                            i++;
                        }
                    }
                }
            }
    
            private void Central_Load(object sender, EventArgs e)
            {
                // When the open opens, make an attempt to display a list of water meters.
                ShowWaterMeters();
            }
    
            private void btnNewWaterMeter_Click(object sender, EventArgs e)
            {
                // Get a reference to the form used to add a water meter
                Create wm = new();
                // Create a FileInfo object
                FileInfo? fiWaterMeters = null;
                // Create a file stream object
                FileStream? fsWaterMeters = null;
                // Create an XML Dom object
                XmlDocument xdWaterMeters = new XmlDocument();
                // Declare a string for a file to hold a list of water meters
                string? strWaterMeters = @"C:\Stellar Water Point1\WaterMeters.xml";
    
                /* Display the form used to create a water meter. 
                 * If the user finishes using that form and click the OK button... */
                if (wm.ShowDialog() == DialogResult.OK)
                {
                    // Store the file of water meters into the FileInfo object that was previously created.
                    fiWaterMeters = new FileInfo(strWaterMeters);
    
                    /* Find out whether a list of water meters was previously created 
                     * and was stored in the string file declared above. */
                    if (fiWaterMeters.Exists)
                    {
                        /* If that file exists already, create a Stream object 
                         * for it with a read-only status. */
                        using (fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open,
                                                              FileAccess.Read, FileShare.Read))
                        {
                            // Pass the list of water meters to the XML Dom object created earlier
                            xdWaterMeters.Load(fsWaterMeters);
                        }
                    }
                    else
                    {
                        // If a file for water meters was not previously created, create it now...
                        using (fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Create,
                                                              FileAccess.Write, FileShare.Write))
                        {
                            // and create the root XML element for it
                            xdWaterMeters.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                                  "<water-meters></water-meters>");
                            // Make sure you save the new file
                            xdWaterMeters.Save(fsWaterMeters);
                        }
                    }
    
                    // Now that the file exists, open it
                    using (fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.OpenOrCreate,
                                                          FileAccess.ReadWrite, FileShare.ReadWrite))
                    {
                        // Start creating a new Water Meter XML element
                        XmlElement xeWaterMeter = xdWaterMeters.CreateElement("water-meter");
    
                        /* Use the values that the user had typed in the Create form.
                         * Use those values to create the child elements of the new water meter node.
                         * Assign the combination of child elements to the new water meter node. */
                        xeWaterMeter.InnerXml = "<meter-number>" + wm.mtbMeterNumber.Text + "</meter-number>" +
                                                "<make>" + wm.txtMake.Text + "</make>" +
                                                "<model>" + wm.txtModel.Text + "</model>" +
                                                "<meter-size>" + wm.txtMeterSize.Text + "</meter-size>";
                        // Once the XML element is ready, add/append it to the XML Dom that was previously created.
                        xdWaterMeters.DocumentElement!.AppendChild(xeWaterMeter);
                        // Once the new element has been created and add it to the file, save that file
                        xdWaterMeters.Save(fsWaterMeters);
                    }
                }
    
                /* Whenever the user has finished using the Create form, 
                 * make an attempt to display the list of water meters. */
                ShowWaterMeters();
            }
    
            private void btnViewWaterMeter_Click(object sender, EventArgs e)
            {
                /* Get a reference to the dialog box that is used 
                 * to view information about a water meter. */
                Details view = new();
                // Display that dialog box
                view.ShowDialog();
    
                // After using the dialog box, make an attempt to display the list of water meters.
                ShowWaterMeters();
            }
    
            private void btnEditWaterMeter_Click(object sender, EventArgs e)
            {
                /* Get a reference to the dialog box that is used 
                 * to update the details of a water meter. */
                Editor editor = new();
                // Display that dialog box
                editor.ShowDialog();
    
                // After using the dialog box, make an attempt to display the list of water meters.
                ShowWaterMeters();
            }
    
            private void btnDeleteWateMeter_Click(object sender, EventArgs e)
            {
                Delete del = new Delete();
                del.ShowDialog();
    
                ShowWaterMeters();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  17. To execute the application, on the main menu, click Debug -> Start Without Debugging
  18. On the Central form, click the Water Meters button:

    Stellar Water Point - Water Meters

  19. Click the Delete Water Meter button:

    Stellar Water Point - Water Meter Deletion

  20. In the Meter # text, type 630-07-055
  21. Click the Find button:

    Stellar Water Point - New Water Meter

  22. Click the Delete button:

    Stellar Water Point - Water Meter Deletion

  23. On the message box, click Yes:

    Stellar Water Point - Water Meters

  24. Close the forms and return to your programming environment

Customers

Introduction

Obviously, customers are the ones who use the services of the bussiness whose application we are building. Obviously, a customer is represented by a business account, and a water meter must be associated to a customer's account. As seen with water meterrs, the application will use forms to create and manage customers accounts.

Customers Accounts

Our application will wuse a database that contains a list of customers. As seen with water meter records, we assume that some time to time, a user will want to view those records. To display a list of customers, we will create a form equipped with a list view.

Practical LearningPractical Learning: Displaying Customers Accounts

  1. To create a folder, in the Solution Explorer, right-click the StellarWaterPoint1 project -> Add -> New Folder
  2. Type Customers as the name of the folder
  3. To create a form, in the Solution Explorer, right-click Models -> Add -> Form (Windows Forms)...
  4. Type Central
  5. Click Add
  6. In the Toolbox, click the ListView button and click the form
  7. On the form, right-click the list view and click Edit Columns...
  8. Create the columns as follows:
    (Name) Text TextAlign Width
    colCustomerId Id   40
    colAccountNumber Account # Center 150
    colMeterNumber Meter # Center 120
    colFirstName First Name   135
    colLastName Last Name   135
    colAddress Address   250
    colCity City   125
    colCounty County   135
    colState State Center  
    colZIPCode ZIP-Code Center 125
  9. Click OK
  10. Complete the design of the form as follows:

    Stellar Water Point - Customers

    Control (Name) Text Other Properties
    ListView List View lvwCustomers   FullRowSelect: True
    GridLines: True
    View: Details
    Anchor: Top, Bottom, Left, Right
    Button Button btnNewCustomerAccount &New Customer Account... Anchor: Bottom, Right
    Button Button btnCreateCustomerAccount &Create Customer Account... Anchor: Bottom, Right
    Button Button btnEditCustomerAccount &Edit Customer Account... Anchor: Bottom, Right
    Button Button btnDeleteCustomerAccount &Delete Customer Account... Anchor: Bottom, Right
    Button Button btnClose &Close Anchor: Bottom, Right
  11. Doubte-click an unoccupied area of the form to generate its Load event
  12. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint1.Customers
    {
        public partial class Central : Form
        {
            public Central()
            {
                InitializeComponent();
            }
    
            private void ShowCustomers()
            {
                int i = 1;
    
                lvwCustomers.Items.Clear();
    
                XmlDocument xdCustomers = new XmlDocument();
                string? strCustomers = @"C:\Stellar Water Point\Customers.xml";
    
                FileInfo? fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists)
                {
                    using (FileStream? fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdCustomers.Load(fsCustomers);
                        XmlNodeList xnlCustomers = xdCustomers.DocumentElement!.ChildNodes;
    
                        foreach (XmlNode xnCustomer in xnlCustomers)
                        {
                            ListViewItem lviCustomer = new ListViewItem(i.ToString());
    
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild!.InnerText);   // Account #
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling!.InnerText);   // Meter #
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling.NextSibling!.InnerText); // First Name
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling!.InnerText);   // Last Name
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling!.InnerText);   // Address
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText);   // City
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.InnerText);   // County
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText);   // State
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText); // ZIP-Code
    
                            lvwCustomers.Items.Add(lviCustomer);
    
                            i++;
                        }
                    }
                }
            }
    
            private void Central_Load(object sender, EventArgs e)
            {
                ShowCustomers();
            }       
        }
    }
  13. Display the code of the WaterDistribution.cs file and change the event that displays the customers as follows:
    namespace StellarWaterPoint1
    {
        public partial class WaterDistribution : Form
        {
            public Switchboard()
            {
                InitializeComponent();
            }
    
            private void Switchboard_Load(object sender, EventArgs e)
            {
                Directory.CreateDirectory(@"C:\Stellar Water Point");
            }
    
            private void btnProcessingWaterBill_Click(object sender, EventArgs e)
            {
                
            }
    
            private void btnViewWaterBill_Click(object sender, EventArgs e)
            {
                
            }
    
            private void btnEditWaterBill_Click(object sender, EventArgs e)
            {
                
            }
    
            private void btnDeleteWaterBill_Click(object sender, EventArgs e)
            {
                
            }
    
            private void btnCustomers_Click(object sender, EventArgs e)
            {
                Customers.Central central = new Customers.Central();
    
                central.ShowDialog();
            }
    
            private void btnWaterMeters_Click(object sender, EventArgs e)
            {
                WaterMeters.Central central = new WaterMeters.Central();
    
                central.ShowDialog();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }

A Customer's Account

As mentioned already, our application will use a database that contains a list of customers. This means that a customer must have an account. We will create a form to let the user create an account. One important detail is that a customer must have a water meter. Therefore, each customer account must have an associated water meter. To set this up, on the form used to create a customer's account, we will add a text box that allows a user to specify and validate a water meter.

Practical LearningPractical Learning: Creating a Customer Account

  1. In the Solution Explorer, right-click the Customers folder -> Add -> Form (Windows Forms)...
  2. Type Create as the name of the file
  3. Click Add
  4. Design the form as follows:

    Stellar Water Point - New Customer Account

    Control (Name) Text Other Properties
    Label Label   &Account #:  
    MaskedTextBox Masked Text Box mtbAccountNumber   Masked: 0000-000-0000
    Label Label   &Meter #:  
    MaskedTextBox Masked Text Box mtbMeterNumber   Masked: 000-00-000
    Button Button btnFindWaterMeter &Find Water Meter  
    Label Label   Meter &Details:  
    TextBox Text Box txtMeterDetails    
    Label Label   &First Name:  
    TextBox Text Box txtFirstName    
    Label Label   &Last Name:  
    TextBox Text Box txtLastName    
    Label Label   &Address:  
    TextBox Text Box txtAddress    
    Label Label   C&ity:  
    TextBox Text Box txtCity    
    Label Label   C&ounty:  
    TextBox Text Box txtCounty    
    Label Label   &State:  
    TextBox Text Box txtState    
    Label Label   &ZIP-Code:  
    MaskedTextBox Masked Text Box mtbZIPCode   Masked: Zip-Code
    Button Button btnSaveCustomerAccount S&ave Customer Account  
    Button Button btnClose &Close  
  5. Using the Properties window, change some characteristics of the form as follows:
    FormBorderStyle: FixedDialog
    Text:            Stellar Water Point - Customer Account Setup
    StartPosition:   CenterScreen
    AcceptButton:    btnSaveCustomerAccount
    CancelButton:    btnCancel
  6. On the form, double-click the Find Water Meter button
  7. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint1.Customers
    {
        public partial class Create : Form
        {
            public Create()
            {
                InitializeComponent();
            }
    
            private void btnFindWaterMeter_Click(object sender, EventArgs e)
            {
                // Create an XML Dom object
                XmlDocument xdWaterMeters = new XmlDocument();
                // Declare a string variable and assign the file of water meters to it
                string? strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
                // Create a FileInfo object to manage the file that has the water meters
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
    
                // Find out whether a file for water meters exists already
                if (fiWaterMeters.Exists)
                {
                    // If a file for water meters exists already, create a Stream object for it
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open,
                                                                      FileAccess.Read, FileShare.Read))
                    {
                        /* From the file of water meters, store the list of water meters 
                         * in the XML Dom that was previously created. */
                        xdWaterMeters.Load(fsWaterMeters);
    
                        /* Check the list of water meters. 
                         * Find a water meter that has the same name as the meter number that the user typed. */
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + mtbMeterNumber.Text + "']")!;
    
                        // If such a water meter exists...
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            // ... store its details in the meter details text box.
                            txtMeterDetails.Text = xnWaterMeter.NextSibling!.InnerText + " " +
                                                   xnWaterMeter.NextSibling.NextSibling!.InnerText + " (Meter Size: " +
                                                   xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText + ")";
                        }
                    }
                }
            }
        }
    }
  8. Display the Central form of the Customers folder
  9. Double-click the Create Customer Account button
  10. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint10.Customers
    {
        public partial class Central : Form
        {
            public Central()
            {
                InitializeComponent();
            }
    
            private void ShowCustomers()
            {
                int i = 1;
    
                lvwCustomers.Items.Clear();
    
                XmlDocument xdCustomers = new XmlDocument();
                string? strCustomers = @"C:\Stellar Water Point1\Customers.xml";
    
                FileInfo? fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists)
                {
                    using (FileStream? fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdCustomers.Load(fsCustomers);
                        XmlNodeList xnlCustomers = xdCustomers.DocumentElement!.ChildNodes;
    
                        foreach (XmlNode xnCustomer in xnlCustomers)
                        {
                            ListViewItem lviCustomer = new ListViewItem(i.ToString());
    
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild!.InnerText);   // Account #
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling!.InnerText);   // Meter #
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling.NextSibling!.InnerText); // First Name
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling!.InnerText);   // Last Name
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling!.InnerText);   // Address
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText);   // City
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.InnerText);   // County
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText);   // State
                            lviCustomer.SubItems.Add(xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText); // ZIP-Code
    
                            lvwCustomers.Items.Add(lviCustomer);
    
                            i++;
                        }
                    }
                }
            }
    
            private void Central_Load(object sender, EventArgs e)
            {
                // When the form opens, try displaying the list of customers
                ShowCustomers();
            }
    
            private void btnCreateCustomerAccount_Click(object sender, EventArgs e)
            {
                Create create = new Create();
    
                if (create.ShowDialog() == DialogResult.OK)
                {
                    /* Make sure the user provides an account number for the new account. 
                     * If not, don't create the account. */
                    if (string.IsNullOrEmpty(create.mtbAccountNumber.Text))
                    {
                        MessageBox.Show("You must provide an account number for the new customer. " +
                                        "Otherwise, the account cannot be created.",
                                        "Stellar Water Point",
                                        MessageBoxButtons.OK, MessageBoxIcon.Information);
    
                        return;
                    }
    
                    /* If the meter details text box is empty, it means the user didn't enter
                     * a meter number, in which case there is no water meter associated 
                     * with the account. The account cannot be created. */
                    if (string.IsNullOrEmpty(create.txtMeterDetails.Text))
                    {
                        MessageBox.Show("You must enter a water meter to associate with a new customer's account.",
                                        "Stellar Water Point",
                                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                        
                        return;
                    }
                    
                    // Create a FileInfo object that will be used to manage a file
                    FileInfo? fiCustomers = null;
                    // Start a Stream object that will be used to manage a file
                    FileStream? fsCustomers = null;
                    // Create an XML Dom
                    XmlDocument xdCustomers = new XmlDocument();
                    // Declare a string variable for the file that contains a list of customers
                    string? strCustomers = @"C:\Stellar Water Point1\Customers.xml";
                    
                    // Pass the file of customers to the FileInfo object that was started
                    fiCustomers = new FileInfo(strCustomers);
    
                    // Find out whether that file was already created
                    if (fiCustomers.Exists)
                    {
                        /* If that file was already created, open it through 
                         * the Stream object that was previously initiated. */
                        using (fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Open,
                                                            FileAccess.Read, FileShare.Read))
                        {
                            // Pass the Stream object to the XML Dom that was previously created.
                            xdCustomers.Load(fsCustomers);
                        }
                    }
                    else
                    {
                        /* If the file of customers was not created already, start by 
                         * initializing the Stream object that was previously initiated. */
                        using (fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Create, FileAccess.Write, FileShare.Write))
                        {
                            // Create a root to start the XML file
                            xdCustomers.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                                "<customers></customers>");
                            // Once the file has been started, save it
                            xdCustomers.Save(fsCustomers);
                        }
                    }
    
                    // Now that we have an XML file for customers, open it
                    using (fsCustomers = new FileStream(fiCustomers.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
                    {
                        /* We want to create an XML element to be added to the XML file.
                         * To start, create an XML element named "customer". */
                        XmlElement xeCustomer = xdCustomers.CreateElement("customer");
    
                        // Create/Format the child nodes of the "customer" element
                        xeCustomer.InnerXml = "<account-number>" + create.mtbAccountNumber.Text + "</account-number>" +
                                              "<meter-number>"   + create.mtbMeterNumber.Text   + "</meter-number>"   +
                                              "<first-name>"     + create.txtFirstName.Text     + "</first-name>"     +
                                              "<last-name>"      + create.txtLastName.Text      + "</last-name>"      +
                                              "<address>"        + create.txtAddress.Text       + "</address>"        +
                                              "<city>"           + create.txtCity.Text          + "</city>"           +
                                              "<county>"         + create.txtCounty.Text        + "</county>"         +
                                              "<state>"          + create.txtState.Text         + "</state>"          +
                                              "<zip-code>"       + create.mtbZIPCode.Text       + "</zip-code>";
                        xdCustomers.DocumentElement!.AppendChild(xeCustomer);
                        xdCustomers.Save(fsCustomers);
                    }
                }
    
                ShowCustomers();
            }
        }
    }
  11. To execute the application, on the main menu, click Debug -> Start Without Debugging
  12. On the Water Distribution form, click the Customers button
  13. On the Central form of the customers, click the Create Customer Account button:

    Stellar Water Point - New Customer Account

  14. In the account # text box, type 9279-570-8394
  15. In the meter # text box, type 799-28-461
  16. Click the Find water meter button
  17. Using the values in the following table, enter an account number, then enter a meter number and click Find Water Meter. Complete the record with the other values. Then click Save Customer Account:

    Stellar Water Point - New Customer Account

    Account # Meter # First Name Last Name Address City County State ZIP-Code
    9279-570-8394 799-28-461 Thomas Stones 10252 Broward Ave #D4 Frederick Frederick MD 21703-6628
    2068-258-9486 186-92-805 Ericka Dellaney 4819 East Munk Street Whitehall Fulton PA 17340-2277
    4820-375-2842 392-44-572 Akhil Koumari 748 Red Hills Rd Roanoke   VA 24012-9726
    6003-386-3955 207-94-835 Mendia Mahmoud 53 Avalon Crt Greener Essex DW 19250-2008
    9249-379-6848 588-29-663 Richard Eghert 8280 Sligo North Way Albright Preston WV 26519-4626
    7518-302-6895 207-94-835 Grace Brenner 4299 Peachtree Court Rockville Montgomery MD 20853-1512
    3028-502-9418 186-99-757 Spencer Kershaw 338C Grayson Street Gatchellville York PA 17352-3808
    5293-957-3395 386-48-057 Kelly Davids 10484 Greenway Avenue Mt Storm Grant WV 26739-6242
    2038-413-9680 938-75-869 Amidou Gomah 2075 Rose Hills Avenue Washington   DC 20004-1818
    7028-405-9381 306-82-497 Jonathan Simmings 613 Meadowhill Road Alonzaville Shenandoah VA 22664-2662
    5938-074-5293 592-84-957 Marie Rath 582G Dunhill Avenue Lanham Prince Georges MD 20706-4422
    1827-395-0203 470-68-850 Sathyavanthara Khooni 10331 Chryswell Road Washington   DC 20008-5050
    8027-304-6829 837-06-836 Anthony Clarcksons 904 Augusta Drive Blackbird New Castle DE 19734-2606
    6699-396-2905 649-33-505 Spencer Reuter 2850 Burnsweak Avenue Silver Spring Montgomery MD 20910-7272
    7080-583-5947 827-50-248 Sandra Moffat 663 Sherry Wood East Street Shimpstown Franklin PA 17236-1116

    Stellar Water Point - Customers

  18. Close the forms and return to your programming environment
namespace StellarWaterPoint1
{
    public partial class WaterDistribution : Form
    {
        public Switchboard()
        {
            InitializeComponent();
        }

        private void Switchboard_Load(object sender, EventArgs e)
        {
            Directory.CreateDirectory(@"C:\Stellar Water Point");
        }

        private void btnProcessingWaterBill_Click(object sender, EventArgs e)
        {
            WaterBills.Create create = new WaterBills.Create();

            create.ShowDialog();
        }

        private void btnViewWaterBill_Click(object sender, EventArgs e)
        {
            WaterBills.Details details = new WaterBills.Details();

            details.ShowDialog();
        }

        private void btnEditWaterBill_Click(object sender, EventArgs e)
        {
            WaterBills.Editor editor = new WaterBills.Editor();

            editor.ShowDialog();
        }

        private void btnDeleteWaterBill_Click(object sender, EventArgs e)
        {
            WaterBills.Delete delete = new WaterBills.Delete();

            delete.ShowDialog();
        }

        private void btnCustomers_Click(object sender, EventArgs e)
        {
            Customers.Central central = new Customers.Central();

            central.ShowDialog();
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            Close();
        }
    }
}
  1. Type Customers as the name of the folder
  2. To create a form, on the main menu, click Customers -> Add ->
  3. Return to the form and double-click the Edit Water Meter button
  4. Return to the form and double-click the Delete Water Meter button
  5. Return to the form and double-click the Close button
  6. Change the document as follows:
    
            private void btnDeleteWaterMeter_Click(object sender, EventArgs e)
            {
                Delete delete = new();
    
                delete.ShowDialog();
    
                ShowWaterMeters();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }

Practical LearningPractical Learning: Preparing Customers Accounts

  1. To create a form, in the Solution Explorer, right-click Customers -> Add -> Form (Windows Forms)...
  2. Type Details
  3. Press Enter
  4. Resize the Editor form to have the same size as the Create form
  5. Copy everything from the Create form and paste it in the Editor form
  6. Delete the bottom two buttons and add a new button
  7. Change the design of the form as follows:

    Stellar Water Point - New Water Meter

    Control (Name) Other Properties
    Button Button btnFindCustomerAccount &Find Customer Account
    Button Button btnClose &Close
  8. Using the Properties window, change some characteristics of the form as follows:
    FormBorderStyle: FixedDialog
    Text:            Stellar Water Point - Customer Account Details
    StartPosition:   CenterScreen
    CancelButton:    btnClose
  9. On the form, double-click the Find Customer Account
  10. Return to the form and double-click the Close button
  11. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint1.Customers
    {
        public partial class Details : Form
        {
            public Details()
            {
                InitializeComponent();
            }
    
            private void btnFindCustomerAccount_Click(object sender, EventArgs e)
            {
                XmlDocument xdCustomers = new XmlDocument();
                string? strCustomers = @"C:\Stellar Water Point\Customers.xml";
    
                FileInfo? fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists)
                {
                    using (FileStream? fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdCustomers.Load(fsCustomers);
                        XmlNodeList xnlCustomers = xdCustomers.DocumentElement!.SelectNodes("//account-number[.='" + mtbAccountNumber.Text + "']")!;
    
                        foreach (XmlNode xnCustomer in xnlCustomers)
                        {
                            mtbMeterNumber.Text = xnCustomer.NextSibling!.InnerText;   // Meter #
                            txtFirstName.Text   = xnCustomer.NextSibling.NextSibling!.InnerText; // First Name
                            txtLastName.Text    = xnCustomer.NextSibling.NextSibling.NextSibling!.InnerText;   // Last Name
                            txtAddress.Text     = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.InnerText;   // Address
                            txtCity.Text        = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText;   // City
                            txtCounty.Text      = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.InnerText;   // County
                            txtState.Text       = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;   // State
                            mtbZIPCode.Text     = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText; // ZIP-Code
                        }
                    }
                }
    
                XmlDocument xdWaterMeters = new XmlDocument();
                string? strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
    
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists)
                {
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterMeters.Load(fsWaterMeters);
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + mtbMeterNumber.Text + "']")!;
    
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            txtMeterDetails.Text = xnWaterMeter.NextSibling!.InnerText + " " +
                                                   xnWaterMeter.NextSibling.NextSibling!.InnerText + " (Meter Size: " +
                                                   xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText + ")";
                        }
                    }
                }
            }
        }
    }
  12. To create a form, in the Solution Explorer, right-click Customers -> Add -> Form (Windows Forms)...
  13. Type Editor
  14. Press Enter
  15. Resize the Editor form to have the same size as the Create form
  16. Copy everything from the Create form and paste it in the Editor form
  17. Change the design as follows:

    Stellar Water Point - Customer Editor

    Control (Name) Text Other Properties
    Button Button btnFindCustomerAccount &Find Customer Account  
    Button Button btnFindWaterMeter &Find Water Meter  
    Button Button btnUpdateCustomerAccount &Update Customer Account  
    Button Button btnCancel &Cancel DialogResult: Cancel
  18. Using the Properties window, change some characteristics of the form as follows:
    FormBorderStyle: FixedDialog
    Text:            Stellar Water Point - Customer Account Editor
    StartPosition:   CenterScreen
    CancelButton:    btnCancel
  19. On the form, double-click the Find Customer Account
  20. Return to the form and double-click the Find Water Meter button
  21. Return to the form and double-click the Update Water Meter button
  22. Change the document as tollows:
    using System.Xml;
    
    namespace StellarWaterPoint1.Customers
    {
        public partial class Editor : Form
        {
            public Editor()
            {
                InitializeComponent();
            }
    
            private void btnFindCustomerAccount_Click(object sender, EventArgs e)
            {
                XmlDocument xdCustomers  = new XmlDocument();
                string?     strCustomers = @"C:\Stellar Water Point\Customers.xml";
    
                FileInfo?   fiCustomers  = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists)
                {
                    using (FileStream? fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdCustomers.Load(fsCustomers);
                        XmlNodeList xnlCustomers   = xdCustomers.DocumentElement!.SelectNodes("//account-number[.='" + mtbAccountNumber.Text + "']")!;
    
                        foreach (XmlNode xnCustomer in xnlCustomers)
                        {
                            mtbMeterNumber.Text = xnCustomer.NextSibling!.InnerText;   // Meter #
                            txtFirstName.Text   = xnCustomer.NextSibling.NextSibling!.InnerText; // First Name
                            txtLastName.Text    = xnCustomer.NextSibling.NextSibling.NextSibling!.InnerText;   // Last Name
                            txtAddress.Text     = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.InnerText;   // Address
                            txtCity.Text        = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText;   // City
                            txtCounty.Text      = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.InnerText;   // County
                            txtState.Text       = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;   // State
                            mtbZIPCode.Text     = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText; // ZIP-Code
                        }
                    }
                }
    
                XmlDocument xdWaterMeters  = new XmlDocument();
                string?     strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
    
                FileInfo?   fiWaterMeters  = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists)
                {
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterMeters.Load(fsWaterMeters);
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + mtbMeterNumber.Text + "']")!;
    
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            txtMeterDetails.Text = xnWaterMeter.NextSibling!.InnerText + " " +
                                                   xnWaterMeter.NextSibling.NextSibling!.InnerText + " (Meter Size: " +
                                                   xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText + ")";
                        }
                    }
                }
            }
    
            private void btnFindWaterMeter_Click(object sender, EventArgs e)
            {
                XmlDocument xdWaterMeters  = new XmlDocument();
                string?     strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
    
                FileInfo? fiWaterMeters    = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists)
                {
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterMeters.Load(fsWaterMeters);
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + mtbMeterNumber.Text + "']")!;
    
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            txtMeterDetails.Text = xnWaterMeter.NextSibling!.InnerText + " " +
                                                   xnWaterMeter.NextSibling.NextSibling!.InnerText + " (Meter Size: " +
                                                   xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText + ")";
                        }
                    }
                }
            }
    
            private void btnUpdateCustomerAccount_Click(object sender, EventArgs e)
            {
                XmlDocument xdCustomers = new XmlDocument();
                string? strCustomers    = @"C:\Stellar Water Point\Customers.xml";
    
                FileInfo? fiCustomers   = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists)
                {
                    using (FileStream? fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdCustomers.Load(fsCustomers);
                        XmlNodeList xnlCustomers   = xdCustomers.DocumentElement!.SelectNodes("//account-number[.='" + mtbAccountNumber.Text + "']")!;
    
                        foreach (XmlNode xnCustomer in xnlCustomers)
                        {
                            xnCustomer.ParentNode!.InnerXml = "<account-number>" + mtbAccountNumber.Text + "</account-number>" +
                                                              "<meter-number>"   + mtbMeterNumber.Text   + "</meter-number>"   +
                                                              "<first-name>"     + txtFirstName.Text     + "</first-name>"     +
                                                              "<last-name>"      + txtLastName.Text      + "</last-name>"      +
                                                              "<address>"        + txtAddress.Text       + "</address>"        +
                                                              "<city>"           + txtCity.Text          + "</city>"           +
                                                              "<county>"         + txtCounty.Text        + "</county>"         +
                                                              "<state>"          + txtState.Text         + "</state>"          +
                                                              "<zip-code>"       + mtbZIPCode.Text       + "</zip-code>";
                        }
                    }
    
                    using (FileStream? fsCustomers = new FileStream(fiCustomers.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
                    {
                        xdCustomers.Save(fsCustomers);
                    }
                }
    
                Close();
            }
        }
    }
  23. To create a form, in the Solution Explorer, right-click Customers -> Add -> Form (Windows Forms)...
  24. Type Delete
  25. Press Enter
  26. Resize the Editor form to have the same size as the Editor form
  27. Copy everything from the Editor form and paste it in the Delete form
  28. Delete the Find Water Meter button and change the bottom button as follows:

    Stellar Water Point - Customer Deletion

    Control (Name) Text
    Button Button btnDeleteCustomerAccount &Delete Customer Account
  29. Using the Properties window, change some characteristics of the form as follows:
    FormBorderStyle: FixedDialog
    Text:            Stellar Water Point - Customer Account Deletion
    StartPosition:   CenterScreen
    CancelButton:    btnCancel
  30. On the form, double-click the Find Customer Account
  31. Return to the form and double-click the Delete Water Meter button
  32. Change the document as tollows:
    using System.Xml;
    
    namespace StellarWaterPoint1.Customers
    {
        public partial class Delete : Form
        {
            public Delete()
            {
                InitializeComponent();
            }
    
            private void btnFindCustomerAccount_Click(object sender, EventArgs e)
            {
                XmlDocument xdCustomers = new XmlDocument();
                string? strCustomers = @"C:\Stellar Water Point\Customers.xml";
    
                FileInfo? fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists)
                {
                    using (FileStream? fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdCustomers.Load(fsCustomers);
                        XmlNodeList xnlCustomers = xdCustomers.DocumentElement!.SelectNodes("//account-number[.='" + mtbAccountNumber.Text + "']")!;
    
                        foreach (XmlNode xnCustomer in xnlCustomers)
                        {
                            mtbMeterNumber.Text = xnCustomer.NextSibling!.InnerText;   // Meter #
                            txtFirstName.Text   = xnCustomer.NextSibling.NextSibling!.InnerText; // First Name
                            txtLastName.Text    = xnCustomer.NextSibling.NextSibling.NextSibling!.InnerText;   // Last Name
                            txtAddress.Text     = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.InnerText;   // Address
                            txtCity.Text        = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText;   // City
                            txtCounty.Text      = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.InnerText;   // County
                            txtState.Text       = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;   // State
                            mtbZIPCode.Text     = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText; // ZIP-Code
                        }
                    }
                }
    
                XmlDocument xdWaterMeters = new XmlDocument();
                string? strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
    
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists)
                {
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterMeters.Load(fsWaterMeters);
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + mtbMeterNumber.Text + "']")!;
    
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            txtMeterDetails.Text = xnWaterMeter.NextSibling!.InnerText + " " +
                                                   xnWaterMeter.NextSibling.NextSibling!.InnerText + " (Meter Size: " +
                                                   xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText + ")";
                        }
                    }
                }
            }
    
            private void btnDeleteCustomerAccount_Click(object sender, EventArgs e)
            {
                XmlDocument xdCustomers = new XmlDocument();
                string? strCustomers = @"C:\Stellar Water Point\Customers.xml";
    
                if (string.IsNullOrEmpty(mtbAccountNumber.Text))
                {
                    MessageBox.Show("You must type an account number for the customer whose account you want to deleteone.",
                                    "Stellar Water Point", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
    
                if (!File.Exists(strCustomers))
                {
                    MessageBox.Show("There is no file for the customers accounts in the system.",
                                    "Stellar Water Point",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
    
                xdCustomers.Load(strCustomers);
    
                XmlNodeList xnlCustomers = xdCustomers.DocumentElement!.GetElementsByTagName("account-number");
    
                foreach (XmlNode xnCustomer in xnlCustomers)
                {
                    if (xnCustomer.InnerText == mtbAccountNumber.Text)
                    {
                        if (MessageBox.Show("Are you sure you want to remove this customer's account from the system?",
                                        "Stellar Water Point",
                                        MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                        {
                            xdCustomers.DocumentElement.RemoveChild(xnCustomer.ParentNode!);
                            break;
                        }
                    }
                }
    
                xdCustomers.Save(strCustomers);
    
                Close();
            }
        }
    }
  33. Return to the form and double-click the New Customer Account button
  34. Return to the form and double-click the View Customer Account button
  35. Return to the form and double-click the Edit Customer Account button
  36. Return to the form and double-click the Delete Customer Account button
  37. Return to the form and double-click the Close button
  38. Change the document as follows:
    
            private void btnNewCustomerAccount_Click(object sender, EventArgs e)
            {
                FileInfo? fiCustomers = null;
                FileStream? fsCustomers = null;
                Create create = new Create();
                XmlDocument xdCustomers = new XmlDocument();
                string? strCustomers = @"C:\Stellar Water Point\Customers.xml";
    
                if (create.ShowDialog() == DialogResult.OK)
                {
                    fiCustomers = new FileInfo(strCustomers);
    
                    if (fiCustomers.Exists)
                    {
                        using (fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                        {
                            xdCustomers.Load(fsCustomers);
                        }
                    }
                    else
                    {
                        using (fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Create, FileAccess.Write, FileShare.Write))
                        {
                            xdCustomers.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                                  "<customers></customers>");
                            xdCustomers.Save(fsCustomers);
                        }
                    }
    
                    using (fsCustomers = new FileStream(fiCustomers.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
                    {
                        XmlElement xeCustomer = xdCustomers.CreateElement("customer");
    
                        xeCustomer.InnerXml = "<account-number>" + create.mtbAccountNumber.Text + "</account-number>" +
                                                "<meter-number>" + create.mtbMeterNumber.Text   + "</meter-number>"   +
                                                "<first-name>"   + create.txtFirstName.Text     + "</first-name>"     +
                                                "<last-name>"    + create.txtLastName.Text      + "</last-name>"      +
                                                "<address>"      + create.txtAddress.Text       + "</address>"        +
                                                "<city>"         + create.txtCity.Text          + "</city>"           +
                                                "<county>"       + create.txtCounty.Text        + "</county>"         +
                                                "<state>"        + create.txtState.Text         + "</state>"          +
                                                "<zip-code>"     + create.mtbZIPCode.Text       + "</zip-code>";
                        xdCustomers.DocumentElement!.AppendChild(xeCustomer);
                        xdCustomers.Save(fsCustomers);
                    }
                }
    
                ShowCustomers();
            }
    
            private void btnViewCustomerAccount_Click(object sender, EventArgs e)
            {
                Details editor = new Details();
    
                editor.ShowDialog();
            }
    
            private void btnEditCustomerAccount_Click(object sender, EventArgs e)
            {
                Editor editor = new Editor();
    
                editor.ShowDialog();
    
                ShowCustomers();
            }
    
            private void btnDeleteCustomerAccount_Click(object sender, EventArgs e)
            {
                Delete delete = new Delete();
    
                delete.ShowDialog();
    
                ShowCustomers();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }

Water Bills

A water bill is a summary that indicates how much water a customer consumed and the value of that consumption. Our application will include a form to process a water bill. We will use another form that can be used to review an existing water bill. We will use another form to change or update a water bill that was previously processed. Finally, we will have a form that can be used to delete a water bill. In previous sections, we provided one Central form for the water meters and another Central form for the Customers. Those Central forms allow the user to navigate to the forms related to a section. Those sections included a form that provides a list of records. Because a water bill has too many values, we will not create a form that presents a list of water bills.

Practical LearningPractical Learning: Preparing Bills

  1. In the Solution Explorer, right-click StellarWaterPoint1 -> Add -> New Folder
  2. Type WaterBills as the name of the folder
  3. To create a form, in the Solution Explorer, right-click WaterBills -> Add -> Form (Windows Forms)...
  4. Type Create as the name of the file
  5. Press Enter
  6. Design the form as follows:

    Stellar Water Point - New Water Bill

    Control (Name) Text Other Properties
    Label Label   Water Bill #:  
    TextBox Text Box txtBillNumber    
    GroupBox Label   Customer Information  
    Label Label   Account #:  
    MaskedTextBox Masked Text Box mtbAccountNumber   Masked: 0000-000-0000
    Button Button btnFindCustomerAccount Find Customer Account  
    Label Label   Customer Name:  
    TextBox Text Box txtCustomerName    
    Label Label   Address:  
    TextBox Text Box txtAddress    
    TextBox Text Box txtCity    
    TextBox Text Box txtCounty    
    TextBox Text Box txtState    
    MaskedTextBox Masked Text Box mtbZIPCode   Masked: Zip-Code
    Label Label   _______________________  
    Label Label   Meter Details:  
    TextBox Text Box txtMeterDetails Modifiers: Public  
    GroupBox Label   Meter Reading  
    Label Label   Meter Reading Start Date:  
    DateTimePicker Date Time Picker dtpMeterReadingStartDate  
    Label Label   Meter Reading End Date:  
    DateTimePicker Date Time Picker dtpMeterReadingEndDate  
    Label Label   Counter Reading Start:  
    TextBox Text Box txtCounterReadingStart    
    Label Label   Counter Reading End:  
    TextBox Text Box txtCounterReadingEnd    
    Button Button btnEvaluateWaterBill Evaluate Water Bill  
    GroupBox Label   Meter Result  
    Label Label   Billing Days:  
    TextBox Text Box txtBillingDays   TextAlign: Right
    Label Label   Total Gallons:  
    TextBox Text Box txtTotalGallons   TextAlign: Right
    Label Label   Total CCF:  
    TextBox Text Box txtTotalCCF   TextAlign: Right
    Label Label   First Tier Consumption:  
    TextBox Text Box txtFirstTierConsumption   TextAlign: Right
    Label Label   Second Tier:  
    TextBox Text Box txtSecondTierConsumption   TextAlign: Right
    Label Label   Last Tier:  
    TextBox Text Box txtLastTierConsumption   TextAlign: Right
    GroupBox Label   Consumption Charges  
    Label Label   Water Charges:  
    TextBox Text Box txtWaterCharges   TextAlign: Right
    Label Label   Sewer Charges:  
    TextBox Text Box txtSewerCharges   TextAlign: Right
    Label Label   Environment Charges:  
    TextBox Text Box txtEnvironmentCharges   TextAlign: Right
    Label Label   Total Charges:  
    TextBox Text Box txtTotalCharges   TextAlign: Right
    GroupBox Label   Taxes  
    Label Label   Local Taxes:  
    TextBox Text Box txtLocalTaxes   TextAlign: Right
    Label Label   State Taxes:  
    TextBox Text Box txtStateTaxes   TextAlign: Right
    GroupBox Label   Water Bill Payment  
    Label Label   Payment Due Date:  
    DateTimePicker Date Time Picker dtpPaymentDueDate  
    Label Label   Amount Due:  
    TextBox Text Box txtAmountDue   TextAlign: Right
    Label Label   Late Payment Due Date:  
    DateTimePicker Date Time Picker dtpLatePaymentDueDate  
    Label Label   Late Amount Due:  
    TextBox Text Box txtLateAmountDue   TextAlign: Right
    Button Button btnSaveWaterBill Save Water Bill  
    Button Button btnClose Close  
  7. On the form, double-click the Find Customer Account button
  8. Return to the Water Bills - Create form and double-click the Meter Reading End Date date time picker
  9. Return to the Water Bills - Create form and double-click the Evaluate Water Bill button
  10. Return to the Water Bills - Create form and double-click the Save Water Bill button
  11. Return to the form and double-click the Close button
  12. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint1.WaterBills
    {
        public partial class Create : Form
        {
            public Create()
            {
                InitializeComponent();
            }
    
            private void btnFindCustomerAccount_Click(object sender, EventArgs e)
            {
                string? strMeterNumber = null;
                XmlDocument xdCustomers = new XmlDocument();
                string? strCustomers = @"C:\Stellar Water Point\Customers.xml";
    
                FileInfo? fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists)
                {
                    using (FileStream? fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdCustomers.Load(fsCustomers);
                        XmlNodeList xnlCustomers = xdCustomers.DocumentElement!.SelectNodes("//account-number[.='" + mtbAccountNumber.Text + "']")!;
    
                        foreach (XmlNode xnCustomer in xnlCustomers)
                        {
                            strMeterNumber       = xnCustomer.NextSibling!.InnerText;   // Meter #
                            txtCustomerName.Text = xnCustomer.NextSibling.NextSibling!.InnerText + " " +
                                                   xnCustomer.NextSibling.NextSibling.NextSibling!.InnerText;   // Customer Name
                            txtAddress.Text      = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.InnerText;   // Address
                            txtCity.Text         = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText;   // City
                            txtCounty.Text       = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.InnerText;   // County
                            txtState.Text        = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;   // State
                            mtbZIPCode.Text      = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText; // ZIP-Code
                        }
                    }
                }
    
                XmlDocument xdWaterMeters  = new XmlDocument();
                string?     strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
    
                FileInfo?   fiWaterMeters  = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists)
                {
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterMeters.Load(fsWaterMeters);
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + strMeterNumber + "']")!;
    
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            txtMeterDetails.Text = xnWaterMeter.NextSibling!.InnerText + " " +
                                                   xnWaterMeter.NextSibling.NextSibling!.InnerText + " (Meter Size: " +
                                                   xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText + ")";
                        }
                    }
                }
            }
    
            private void dtpMeterReadingEndDate_ValueChanged(object sender, EventArgs e)
            {
                TimeSpan tsDays = dtpMeterReadingEndDate.Value - dtpMeterReadingStartDate.Value;
    
                txtBillingDays.Text = tsDays.Days.ToString();
            }
    
            private void btnEvaluateWaterBill_Click(object sender, EventArgs e)
            {
                double counterStart = 0, counterEnd = 0;
    
                try
                {
                    counterStart = double.Parse(txtCounterReadingStart.Text);
                }
                catch (FormatException feCRStart)
                {
                    MessageBox.Show("There was a problem with the value of the " +
                                    "Counter Reading Start. The error produced is: " + feCRStart.Message,
                                    "Stellar Water Point", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
    
                try
                {
                    counterEnd = double.Parse(txtCounterReadingEnd.Text);
                }
                catch (FormatException feCREnd)
                {
                    MessageBox.Show("There was a problem with the value of the " +
                                    "Counter Reading End. The error produced is: " + feCREnd.Message,
                                    "Stellar Water Point", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
    
                double consumption  = counterEnd   - counterStart;
                double gallons      = consumption  * 748.05;
                double firstTier    = gallons      * (48.00 / 10000.00);
                double secondTier   = gallons      * (32.00 / 10000.00);
                double lastTier     = gallons      * (20.00 / 10000.00);
                double waterCharges = firstTier    + secondTier + lastTier;
                double sewerCharges = waterCharges * 28.65 / 100;
                double envCharges   = waterCharges * 0.22184;
                double totalCharges = waterCharges + sewerCharges + envCharges;
                double localTaxes   = totalCharges * 0.06148;
                double stateTaxes   = totalCharges * 0.01374;
                double amtDue       = totalCharges + localTaxes + stateTaxes;
    
                TimeSpan tsPaymentDueDate = new TimeSpan(15, 0, 0, 0);
    
                txtTotalCCF.Text              = consumption.ToString();
                txtTotalGallons.Text          = gallons.ToString("F");
                txtFirstTierConsumption.Text  = firstTier.ToString("F");
                txtSecondTierConsumption.Text = secondTier.ToString("F");
                txtLastTierConsumption.Text   = lastTier.ToString("F");
                txtWaterCharges.Text          = waterCharges.ToString("F");
                txtSewerCharges.Text          = sewerCharges.ToString("F");
                txtEnvironmentCharges.Text    = envCharges.ToString("F");
                txtTotalCharges.Text          = totalCharges.ToString("F");
                txtLocalTaxes.Text            = localTaxes.ToString("F");
                txtStateTaxes.Text            = stateTaxes.ToString("F");
                dtpPaymentDueDate.Value       = dtpMeterReadingEndDate.Value + tsPaymentDueDate;
                txtAmountDue.Text             = amtDue.ToString("F");
                dtpLatePaymentDueDate.Value   = dtpMeterReadingEndDate.Value + new TimeSpan(30, 0, 0, 0);
                txtLateAmountDue.Text         = (amtDue + 8.95).ToString("F");
            }
    
            private void btnSaveWaterBill_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(txtBillNumber.Text))
                {
                    MessageBox.Show("You must type a bill number." +
                                    "Otherwise, the account cannot be saved.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                if (string.IsNullOrEmpty(txtCounterReadingStart.Text))
                {
                    MessageBox.Show("You must enter the start value of the water bill counter." +
                                    "Otherwise, the account cannot be saved.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                if (string.IsNullOrEmpty(mtbAccountNumber.Text))
                {
                    MessageBox.Show("You must type an account number of a customer." +
                                    "Otherwise, the account cannot be saved.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                FileStream? fsWaterBills = null;
                XmlDocument xdWaterBills = new XmlDocument();
                string strWaterBills = @"C:\Stellar Water Point\WaterBills.xml";
    
                FileInfo? fiWaterBills = new FileInfo(strWaterBills);
                
                if (fiWaterBills.Exists)    
                {
                    using(fsWaterBills = new FileStream(fiWaterBills.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterBills.Load(fsWaterBills);
                    }
                }
                else
                {
                    using (fsWaterBills = new FileStream(fiWaterBills.FullName, FileMode.Create, FileAccess.Write, FileShare.Write))
                    {
                        xdWaterBills.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                             "<water-bills></water-bills>");
                        xdWaterBills.Save(fsWaterBills);
                    }
                }
                
                using (fsWaterBills = new FileStream(fiWaterBills.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
                {
                    XmlElement xeWaterBill = xdWaterBills.CreateElement("water-bill");
                    
                    xeWaterBill.InnerXml = "<bill-number>"              + txtBillNumber.Text            + "</bill-number>"             + 
                                           "<account-number>"           + mtbAccountNumber.Text         + "</account-number>"          +
                                           "<meter-reading-start-date>" + dtpMeterReadingStartDate.Value.ToShortDateString()           + "</meter-reading-start-date>" +
                                           "<meter-reading-end-d ate>"  + dtpMeterReadingEndDate.Value.ToShortDateString()             + "</meter-reading-end-date>" +
                                           "<billing-days>"             + txtBillingDays.Text           + "</billing-days>"            +
                                           "<counter-reading-start>"    + txtCounterReadingStart.Text   + "</counter-reading-start>"   +
                                           "<counter-reading-end>"      + txtCounterReadingEnd.Text     + "</counter-reading-end>"     +
                                           "<total-gallons>"            + txtTotalGallons.Text          + "</total-gallons>"           +
                                           "<total-ccf>"                + txtTotalCCF.Text              + "</total-ccf>"               +
                                           "<first-tier-consumption>"   + txtFirstTierConsumption.Text  + "</first-tier-consumption>"  +
                                           "<second-tier-consumption>"  + txtSecondTierConsumption.Text + "</second-tier-consumption>" +
                                           "<last-tier-consumption>"    + txtLastTierConsumption.Text   + "</last-tier-consumption>"   +
                                           "<water-charges>"            + txtWaterCharges.Text          + "</water-charges>"           +
                                           "<sewer-charges>"            + txtSewerCharges.Text          + "</sewer-charges>"           +
                                           "<environment-charges>"      + txtEnvironmentCharges.Text    + "</environment-charges>"     +
                                           "<total-charges>"            + txtTotalCharges.Text          + "</total-charges>"           +
                                           "<local-taxes>"              + txtLocalTaxes.Text            + "</local-taxes>"             +
                                           "<state-taxes>"              + txtStateTaxes.Text            + "</state-taxes>"             +
                                           "<amount-due>"               + txtAmountDue.Text             + "</amount-due>"              +
                                           "<payment-due-date>"         + dtpPaymentDueDate.Value.ToShortDateString()                  + "</payment-due-date>" +
                                           "<late-amount-due>"          + txtLateAmountDue.Text         + "</late-amount-due>"         +
                                           "<late-payment-due-date>"    + dtpLatePaymentDueDate.Value.ToShortDateString()              + "</late-payment-due-date>";
                    
                    xdWaterBills.DocumentElement!.AppendChild(xeWaterBill);
                    xdWaterBills.Save(fsWaterBills);
                }
    
                Close();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  13. To create a new form, in the Solution Explorer, right-click Water Bills -> New -> Form (Windows Forms)...
  14. Type Details as the name of the form
  15. Click Add
  16. Make that form the same size as the Create Water Bill form
  17. Select everything on the Create Water Bill form. Copy that selection and paste it in the new Water Bill - Details form
  18. On the Water Bill - Details form, delete the Find Customer Account, the Evaluate Water Bill, and the Save Water Bill buttons
  19. Add a button as follows:

    Stellar Water Point - Water Bill Viewer

    Control (Name) Text
    Button Button btnFindWaterBill Find Water &Bill
  20. On the form, double-click the Find Water Bill button
  21. Return tp the form and double-click the Close button
  22. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint1.WaterBills
    {
        public partial class Details : Form
        {
            public Details()
            {
                InitializeComponent();
            }
    
            private void btnFindWaterBill_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(txtBillNumber.Text))
                {
                    MessageBox.Show("You must type a bill number." +
                                    "Otherwise, the account cannot be saved.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                string? strMeterNumber = null;
    
                FileStream? fsWaterBills = null;
                XmlDocument xdWaterBills = new XmlDocument();
                string strWaterBills = @"C:\Stellar Water Point\WaterBills.xml";
    
                FileInfo? fiWaterBills = new FileInfo(strWaterBills);
    
                if (fiWaterBills.Exists)
                {
                    using (fsWaterBills = new FileStream(fiWaterBills.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterBills.Load(fsWaterBills);
                        XmlNodeList xnlWaterBills = xdWaterBills.DocumentElement!.SelectNodes("//bill-number[.='" + txtBillNumber.Text + "']")!;
    
                        foreach (XmlNode xnWaterBill in xnlWaterBills)
                        {
                            mtbAccountNumber.Text          =                xnWaterBill.NextSibling!.InnerText;
                            dtpMeterReadingStartDate.Value = DateTime.Parse(xnWaterBill.NextSibling!.NextSibling!.InnerText); 
                            dtpMeterReadingEndDate.Value   = DateTime.Parse(xnWaterBill.NextSibling.NextSibling.NextSibling!.InnerText);
                            txtBillingDays.Text            =                xnWaterBill.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText;
                            txtCounterReadingStart.Text    =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.InnerText;
                            txtCounterReadingEnd.Text      =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText;
                            txtTotalGallons.Text           =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtTotalCCF.Text               =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtFirstTierConsumption.Text   =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtSecondTierConsumption.Text  =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtLastTierConsumption.Text    =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtWaterCharges.Text           =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtSewerCharges.Text           =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtEnvironmentCharges.Text     =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtTotalCharges.Text           =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtLocalTaxes.Text             =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtStateTaxes.Text             =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtAmountDue.Text              =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            dtpPaymentDueDate.Value        = DateTime.Parse(xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText);
                            txtLateAmountDue.Text          =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            dtpLatePaymentDueDate.Value    = DateTime.Parse(xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText);
                        }
                    }
                }
    
                XmlDocument xdCustomers = new XmlDocument();
                string? strCustomers = @"C:\Stellar Water Point\Customers.xml";
    
                FileInfo? fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists)
                {
                    using (FileStream? fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdCustomers.Load(fsCustomers);
                        XmlNodeList xnlCustomers = xdCustomers.DocumentElement!.SelectNodes("//account-number[.='" + mtbAccountNumber.Text + "']")!;
    
                        foreach (XmlNode xnCustomer in xnlCustomers)
                        {
                            strMeterNumber       = xnCustomer.NextSibling!.InnerText;   // Meter #
                            txtCustomerName.Text = xnCustomer.NextSibling.NextSibling!.InnerText + " " +
                                                   xnCustomer.NextSibling.NextSibling.NextSibling!.InnerText;   // Customer Name
                            txtAddress.Text      = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.InnerText;   // Address
                            txtCity.Text         = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText;   // City
                            txtCounty.Text       = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.InnerText;   // County
                            txtState.Text        = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;   // State
                            mtbZIPCode.Text      = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText; // ZIP-Code
                        }
                    }
                }
    
                XmlDocument xdWaterMeters = new XmlDocument();
                string? strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
    
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists)
                {
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterMeters.Load(fsWaterMeters);
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + strMeterNumber + "']")!;
    
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            txtMeterDetails.Text = xnWaterMeter.NextSibling!.InnerText + " " +
                                                   xnWaterMeter.NextSibling.NextSibling!.InnerText + " (Meter Size: " +
                                                   xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText + ")";
                        }
                    }
                }
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  23. To create a new form, in the Solution Explorer, right-click Water Bills -> New -> Form (Windows Forms)...
  24. Type Editor as the name of the form
  25. Click Add
  26. Make that form the same size as the Create Water Bill form
  27. Select everything on the Create Water Bill form. Copy that selection and paste it in the new Editor form
  28. Copy the Find Water Bill button from the Water Bill Details form and paste it on the Water Bill Editor form
  29. Complete the design of the form as follows:

    Stellar Water Point - Water Bill Editor

    Control (Name) Text
    Button Button btnUpdateWaterBill &Update Water Bill
  30. On the form, double-click the Find Water Bill button
  31. Return tp the form and double-click the Find Customer Account button
  32. Return tp the form and double-click the Meter Reading End Date date time picker
  33. Return tp the form and double-click the Evaluate Water Bill button
  34. Return tp the form and double-click the Update Water Bill button
  35. Return tp the form and double-click the Close button
  36. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint1.WaterBills
    {
        public partial class Editor : Form
        {
            public Editor()
            {
                InitializeComponent();
            }
    
            private void btnFindWaterBill_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(txtBillNumber.Text))
                {
                    MessageBox.Show("You must type a bill number." +
                                    "Otherwise, the account cannot be saved.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                string? strMeterNumber = null;
    
                FileStream? fsWaterBills = null;
                XmlDocument xdWaterBills = new XmlDocument();
                string strWaterBills = @"C:\Stellar Water Point\WaterBills.xml";
    
                FileInfo? fiWaterBills = new FileInfo(strWaterBills);
    
                if (fiWaterBills.Exists)
                {
                    using (fsWaterBills = new FileStream(fiWaterBills.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterBills.Load(fsWaterBills);
                        XmlNodeList xnlWaterBills = xdWaterBills.DocumentElement!.SelectNodes("//bill-number[.='" + txtBillNumber.Text + "']")!;
    
                        foreach (XmlNode xnWaterBill in xnlWaterBills)
                        {
                            mtbAccountNumber.Text          =                xnWaterBill.NextSibling!.InnerText;
                            dtpMeterReadingStartDate.Value = DateTime.Parse(xnWaterBill.NextSibling!.NextSibling!.InnerText);
                            dtpMeterReadingEndDate.Value   = DateTime.Parse(xnWaterBill.NextSibling.NextSibling.NextSibling!.InnerText);
                            txtBillingDays.Text            =                xnWaterBill.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText;
                            txtCounterReadingStart.Text    =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.InnerText;
                            txtCounterReadingEnd.Text      =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText;
                            txtTotalGallons.Text           =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtTotalCCF.Text               =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtFirstTierConsumption.Text   =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtSecondTierConsumption.Text  =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtLastTierConsumption.Text    =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtWaterCharges.Text           =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtSewerCharges.Text           =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtEnvironmentCharges.Text     =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtTotalCharges.Text           =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtLocalTaxes.Text             =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtStateTaxes.Text             =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtAmountDue.Text              =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            dtpPaymentDueDate.Value        = DateTime.Parse(xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText);
                            txtLateAmountDue.Text          =                xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            dtpLatePaymentDueDate.Value    = DateTime.Parse(xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText);
                        }
                    }
                }
    
                XmlDocument xdCustomers = new XmlDocument();
                string? strCustomers = @"C:\Stellar Water Point\Customers.xml";
    
                FileInfo? fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists)
                {
                    using (FileStream? fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdCustomers.Load(fsCustomers);
                        XmlNodeList xnlCustomers = xdCustomers.DocumentElement!.SelectNodes("//account-number[.='" + mtbAccountNumber.Text + "']")!;
    
                        foreach (XmlNode xnCustomer in xnlCustomers)
                        {
                            strMeterNumber       = xnCustomer.NextSibling!.InnerText;   // Meter #
                            txtCustomerName.Text = xnCustomer.NextSibling.NextSibling!.InnerText + " " +
                                                   xnCustomer.NextSibling.NextSibling.NextSibling!.InnerText;   // Last Name
                            txtAddress.Text      = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.InnerText;   // Address
                            txtCity.Text         = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText;   // City
                            txtCounty.Text       = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.InnerText;   // County
                            txtState.Text        = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;   // State
                            mtbZIPCode.Text      = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText; // ZIP-Code
                        }
                    }
                }
    
                XmlDocument xdWaterMeters = new XmlDocument();
                string? strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
    
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists)
                {
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterMeters.Load(fsWaterMeters);
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + strMeterNumber + "']")!;
    
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            txtMeterDetails.Text = xnWaterMeter.NextSibling!.InnerText + " " +
                                                   xnWaterMeter.NextSibling.NextSibling!.InnerText + " (Meter Size: " +
                                                   xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText + ")";
                        }
                    }
                }
            }
    
            private void btnFindCustomerAccount_Click(object sender, EventArgs e)
            {
                string? strMeterNumber = null;
                XmlDocument xdCustomers = new XmlDocument();
                string? strCustomers = @"C:\Stellar Water Point\Customers.xml";
    
                FileInfo? fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists)
                {
                    using (FileStream? fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdCustomers.Load(fsCustomers);
                        XmlNodeList xnlCustomers = xdCustomers.DocumentElement!.SelectNodes("//account-number[.='" + mtbAccountNumber.Text + "']")!;
    
                        foreach (XmlNode xnCustomer in xnlCustomers)
                        {
                            strMeterNumber       = xnCustomer.NextSibling!.InnerText;   // Meter #
                            txtCustomerName.Text = xnCustomer.NextSibling.NextSibling!.InnerText + " " +
                                                   xnCustomer.NextSibling.NextSibling.NextSibling!.InnerText;   // Customer Name
                            txtAddress.Text      = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.InnerText;   // Address
                            txtCity.Text         = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText;   // City
                            txtCounty.Text       = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.InnerText;   // County
                            txtState.Text        = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;   // State
                            mtbZIPCode.Text      = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText; // ZIP-Code
                        }
                    }
                }
    
                XmlDocument xdWaterMeters  = new XmlDocument();
                string?     strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
    
                FileInfo? fiWaterMeters    = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists)
                {
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterMeters.Load(fsWaterMeters);
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + strMeterNumber + "']")!;
    
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            txtMeterDetails.Text = xnWaterMeter.NextSibling!.InnerText + " " +
                                                   xnWaterMeter.NextSibling.NextSibling!.InnerText + " (Meter Size: " +
                                                   xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText + ")";
                        }
                    }
                }
            }
    
            private void dtpMeterReadingEndDate_ValueChanged(object sender, EventArgs e)
            {
                TimeSpan tsDays = dtpMeterReadingEndDate.Value - dtpMeterReadingStartDate.Value;
    
                txtBillingDays.Text = tsDays.Days.ToString();
            }
    
            private void btnEvaluateWaterBill_Click(object sender, EventArgs e)
            {
                double counterStart = 0, counterEnd = 0;
    
                try
                {
                    counterStart = double.Parse(txtCounterReadingStart.Text);
                }
                catch (FormatException feCRStart)
                {
                    MessageBox.Show("There was a problem with the value of the " +
                                    "Counter Reading Start. The error produced is: " + feCRStart.Message,
                                    "Stellar Water Point", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
    
                try
                {
                    counterEnd = double.Parse(txtCounterReadingEnd.Text);
                }
                catch (FormatException feCREnd)
                {
                    MessageBox.Show("There was a problem with the value of the " +
                                    "Counter Reading End. The error produced is: " + feCREnd.Message,
                                    "Stellar Water Point", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
    
                double consumption  = counterEnd - counterStart;
                double gallons      = consumption * 748.05;
                double firstTier    = gallons * (48.00 / 10000.00);
                double secondTier   = gallons * (32.00 / 10000.00);
                double lastTier     = gallons * (20.00 / 10000.00);
                double waterCharges = firstTier + secondTier + lastTier;
                double sewerCharges = waterCharges * 28.65 / 100;
                double envCharges   = waterCharges * 0.22184;
                double totalCharges = waterCharges + sewerCharges + envCharges;
                double localTaxes   = totalCharges * 0.06148;
                double stateTaxes   = totalCharges * 0.01374;
                double amtDue       = totalCharges + localTaxes + stateTaxes;
    
                TimeSpan tsPaymentDueDate = new TimeSpan(15, 0, 0, 0);
    
                txtTotalCCF.Text              = consumption.ToString();
                txtTotalGallons.Text          = gallons.ToString("F");
                txtFirstTierConsumption.Text  = firstTier.ToString("F");
                txtSecondTierConsumption.Text = secondTier.ToString("F");
                txtLastTierConsumption.Text   = lastTier.ToString("F");
                txtWaterCharges.Text          = waterCharges.ToString("F");
                txtSewerCharges.Text          = sewerCharges.ToString("F");
                txtEnvironmentCharges.Text    = envCharges.ToString("F");
                txtTotalCharges.Text          = totalCharges.ToString("F");
                txtLocalTaxes.Text            = localTaxes.ToString("F");
                txtStateTaxes.Text            = stateTaxes.ToString("F");
                dtpPaymentDueDate.Value       = dtpMeterReadingEndDate.Value + tsPaymentDueDate;
                txtAmountDue.Text             = amtDue.ToString("F");
                dtpLatePaymentDueDate.Value   = dtpMeterReadingEndDate.Value + new TimeSpan(30, 0, 0, 0);
                txtLateAmountDue.Text         = (amtDue + 8.95).ToString("F");
            }
    
            private void btnUpdateWaterBill_Click(object sender, EventArgs e)
            {
                FileStream? fsWaterBills  = null;
                XmlDocument xdWaterBills  = new XmlDocument();
                string      strWaterBills = @"C:\Stellar Water Point\WaterBills.xml";
    
                FileInfo?   fiWaterBills  = new FileInfo(strWaterBills);
    
                if (fiWaterBills.Exists)
                {
                    using (fsWaterBills   = new FileStream(fiWaterBills.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterBills.Load(fsWaterBills);
                        XmlNodeList xnlWaterBills = xdWaterBills.DocumentElement!.SelectNodes("//bill-number[.='" + txtBillNumber.Text + "']")!;
                        
                        foreach (XmlNode xnWaterBill in xnlWaterBills)
                        {
                            xnWaterBill.ParentNode!.InnerXml = "<bill-number>"              + txtBillNumber.Text            + "</bill-number>"             +
                                                               "<account-number>"           + mtbAccountNumber.Text         + "</account-number>"          +
                                                               "<meter-reading-start-date>" + dtpMeterReadingStartDate.Value.ToShortDateString()           + "</meter-reading-start-date>" +
                                                               "<meter-reading-end-date>"   + dtpMeterReadingEndDate.Value.ToShortDateString()             + "</meter-reading-end-date>"   +
                                                               "<billing-days>"             + txtBillingDays.Text           + "</billing-days>"            +
                                                               "<counter-reading-start>"    + txtCounterReadingStart.Text   + "</counter-reading-start>"   +
                                                               "<counter-reading-end>"      + txtCounterReadingEnd.Text     + "</counter-reading-end>"     +
                                                               "<total-gallons>"            + txtTotalGallons.Text          + "</total-gallons>"           +
                                                               "<total-ccf>"                + txtTotalCCF.Text              + "</total-ccf>"               +
                                                               "<first-tier-consumption>"   + txtFirstTierConsumption.Text  + "</first-tier-consumption>"  +
                                                               "<second-tier-consumption>"  + txtSecondTierConsumption.Text + "</second-tier-consumption>" +
                                                               "<last-tier-consumption>"    + txtLastTierConsumption.Text   + "</last-tier-consumption>"   +
                                                               "<water-charges>"            + txtWaterCharges.Text          + "</water-charges>"           +
                                                               "<sewer-charges>"            + txtSewerCharges.Text          + "</sewer-charges>"           +
                                                               "<environment-charges>"      + txtEnvironmentCharges.Text    + "</environment-charges>"     +
                                                               "<total-charges>"            + txtTotalCharges.Text          + "</total-charges>"           +
                                                               "<local-taxes>"              + txtLocalTaxes.Text            + "</local-taxes>"             +
                                                               "<state-taxes>"              + txtStateTaxes.Text            + "</state-taxes>"             +
                                                               "<amount-due>"               + txtAmountDue.Text             + "</amount-due>"              +
                                                               "<payment-due-date>"         + dtpPaymentDueDate.Value.ToShortDateString()                  + "</payment-due-date>" +
                                                               "<late-amount-due>"          + txtLateAmountDue.Text         + "</late-amount-due>"         +
                                                               "<late-payment-due-date>"    + dtpLatePaymentDueDate.Value.ToShortDateString()              + "</late-payment-due-date>";
                        }
                    }
    
                    using (fsWaterBills = new FileStream(fiWaterBills.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
                    {
                        xdWaterBills.Save(fsWaterBills);
                    }
                }
    
                Close();
            }
        }
    }
  37. To create a new form, in the Solution Explorer, right-click Water Bills -> New -> Form (Windows Forms)...
  38. Type Delete as the name of the form
  39. Click Add
  40. Make that form the same size as the Water Bill Editor form
  41. Select everything on the Water Bill Editor form. Copy that selection and paste it in the new Delete form
  42. Delete the Find Customer Account button
  43. Complete the design of the form as follows:

    Stellar Water Point - Water Bill Deletion

    Control (Name) Text
    Button Button btnDeleteWaterBill &Update Water Bill
  44. On the form, double-click the Find Water Bill button
  45. Return tp the form and double-click the Delete Water Bill button
  46. Return tp the form and double-click the Close button
  47. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint1.WaterBills
    {
        public partial class Delete : Form
        {
            public Delete()
            {
                InitializeComponent();
            }
    
            private void btnFindWaterBill_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(txtBillNumber.Text))
                {
                    MessageBox.Show("You must type a bill number." +
                                    "Otherwise, the account cannot be saved.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                string? strMeterNumber = null;
    
                FileStream? fsWaterBills  = null;
                XmlDocument xdWaterBills  = new XmlDocument();
                string      strWaterBills = @"C:\Stellar Water Point\WaterBills.xml";
    
                FileInfo?   fiWaterBills  = new FileInfo(strWaterBills);
    
                if (fiWaterBills.Exists)
                {
                    using (fsWaterBills = new FileStream(fiWaterBills.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterBills.Load(fsWaterBills);
                        XmlNodeList xnlWaterBills = xdWaterBills.DocumentElement!.SelectNodes("//bill-number[.='" + txtBillNumber.Text + "']")!;
    
                        foreach (XmlNode xnWaterBill in xnlWaterBills)
                        {
                            mtbAccountNumber.Text          = xnWaterBill.NextSibling!.InnerText;
                            dtpMeterReadingStartDate.Value = DateTime.Parse(xnWaterBill.NextSibling!.NextSibling!.InnerText);
                            dtpMeterReadingEndDate.Value   = DateTime.Parse(xnWaterBill.NextSibling.NextSibling.NextSibling!.InnerText);
                            txtBillingDays.Text            = xnWaterBill.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText;
                            txtCounterReadingStart.Text    = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.InnerText;
                            txtCounterReadingEnd.Text      = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText;
                            txtTotalGallons.Text           = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtTotalCCF.Text               = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtFirstTierConsumption.Text   = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtSecondTierConsumption.Text  = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtLastTierConsumption.Text    = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtWaterCharges.Text           = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtSewerCharges.Text           = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtEnvironmentCharges.Text     = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtTotalCharges.Text           = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtLocalTaxes.Text             = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtStateTaxes.Text             = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            txtAmountDue.Text              = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            dtpPaymentDueDate.Value        = DateTime.Parse(xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText);
                            txtLateAmountDue.Text          = xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;
                            dtpLatePaymentDueDate.Value    = DateTime.Parse(xnWaterBill.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText);
                        }
                    }
                }
    
                XmlDocument xdCustomers  = new XmlDocument();
                string?     strCustomers = @"C:\Stellar Water Point\Customers.xml";
    
                FileInfo?   fiCustomers  = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists)
                {
                    using (FileStream? fsCustomers = new FileStream(fiCustomers.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdCustomers.Load(fsCustomers);
                        XmlNodeList xnlCustomers = xdCustomers.DocumentElement!.SelectNodes("//account-number[.='" + mtbAccountNumber.Text + "']")!;
    
                        foreach (XmlNode xnCustomer in xnlCustomers)
                        {
                            strMeterNumber       = xnCustomer.NextSibling!.InnerText;   // Meter #
                            txtCustomerName.Text = xnCustomer.NextSibling.NextSibling!.InnerText + " " +
                                                   xnCustomer.NextSibling.NextSibling.NextSibling!.InnerText;   // Custome Name
                            txtAddress.Text      = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.InnerText;   // Address
                            txtCity.Text         = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.InnerText;   // City
                            txtCounty.Text       = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.InnerText;   // County
                            txtState.Text        = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText;   // State
                            mtbZIPCode.Text      = xnCustomer.NextSibling.NextSibling.NextSibling.NextSibling!.NextSibling!.NextSibling!.NextSibling!.NextSibling!.InnerText; // ZIP-Code
                        }
                    }
                }
    
                XmlDocument xdWaterMeters = new XmlDocument();
                string? strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
    
                FileInfo? fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists)
                {
                    using (FileStream? fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xdWaterMeters.Load(fsWaterMeters);
                        XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.SelectNodes("//meter-number[.='" + strMeterNumber + "']")!;
    
                        foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                        {
                            txtMeterDetails.Text = xnWaterMeter.NextSibling!.InnerText + " " +
                                                   xnWaterMeter.NextSibling.NextSibling!.InnerText + " (Meter Size: " +
                                                   xnWaterMeter.NextSibling.NextSibling.NextSibling!.InnerText + ")";
                        }
                    }
                }
            }
    
            private void btnDeleteWaterBill_Click(object sender, EventArgs e)
            {
                XmlDocument xdWaterMeters = new XmlDocument();
                string? strWaterMeters = @"C:\Stellar Water Point\WaterBills.xml";
    
                if (string.IsNullOrEmpty(mtbAccountNumber.Text))
                {
                    MessageBox.Show("You must type a bill number for the water bill you want to delete.",
                                    "Stellar Water Point", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
    
                if (!File.Exists(strWaterMeters))
                {
                    MessageBox.Show("There is no file for the water bills in the system.",
                                    "Stellar Water Point",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
    
                xdWaterMeters.Load(strWaterMeters);
    
                XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement!.GetElementsByTagName("bill-number");
    
                foreach (XmlNode xnWaterMeter in xnlWaterMeters)
                {
                    if (xnWaterMeter.InnerText == txtBillNumber.Text)
                    {
                        if (MessageBox.Show("Are you sure you want to delete this water bill from the system?",
                                            "Stellar Water Point",
                                            MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                        {
                            xdWaterMeters.DocumentElement.RemoveChild(xnWaterMeter.ParentNode!);
                            break;
                        }
                    }
                }
    
                xdWaterMeters.Save(strWaterMeters);
    
                Close();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }

Testing the Application

After creating an application, you can test it. Of course, you must first execute it.

Practical LearningPractical Learning: Testing the Application

  1. To execute, on the main menu, click Debug -> Start Without Debugging:

  2. On the form, click Water Meters...
  3. Close the Water Meters form
  4. On the Stellar Water Point form, click Water Bill Processing

    Stellar Water Point - Water Bill Processing

  5. Fill the form with the following values:
    Water Bill #:             847384
    Account #: 	              3028-502-9418
  6. Click Find Customer Account

    Stellar Water Point - Water Bill Processing

  7. Select and type the other values as follows Meter Reading Start Date: 10/03/2024 Meter Reading End Date: 01/06/2025 Counter Reading Start: 16 Counter Reading End: 28
  8. Click Evaluate Water Bill

    Stellar Water Point - Water Bill Processing

  9. Click Save Water Bill
  10. Follow the same steps to create records as follows:
    Water Bill # Account # Meter Reading Start Date Meter Reading End Date Counter Reading Start Counter Reading End
    330820 7028-405-9381 10/03/2024 01/03/2025 9749 9906
    468550 7518-302-6895 10/05/2024 01/09/2025 96 114
    148274 9249-379-6848 10/05/2024 01/10/2025 260504 260555
    326384 2068-258-9486 10/08/2024 01/10/2025 104837 104851
  11. Close the forms
  12. Close Microsoft Visual Studio

Application


Home Copyright © 2010-2025, FunctionX Monday 12 August 2024: Home