Introduction

The eXtensible Markup Language (XML) is one of the techniques you can use to create a text-based database application. The .NET Framework is wonderful library filled with all types of classes to explore XML, including creating, viewing, editing, deleting and managing nodes.

Practical LearningPractical Learning: Introducing the Application

  1. Start Microsoft Visual Studio
  2. Create a Windows Forms App named StellarWaterPoint2
  3. To create a form, on the main menu, click Project -> Add Form (Windows Forms)...

Water Meters

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.

Practical LearningPractical Learning: Starting Water Meters Issues

  1. To create a folder, in the Solution Explorer, right-click the StellarWaterPoint2 project -> Add -> New Folder
  2. Type WaterMeters as the name of the folder
  3. To create a form, in the Solution Explorer, right-click the new WaterMeters folder -> Add -> Form (Windows Forms)...
  4. Type Create
  5. Press Enter
  6. 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
    Label Label   M&ake:  
    TextBox Text Box txtMake  
    Label Label   M&odel:  
    TextBox Text Box txtModel   Modifiers: Public
    Label Label   Me&ter Size:  
    TextBox Text Box txtMeterSize  
    Button Button btnOK &OK DialogResult: OK
    Button Button btnCancel &Cancel DialogResult: Cancel
  7. 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
  8. To create a form, in the Solution Explorer, right-click WaterMeters -> Add -> Form (Windows Forms)...
  9. Type Details
  10. Press Enter
  11. Resize the Editor form to have the same size as the Create form
  12. Copy everything from the Create form and paste it in the Editor form
  13. Delete the bottom two buttons and add a new button
  14. 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
  15. On the form, double-click the Find button
  16. Return to the form and double-click the Close button
  17. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint.WaterMeters
    {
        public partial class Details : Form
        {
            public Details()
            {
                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;
                        }
                    }
                }
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  18. To create a form, in the Solution Explorer, right-click WaterMeters -> Add -> Form (Windows Forms)...
  19. Type Editor
  20. Press Enter
  21. Resize the Editor form to have the same size as the Details form
  22. Copy everything from the Details form and paste it in the Editor form
  23. Change the design of the form as follows:

    Stellar Water Point - New Water Meter

    Control (Name) Text
    Button Button btnUpdateWateMeter &Update Water Meter
  24. On the form, double-click the Find button
  25. Return to the form and double-click the Close button
  26. Return to the form and double-click the Update Water Meter button
  27. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint.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;
                        }
                    }
                }
            }
    
            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();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  28. To create a form, in the Solution Explorer, right-click WaterMeters -> Add -> Form(Windows Forms)...
  29. Type Delete
  30. Press Enter
  31. Resize the Editor form to have the same size as the Editor form
  32. Copy everything from the Editor form and paste it in the Delete form
  33. Change the bottom button as follows:

    Stellar Water Point - New Water Meter

    Control (Name) Text
    Button Button btnDeleteWateMeter &Delete Water Meter
  34. On the form, double-click the Find button
  35. Return to the form and double-click the Close button
  36. Return to the form and double-click the Delete Water Meter button
  37. Change the document as tollows:
    using System.Xml;
    
    namespace StellarWaterPoint.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;
                        }
                    }
                }
            }
    
            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();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  38. To create a form, in the Solution Explorer, right-click WaterMeters -> Add -> Form (Windows Forms)...
  39. Type Central
  40. Press Enter
  41. In the Toolbox, click the ListView button and click the form
  42. On the form, right-click the list view and click Edit Columns...
  43. Create the columns as follows:
    (Name) Text Width
    colWaterMeterId Id 40
    colMeterNumber Meter # 150
    colMake Make 300
    colModel Model 150
    colMeterSize Meter Size 175
  44. Click OK
  45. 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
  46. Doubte-click an unoccupied area of the form to generate its Load event
  47. Return to the form and double-click the New Water Meter button
  48. Return to the form and double-click the View Water Meter button
  49. Return to the form and double-click the Edit Water Meter button
  50. Return to the form and double-click the Delete Water Meter button
  51. Return to the form and double-click the Close button
  52. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint.WaterMeters
    {
        public partial class Central : Form
        {
            public Central()
            {
                InitializeComponent();
            }
    
            private void ShowWaterMeters()
            {
                lvwWaterMeters.Items.Clear();
    
                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!.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);
    
                            i++;
                        }
                    }
                }
            }
    
            private void Central_Load(object sender, EventArgs e)
            {
                ShowWaterMeters();
            }
    
            private void btnNewWaterMeter_Click(object sender, EventArgs e)
            {
                Create      wm            = new();
                FileInfo?   fiWaterMeters = null;
                FileStream? fsWaterMeters = null;
                XmlDocument xdWaterMeters = new XmlDocument();
                string?     strWaterMeters = @"C:\Stellar Water Point\WaterMeters.xml";
    
                if (wm.ShowDialog() == DialogResult.OK)
                {
                    fiWaterMeters = new FileInfo(strWaterMeters);
    
                    if (fiWaterMeters.Exists)
                    {
                        using (fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                        {
                            xdWaterMeters.Load(fsWaterMeters);
                        }
                    }
                    else
                    {
                        using (fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.Create, FileAccess.Write, FileShare.Write))
                        {
                            xdWaterMeters.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                                  "<water-meters></water-meters>");
                            xdWaterMeters.Save(fsWaterMeters);
                        }
                    }
    
                    using (fsWaterMeters = new FileStream(fiWaterMeters.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
                    {
                        XmlElement xeWaterMeter = xdWaterMeters.CreateElement("water-meter");
    
                        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>";
                        xdWaterMeters.DocumentElement!.AppendChild(xeWaterMeter);
                        xdWaterMeters.Save(fsWaterMeters);
                    }
                }
    
                ShowWaterMeters();
            }
    
            private void btnViewWaterMeter_Click(object sender, EventArgs e)
            {
                Details editor = new();
    
                editor.ShowDialog();
            }
    
            private void btnEditWaterMeter_Click(object sender, EventArgs e)
            {
                Editor editor = new();
    
                editor.ShowDialog();
    
                ShowWaterMeters();
            }
    
            private void btnDeleteWaterMeter_Click(object sender, EventArgs e)
            {
                Delete delete = new();
    
                delete.ShowDialog();
    
                ShowWaterMeters();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }

Customers

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

Practical LearningPractical Learning: Preparing Customers Accounts

  1. 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, on the main menu, click Customers -> Add -> Form (Windows Forms)...
  4. Type Create as the name of the file
  5. Click Add
  6. 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  
  7. 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
  8. On the form, double-click the Find Water Meter button
  9. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint.Customers
    {
        public partial class Create : Form
        {
            public Create()
            {
                InitializeComponent();
            }
    
            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 + ")";
                        }
                    }
                }
            }
        }
    }
  10. To create a form, in the Solution Explorer, right-click Customers -> Add -> Form (Windows Forms)...
  11. Type Details
  12. Press Enter
  13. Resize the Editor form to have the same size as the Create form
  14. Copy everything from the Create form and paste it in the Editor form
  15. Delete the bottom two buttons and add a new button
  16. 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
  17. 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
  18. On the form, double-click the Find Customer Account
  19. Return to the form and double-click the Close button
  20. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint.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 + ")";
                        }
                    }
                }
            }
        }
    }
  21. To create a form, in the Solution Explorer, right-click Customers -> Add -> Form (Windows Forms)...
  22. Type Editor
  23. Press Enter
  24. Resize the Editor form to have the same size as the Create form
  25. Copy everything from the Create form and paste it in the Editor form
  26. 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
  27. 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
  28. On the form, double-click the Find Customer Account
  29. Return to the form and double-click the Find Water Meter button
  30. Return to the form and double-click the Update Water Meter button
  31. Change the document as tollows:
    using System.Xml;
    
    namespace StellarWaterPoint.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();
            }
        }
    }
  32. To create a form, in the Solution Explorer, right-click Customers -> Add -> Form (Windows Forms)...
  33. Type Delete
  34. Press Enter
  35. Resize the Editor form to have the same size as the Editor form
  36. Copy everything from the Editor form and paste it in the Delete form
  37. 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
  38. 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
  39. On the form, double-click the Find Customer Account
  40. Return to the form and double-click the Delete Water Meter button
  41. Change the document as tollows:
    using System.Xml;
    
    namespace StellarWaterPoint.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();
            }
        }
    }
  42. To create a form, in the Solution Explorer, right-click Models -> Add -> Form (Windows Forms)...
  43. Type Central
  44. Press Enter
  45. In the Toolbox, click the ListView button and click the form
  46. On the form, right-click the list view and click Edit Columns...
  47. 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
  48. Click OK
  49. 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 btnViewCustomerAccount &View 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
  50. Doubte-click an unoccupied area of the form to generate its Load event
  51. Return to the form and double-click the New Customer Account button
  52. Return to the form and double-click the View Customer Account button
  53. Return to the form and double-click the Edit Customer Account button
  54. Return to the form and double-click the Delete Customer Account button
  55. Return to the form and double-click the Close button
  56. Change the document as follows:
    using System.Xml;
    
    namespace StellarWaterPoint.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();
            }
    
            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 StellarWaterPoint.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 StellarWaterPoint.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 StellarWaterPoint.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 StellarWaterPoint.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();
            }
        }
    }

Finalizing the Application

In previous sections, we created some forms for water meters and customers. Their sections included a form that shos a list of their records. We also created some forms for the water bills. Now we can provide a central form for the application. From that form, a user can navigate to the other sections of the application.

Practical LearningPractical Learning: Laying Out the Documents

  1. In the Solution Explorer, right-click Form1.cs and click Rename
  2. Change the name to WaterDistribution.cs
  3. Press Enter three times to apply the name and display the form
  4. In the Properties window, change the following characteristics:
    Text: Stellar Water Point
    StartPosition: CenterScreen
    MaximizeBox: False
  5. 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
  6. Double-click an unoccupied area of the form to generate its Load event
  7. Return to the Stellar Water Point form and double-click the &Water Bill Processing button
  8. Return to the Stellar Water Point form and double-click the &View Water Bill button
  9. Return to the Stellar Water Point form and double-click the &Edit Water Bill button
  10. Return to the Stellar Water Point form and double-click the &Delete Water Bill button
  11. Return to the Stellar Water Point form and double-click the C&ustomers button
  12. Return to the Stellar Water Point form and double-click the &Water Meters button
  13. Return to the Stellar Water Point form and double-click the Close button
  14. Change the document as follows:
    namespace StellarWaterPoint
    {
        public partial class Switchboard : 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 btnWaterMeters_Click(object sender, EventArgs e)
            {
                WaterMeters.Central central = new WaterMeters.Central();
    
                central.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();
            }
        }
    }

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. Click New Water Meter:

    Stellar Water Point - New Water Meter

  4. 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 Kensa Sons M-686-G 1 1/2 Inches
    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

  5. Close the Water Meters form
  6. On the Stellar Water Point form, click Customers
  7. On the Customers form, click New Customer Account:

    Stellar Water Point - New Customer Account

  8. Using the values in the following table, enter an account number, then enter a meter number and click Find Water Meter. Complethe the record with the other values. Then click Save 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 374-06-284 Mandiakandara Marmoudi 539 Avalon Court Greenwood Sussex DE 19950-2288
    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

  9. Close the Customers form
  10. On the Stellar Water Point form, click Water Bill Processing

    Stellar Water Point - Water Bill Processing

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

    Stellar Water Point - Water Bill Processing

  13. 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
  14. Click Evaluate Water Bill

    Stellar Water Point - Water Bill Processing

  15. Click Save Water Bill
  16. 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
  17. Close the forms
  18. Close Microsoft Visual Studio

Application


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