Introduction

A text-based database is an application used to create, keep, and manage records. You have many options. One way to store the records of a database is as text. Even then, you still have many option. One solution is to create and manage records using a collection class.

Besides using a collection class to create and manage records, you also have to decide in what format you would keep the record. For this example, we will save the records in XML.

Practical LearningPractical Learning: Introducing MDI Applications

  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)...
  4. In the middle list, click About Box (Windows Forms)
  5. Change the file Name to AboutSWP
  6. Click Add
  7. In the Solution Explorer, right-click StellarWaterPoint1 -> Add -> New Folder
  8. Type Models as the name of the folder

Water Meters

A water meter is a mechanical device used to measure the amount of water that is consumed. To deal with it, we will create a class and forms.

Practical LearningPractical Learning: Starting Water Meters Issues

  1. To create a class, in the Solution Explorer, right-click Models -> Add -> Class...
  2. On the main menu, click Project -> Add Class...
  3. Replace the name with WaterMeter
  4. Click Add
  5. Change the code as follows:
    namespace StellarWaterPoint2.Models
    {
        internal readonly record struct WaterMeter
        {
            public readonly string? MeterNumber { get; init; }
            public readonly string? Make        { get; init; }
            public readonly string? Model       { get; init; }
            public readonly string? MeterSize   { get; init; }
        }
    }
  6. In the Solution Explorer, right-click StellarWaterPoint1 -> Add -> New Folder
  7. Type WaterMeters as the name of the folder
  8. To create a form, in the Solution Explorer, right-click WaterMeters -> Add -> Form(Windows Forms)...
  9. Type Create
  10. Press Enter
  11. 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 btnSaveWateMeter S&ave Water Meter  
  12. To create a form, in the Solution Explorer, right-click WaterMeters -> Add -> Form(Windows Forms)...
  13. Type Editor
  14. Press Enter
  15. Resize the Editor form to have the same size as the Create form
  16. Copy everything from the Create form and paste it in the Editor form
  17. Change the design as follows:

    Stellar Water Point - New Water Meter

    Control (Name) Text
    Button Button btnFindWateMeter &Find Water Meter
    Button Button btnUpdateWateMeter &Update Water Meter
  18. To create a form, in the Solution Explorer, right-click WaterMeters -> Add -> Form(Windows Forms)...
  19. Type Delete
  20. Press Enter
  21. Resize the Editor form to have the same size as the Editor form
  22. Copy everything from the Editor form and paste it in the Delete form
  23. Change the bottom button as follows:

    Stellar Water Point - New Water Meter

    Control (Name) Text
    Button Button btnDeleteWateMeter &Delete Water Meter
  24. To create a form, in the Solution Explorer, right-click WaterMeters -> Add -> Form(Windows Forms)...
  25. Type Manage
  26. Press Enter
  27. In the Toolbox, click the ListView button and click the form
  28. On the form, right-click the list view and click Edit Columns...
  29. Create the columns as follows:
    (Name) Text Width
    colWaterMeterId Id 40
    colMeterNumber Meter # 150
    colMake Make 225
    colModel Model 100
    colMeterSize Meter Size 150
  30. Click OK
  31. Complete the design of the form as follows:

    Stellar Water Point - Customers

    Control (Name) Other Properties
    ListView List View lvwWaterMeters FullRowSelect: True
    GridLines: True
    View: Details
    Anchor: Top, Bottom, Left, Right

Customers

Customers are families or businesses that consume a product or service, which is the case for water consumption. To deal with these issues, we will create a class and forms.

Practical LearningPractical Learning: Preparing Customers Accounts

  1. To create a class, in the Solution Explorer, right-click Models -> Add -> Class...
  2. On the main menu, click Project -> Add Class...
  3. Replace the name with Customer
  4. Click Add
  5. Change the code as follows:
    namespace StellarWaterPoint1.Models
    {
        internal readonly record struct Customer
        {
            public readonly string? AccountNumber { get; init; }
            public readonly string? MeterNumber   { get; init; }
            public readonly string? FirstName     { get; init; }
            public readonly string? LastName      { get; init; }
            public readonly string? Address       { get; init; }
            public readonly string? City          { get; init; }
            public readonly string? County        { get; init; }
            public readonly string? State         { get; init; }
            public readonly string? ZIPCode       { get; init; }
        }
    }
  6. In the Solution Explorer, right-click StellarWaterPoint1 -> Add -> New Folder
  7. Type Customers as the name of the folder
  8. To create a form, on the main menu, click Customers -> Add Form (Windows Forms)...
  9. Type Create as the name of the file
  10. Click Add
  11. Design the form as follows:

    Stellar Water Point - New Customer Account

    Control (Name) Text Mask
    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  
  12. To create a form, in the Solution Explorer, right-click Customers -> Add -> Form (Windows Forms)...
  13. Type Editor
  14. Press Enter
  15. Resize the Editor form to have the same size as the Create form
  16. Copy everything from the Create form and paste it in the Editor form
  17. Change the design as follows:

    Stellar Water Point - Customer Editor

    Control (Name) Text
    Button Button btnFindCustomer &Find Customer
    Button Button btnUpdateCustomerAccount &Update Customer Account
  18. To create a form, in the Solution Explorer, right-click Customers -> Add -> Form (Windows Forms)...
  19. Type Delete
  20. Press Enter
  21. Resize the Editor form to have the same size as the Editor form
  22. Copy everything from the Editor form and paste it in the Delete form
  23. 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
  24. To create a form, in the Solution Explorer, right-click Models -> Add -> Form (Windows Forms)...
  25. Type ViewAll
  26. Press Enter
  27. In the Toolbox, click the ListView button and click the form
  28. On the form, right-click the list view and click Edit Columns...
  29. Create the columns as follows:
    (Name) Text TextAlign Width
    colCustomerId Id   40
    colAccountNumber Account # Center 175
    colMeterNumber Meter # Center 150
    colFirstName First Name   125
    colLastName Last Name   125
    colAddress Address   250
    colCity City   125
    colCounty County   150
    colState State Center  
    colZIPCode ZIP-Code Center 125
  30. Click OK
  31. 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

Water Bills

Bills are the natural results and benefits of services and products that people and businesses consume. To prepare them, we will create a class and forms.

Practical LearningPractical Learning: Preparing Bills

  1. To create another class, in the Solution Explorer, right-click Models -> Add -> Class...
  2. On the main menu, click Project -> Add Class...
  3. Replace the name with WaterBill
  4. Click Add
  5. Change the code as follows:
    namespace StellarWaterPoint1.Models
    {
        internal readonly record struct WaterBill
        {
            public readonly int     BillNumber            { get; init; }
            public readonly string? AccountNumber         { get; init; }
            public readonly string? MeterReadingStartDate { get; init; }
            public readonly string? MeterReadingEndDate   { get; init; }
            public readonly int     BillingDays           { get; init; }
            public readonly double  CounterReadingStart   { get; init; }
            public readonly double  CounterReadingEnd     { get; init; }
            public readonly double  TotalGallons          { get; init; }
            public readonly double  TotalCCF              { get; init; }
            public readonly double  FirstTierConsumption  { get; init; }
            public readonly double  SecondTierConsumption { get; init; }
            public readonly double  LastTierConsumption   { get; init; }
            public readonly double  WaterCharges          { get; init; }
            public readonly double  SewerCharges          { get; init; }
            public readonly double  EnvironmentCharges    { get; init; }
            public readonly double  TotalCharges          { get; init; }
            public readonly double  LocalTaxes            { get; init; }
            public readonly double  StateTaxes            { get; init; }
            public readonly double  AmountDue             { get; init; }
            public readonly string? PaymentDueDate        { get; init; }
            public readonly double  LateAmountDue         { get; init; }
            public readonly string? LatePaymentDueDate    { get; init; }
        }
    }
  6. In the Solution Explorer, right-click StellarWaterPoint1 -> Add -> New Folder
  7. Type WaterBills as the name of the folder
  8. To create a form, in the Solution Explorer, right-click WaterBills -> Add -> Form (Windows Forms)...
  9. Type Create as the name of the file
  10. Press Enter
  11. 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  
  12. On the form, double-click the Find Customer Account button
  13. Return to the Water Bills - Create form and double-click the Evaluate Water Bill button
  14. Return to the Water Bills - Create form and double-click the Save Water Bill button
  15. Return to the form and double-click the Close button
  16. Change the document as follows:
    using StellarWaterPoint2.Models;
    using System.Xml.Serialization;
    
    namespace StellarWaterPoint2.WaterBills
    {
        public partial class Create : Form
        {
            public Create()
            {
                InitializeComponent();
            }
    
            private void btnFindCustomerAccount_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(mtbAccountNumber.Text))
                {
                    MessageBox.Show("You must type an account number for a customer.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                Customer? client          = null;
                List<Customer> clients    = new List<Customer>();
                string strCustomers       = @"E:\Stellar Water Point\Customers.xml";
                XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>));
    
                FileInfo fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists == true)
                {
                    using (TextReader trCustomers = new StreamReader(fiCustomers.FullName))
                    {
                        clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!;
    
                        client  = clients.Find(cust => cust.AccountNumber == mtbAccountNumber.Text)!;
                    }
                }
    
                if (client is null)
                {
                    MessageBox.Show("There is no customer with that account number in our system.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                string strMeterNumber = client.MeterNumber!;
                txtCustomerName.Text  = client.FirstName + " " + client.LastName;
                txtAddress.Text       = client.Address;
                txtCity.Text          = client.City;
                txtCounty.Text        = client.County;
                txtState.Text         = client.State;
                mtbZIPCode.Text       = client.ZIPCode;
    
                WaterMeter? meter            = null;
                List<WaterMeter> waterMeters = new List<WaterMeter>();
                string strWaterMeters        = @"E:\Stellar Water Point\WaterMeters.xml";
                XmlSerializer xsWaterMeters  = new XmlSerializer(typeof(List<WaterMeter>));
    
                FileInfo fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists == true)
                {
                    using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName))
                    {
                        waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!;
    
                        meter       = waterMeters.Find(m => m.MeterNumber == strMeterNumber)!;
                    }
                }
    
                txtMeterDetails.Text = meter?.Make + " " +
                                       meter?.Model + " (Meter #: " +
                                       meter?.MeterSize + ")";
            }
    
            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;
                }
    
                List<WaterBill> bills      = new List<WaterBill>();
                string strWaterBills       = @"E:\Stellar Water Point\WaterBills.xml";
                XmlSerializer xsWaterBills = new XmlSerializer(typeof(List<WaterBill>));
    
                FileInfo fiWaterBills      = new FileInfo(strWaterBills);
    
                if (fiWaterBills.Exists == true)
                {
                    using (TextReader trWaterBills = new StreamReader(fiWaterBills.FullName))
                    {
                        bills = (List<WaterBill>)xsWaterBills.Deserialize(trWaterBills)!;
                    }
                }
    
                WaterBill bill = new WaterBill()
                {
                    BillNumber            =    int.Parse(txtBillNumber.Text),
                    AccountNumber         =              mtbAccountNumber.Text,
                    MeterReadingStartDate =              dtpLatePaymentDueDate.Value.ToShortDateString(),
                    MeterReadingEndDate   =              dtpMeterReadingEndDate.Value.ToShortDateString(),
                    BillingDays           =    int.Parse(txtBillingDays.Text),
                    CounterReadingStart   = double.Parse(txtCounterReadingStart.Text),
                    CounterReadingEnd     = double.Parse(txtCounterReadingEnd.Text),
                    TotalGallons          = double.Parse(txtTotalGallons.Text),
                    TotalCCF              = double.Parse(txtTotalCCF.Text),
                    FirstTierConsumption  = double.Parse(txtFirstTierConsumption.Text),
                    SecondTierConsumption = double.Parse(txtSecondTierConsumption.Text),
                    LastTierConsumption   = double.Parse(txtLastTierConsumption.Text),
                    WaterCharges          = double.Parse(txtWaterCharges.Text),
                    SewerCharges          = double.Parse(txtSewerCharges.Text),
                    EnvironmentCharges    = double.Parse(txtEnvironmentCharges.Text),
                    TotalCharges          = double.Parse(txtTotalCharges.Text),
                    LocalTaxes            = double.Parse(txtLocalTaxes.Text),
                    StateTaxes            = double.Parse(txtStateTaxes.Text),
                    AmountDue             = double.Parse(txtAmountDue.Text),
                    PaymentDueDate        =              dtpPaymentDueDate.Value.ToShortDateString(),
                    LateAmountDue         = double.Parse(txtLateAmountDue.Text),
                    LatePaymentDueDate    =              dtpLatePaymentDueDate.Value.ToShortDateString()
                };
    
                bills.Add(bill);
    
                using (TextWriter twWaterBills = new StreamWriter(fiWaterBills.FullName))
                {
                    xsWaterBills.Serialize(twWaterBills, bills);
                }
    
                Close();
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  17. To create a new form, on the main menu, click Project and click Form (Windows Forms)...
  18. Type Details as the name of the form
  19. Click Add
  20. Make that form the same size as the New Water Bill form
  21. Select everything on the New Water Bill form. Copy that selection and paste it in the new Water Bill - Details form
  22. On the Water Bill - Details form, delete the Find Customer Account, the Evaluate Water Bill, and the Save Water Bill buttons
  23. Add a button as follows:

    Stellar Water Point - Water Bill Viewer

    Control (Name) Text
    Button Button btnFindWaterBill Find Water &Bill
  24. On the form, double-click the Find Water Bill button
  25. Return tp the form and double-click the Close button
  26. Change the document as follows:
    using StellarWaterPoint20.Models;
    using System.Xml.Serialization;
    
    namespace StellarWaterPoint20.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.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                WaterBill? bill            = null;
                List<WaterBill> bills      = new List<WaterBill>();
                string strWaterBills       = @"E:\Stellar Water Point\WaterBills.xml";
                XmlSerializer xsWaterBills = new XmlSerializer(typeof(List<WaterBill>));
    
                FileInfo fiWaterBills      = new FileInfo(strWaterBills);
    
                if (fiWaterBills.Exists == true)
                {
                    using (TextReader trWaterBills = new StreamReader(fiWaterBills.FullName))
                    {
                        bills = (List<WaterBill>)xsWaterBills.Deserialize(trWaterBills)!;
    
                        bill  = bills.Find(pay => pay.BillNumber == int.Parse(txtBillNumber.Text))!;
                    }
                }
    
                if (bill is null)
                {
                    MessageBox.Show("There is no water bill with that number in our system.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                mtbAccountNumber.Text         = bill.AccountNumber;
                dtpLatePaymentDueDate.Value   = DateTime.Parse(bill.MeterReadingStartDate!);
                dtpMeterReadingEndDate.Value  = DateTime.Parse(bill.MeterReadingEndDate!);
                txtBillingDays.Text           = bill.BillingDays.ToString();
                txtCounterReadingStart.Text   = bill.CounterReadingStart.ToString();
                txtCounterReadingEnd.Text     = bill.CounterReadingEnd.ToString();
                txtTotalGallons.Text          = bill.TotalGallons.ToString();
                txtTotalCCF.Text              = bill.TotalCCF.ToString();
                txtFirstTierConsumption.Text  = bill.FirstTierConsumption.ToString();
                txtSecondTierConsumption.Text = bill.SecondTierConsumption.ToString();
                txtLastTierConsumption.Text   = bill.LastTierConsumption.ToString();
                txtWaterCharges.Text          = bill.WaterCharges.ToString();
                txtSewerCharges.Text          = bill.SewerCharges.ToString();
                txtEnvironmentCharges.Text    = bill.EnvironmentCharges.ToString();
                txtTotalCharges.Text          = bill.TotalCharges.ToString();
                txtLocalTaxes.Text            = bill.LocalTaxes.ToString();
                txtStateTaxes.Text            = bill.StateTaxes.ToString();
                txtAmountDue.Text             = bill.AmountDue.ToString();
                dtpPaymentDueDate.Value       = DateTime.Parse(bill.PaymentDueDate!);
                txtLateAmountDue.Text         = bill.LateAmountDue.ToString();
                dtpLatePaymentDueDate.Value   = DateTime.Parse(bill.LatePaymentDueDate!);
    
                Customer? client              = null;
                string? strMeterNumber        = string.Empty;
                List<Customer> clients        = new List<Customer>();
                string strCustomers           = @"E:\Stellar Water Point\Customers.xml";
                XmlSerializer xsCustomers     = new XmlSerializer(typeof(List<Customer>));
    
                FileInfo fiCustomers          = new FileInfo(strCustomers);
    
                using (TextReader trCustomers = new StreamReader(fiCustomers.FullName))
                {
                    clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!;
    
                    client  = clients.Find(cust => cust.AccountNumber == mtbAccountNumber.Text)!;
    
                    strMeterNumber           = client.MeterNumber!;
                    txtCustomerName.Text     = client.FirstName + " " + client.LastName;
                    txtAddress.Text          = client.Address;
                    txtCity.Text             = client.City;
                    txtCounty.Text           = client.County;
                    txtState.Text            = client.State;
                    mtbZIPCode.Text          = client.ZIPCode;
                }
    
                WaterMeter? meter            = null;
                List<WaterMeter> waterMeters = new List<WaterMeter>();
                string strWaterMeters        = @"E:\Stellar Water Point\WaterMeters.xml";
                XmlSerializer xsWaterMeters  = new XmlSerializer(typeof(List<WaterMeter>));
    
                FileInfo fiWaterMeters       = new FileInfo(strWaterMeters);
    
                using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName))
                {
                    waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!;
    
                    meter       = waterMeters.Find(m => m.MeterNumber == strMeterNumber)!;
    
                    txtMeterDetails.Text = meter?.Make + " " +
                                           meter?.Model + " (Meter #: " +
                                           meter?.MeterSize + ")";
                }
            }
    
            private void btnClose_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }

Finalizing the Application

An application must provide intuitive tools for the users. To make this happen, we will create a menu for 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:
    IsMdiContainer: True
    StartPosition: CenterScreen
    Text: Stellar Water Point

    Stellar Water Point - Multiple Document Interface

  1. In the Solution Explorer, double-click WaterDistribution.cs to display the main form of the application
  2. In the Toolbox, expand Menus & Toolbars
  3. In the Menus & Toolbars section of the Toolbox, click MenuStrip and click the form
  4. In the Properties window, click (Name) and type msMainMenu
  5. Still in the Properties window, click Items and click its button
  6. Using the Add button, create three items as follows:
    Text (Name)
    &File miFile
    Water &Bills miWaterBills
    &Customers miCustomers
    Water &Meters miWaterMeters
    &Window miWindow
    &Help miHelp
  7. In the Members list of the Items Collection Editor, click miFile
  8. In the right list, click DropDownItems and click its button
  9. Using the Add button, create two items as follows:
    Text (Name) Shortcuts
    E&xit miFileExit Alt + F4
  10. On the Items Collection Editor (miFile.DropDownItems) dialog box, click OK
  11. In the Members list of the Items Collection Editor, click miWaterBills
  12. In the right list, click DropDownItems and click its button
  13. Using the Add button, create two items as follows:
    Text (Name) Shortcuts
    &Prepare Water Bill... miWaterBillsCreate Ctrl+Shift+B
    &View Water Bill... miWaterBillsView Ctrl+Shift+V
  14. On the Items Collection Editor (miWaterBills.DropDownItems) dialog box, click OK
  15. In the Members list of the Items Collection Editor, click miCustomers
  16. In the right list, click DropDownItems and click its button
  17. Using the Add button, create two items as follows:
    Text (Name) Shortcuts
    &Create Customer Account... miCustomersCreate Ctrl+Shift+C
    &Edit Customer Account... miCustomersEditor Ctrl+Shift+E
    &Delete Customer Account... miCustomersDelete Ctrl+Shift+D
    tsCustomersSeparator
    &View All Accounts... miCustomerViewAll Ctrl+Shift+A
  18. On the Items Collection Editor (miCustomers.DropDownItems) dialog box, click OK
  19. In the Members list of the Items Collection Editor, click miWaterMeters
  20. In the right list, click DropDownItems and click its button
  21. Using the Add button, create two items as follows:
    Text (Name) Shortcuts
    &Setup Water Meter... miWaterMetersCreate Ctrl+Shift+W
    Edit &Water Meter... miWaterMetersEditor Ctrl+Shift+I
    De&lete Water Meter... miWaterMetersCreate Ctrl+Shift+R
    tsWaterMetersSeparator
    View All Wate&r Meters... miWaterMeterViewAll Ctrl+Shift+T
  22. On the Items Collection Editor (miWaterMeters.DropDownItems) dialog box, click OK
  23. In the Members list of the Items Collection Editor, click miWindow
  24. In the right list, click DropDownItems and click its button
  25. Using the Add button, create two items as follows:
    Text (Name)
    &Arrange miWindowArrange
    &Cascade miWindowCascade
    Tile &Horizontal miWindowTileHorizontal
    Tile &Vertical mnuWindowTileVertical
  26. On the Items Collection Editor (miWindow.DropDownItems) dialog box, click OK
  27. In the Members list of the Items Collection Editor, click miHelp
  28. In the right list, click DropDownItems and click its button
  29. Using the Add button, create an item as follows:
    Text (Name) Shortcuts
    &About Stellar Water Point... miHelpAbout Ctrl+F1
  30. On the Items Collection Editor (miHelp.DropDownItems) dialog box, click OK
  31. On the Items Collection Editor dialog box, click OK
  32. On the Stellar Water Point form, click the Water Bills menu item and double-click Prepare Water Bill...
  33. Return to the Stellar Water Point form
  34. On the Stellar Water Point form, below Prepare Water Bill..., double-click View Water Bill...
  35. Return to the Stellar Water Point form
  36. Click the Customers menu item and double-click Create Customer Account...
  37. Return to the Stellar Water Point form and, below Create Customer Account..., double-click Edit Customer Account...
  38. Return to the Stellar Water Point form and double-click Delete Customer Account...
  39. Return to the Stellar Water Point form and double-click View All Accounts...
  40. Return to the Stellar Water Point form
  41. Click the Water Meters menu item and double-click Setup Water Meter...
  42. Return to the Stellar Water Point form and, below Setup Water Meter..., double-click Edit Water Meter...
  43. Return to the Stellar Water Point form and double-click Delete Water Meter...
  44. Return to the Stellar Water Point form and double-click View All Water Meters...
  45. Return to the Stellar Water Point form
  46. Click the Window menu item and double-click Arrange
  47. Return to the Stellar Water Point form and, below Arrange, double-click Cascade
  48. Return to the Stellar Water Point form and, below Cascade, double-click Tile Horizontal
  49. Return to the Stellar Water Point form and, below Tile Horizontal, double-click Tile Vertical
  50. Return to the Stellar Water Point form
  51. Click the Help menu item and double-click About Stellar Water Point...
  52. Return to the Stellar Water Point form
  53. Click the File menu item and double-click Exit
  54. Change the document as follows:
    namespace StellarWaterPoint2
    {
        public partial class WaterDistribution : Form
        {
            public static bool MetersDisplaying;
            public static bool MeterEditorDisplaying;
            public static bool MeterDeleteDisplaying;
            public static bool MeterCreateDisplaying;
    
            public static bool ClientsDisplaying;
            public static bool ClientEditorDisplaying;
            public static bool ClientDeleteDisplaying;
            public static bool ClientCreateDisplaying;
    
            private WaterMeters.Manage meters;
            private WaterMeters.Editor meterEditor;
            private WaterMeters.Create meterCreate;
            private WaterMeters.Delete meterDelete;
    
            private Customers.ViewAll clients;
            private Customers.Editor clientEditor;
            private Customers.Create clientCreate;
            private Customers.Delete clientDelete;
    
            public WaterDistribution()
            {
                InitializeComponent();
    
                MetersDisplaying = false;
                MeterEditorDisplaying = false;
                MeterCreateDisplaying = false;
                MeterDeleteDisplaying = false;
    
                ClientsDisplaying = false;
                ClientEditorDisplaying = false;
                ClientCreateDisplaying = false;
                ClientDeleteDisplaying = false;
                
                meters = new WaterMeters.Manage();
                meterEditor = new WaterMeters.Editor();
                meterCreate = new WaterMeters.Create();
                meterDelete = new WaterMeters.Delete();
    
                clients = new Customers.ViewAll();
                clientEditor = new Customers.Editor();
                clientCreate = new Customers.Create();
                clientDelete = new Customers.Delete();
            }
    
            private void miWaterBillsCreate_Click(object sender, EventArgs e)
            {
                WaterBills.Create bill = new WaterBills.Create();
    
                bill.ShowDialog();
            }
    
            private void miWaterBillsDetails_Click(object sender, EventArgs e)
            {
                WaterBills.Details details = new WaterBills.Details();
    
                details.ShowDialog();
            }
    
            private void miCustomersCreate_Click(object sender, EventArgs e)
            {
                if (ClientCreateDisplaying == false)
                {
                    clientCreate = new();
                    clientCreate.MdiParent = this;
                    clientCreate.Show();
    
                    ClientCreateDisplaying = true;
                }
                else
                {
                    clientCreate.BringToFront();
                }
            }
    
            private void miCustomersEditor_Click(object sender, EventArgs e)
            {
                if (ClientEditorDisplaying == false)
                {
                    clientEditor = new();
                    clientEditor.MdiParent = this;
                    clientEditor.Show();
    
                    ClientEditorDisplaying = true;
                }
                else
                {
                    clientEditor.BringToFront();
                }
            }
    
            private void miCustomersDelete_Click(object sender, EventArgs e)
            {
                if (ClientDeleteDisplaying == false)
                {
                    clientDelete = new();
                    clientDelete.MdiParent = this;
                    clientDelete.Show();
    
                    ClientDeleteDisplaying = true;
                }
                else
                {
                    clientDelete.BringToFront();
                }
            }
    
            private void miCustomerViewAll_Click(object sender, EventArgs e)
            {
                if (ClientsDisplaying == false)
                {
                    clients = new();
                    clients.MdiParent = this;
                    clients.Show();
    
                    ClientsDisplaying = true;
                }
                else
                {
                    clients.BringToFront();
                }
            }
    
            private void miWaterMetersCreate_Click(object sender, EventArgs e)
            {
                if (MeterCreateDisplaying == false)
                {
                    meterCreate = new();
                    meterCreate.MdiParent = this;
                    meterCreate.Show();
    
                    MeterCreateDisplaying = true;
                }
                else
                {
                    meterCreate.BringToFront();
                }
            }
    
            private void miWaterMetersEditor_Click(object sender, EventArgs e)
            {
                if (MeterEditorDisplaying == false)
                {
                    meterEditor = new();
                    meterEditor.MdiParent = this;
                    meterEditor.Show();
    
                    MeterEditorDisplaying = true;
                }
                else
                {
                    meterEditor.BringToFront();
                }
            }
    
            private void miWaterMeterViewAll_Click(object sender, EventArgs e)
            {
                if (MetersDisplaying == false)
                {
                    meters = new WaterMeters.Manage();
    
                    meters.MdiParent = this;
                    meters.Show();
    
                    MetersDisplaying = true;
                }
                else
                {
                    meters.BringToFront();
                }
            }
    
            private void miWaterMetersDelete_Click(object sender, EventArgs e)
            {
                if (MeterDeleteDisplaying == false)
                {
                    meterDelete = new();
                    meterDelete.MdiParent = this;
                    meterDelete.Show();
    
                    MeterDeleteDisplaying = true;
                }
                else
                {
                    meterDelete.BringToFront();
                }
            }
    
            private void miWindowArrange_Click(object sender, EventArgs e)
            {
                LayoutMdi(MdiLayout.ArrangeIcons);
            }
    
            private void miWindowCascade_Click(object sender, EventArgs e)
            {
                LayoutMdi(MdiLayout.Cascade);
            }
    
            private void miWindowTileHorizontal_Click(object sender, EventArgs e)
            {
                LayoutMdi(MdiLayout.TileHorizontal);
            }
    
            private void miWindowTileVertical_Click(object sender, EventArgs e)
            {
                LayoutMdi(MdiLayout.TileVertical);
            }
    
            private void miHelpAbout_Click(object sender, EventArgs e)
            {
                AboutSWP about = new AboutSWP();
                about.ShowDialog();
            }
    
            private void miFileExit_Click(object sender, EventArgs e)
            {
                Close();
            }
        }
    }
  55. In the Solution Explorer, below Customers, double-click Create
  56. On the Customers Create form, double-click the Find Water Meter button
  57. Return to the Customers Create form and double-click the Save Customer Account button
  58. Return to the Customers Create form and click an unoccupied area of the form
  59. In the Solution Explorer, click the Events button Events
  60. While the Customers Create form is selected, in the Events section of the Properties window, double-click Activated
  61. Return to the Customers Create form and, in the Events section of the Properties window, double-click FormClosing
  62. Implement the events as follows:
    using System.Xml.Serialization;
    using StellarWaterPoint2.Models;
    
    namespace StellarWaterPoint2.Customers
    {
        public partial class Create : Form
        {
            public Create()
            {
                InitializeComponent();
            }
    
            private void btnFindWaterMeter_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(mtbMeterNumber.Text))
                {
                    MessageBox.Show("You must type a number for a water meter.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                WaterMeter? meter = null;
                List<WaterMeter> waterMeters = new List<WaterMeter>();
                string strWaterMeters = @"E:\Stellar Water Point\WaterMeters.xml";
                XmlSerializer xsWaterMeters = new XmlSerializer(typeof(List<WaterMeter>));
    
                FileInfo fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists == true)
                {
                    using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName))
                    {
                        waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!;
    
                        meter       = waterMeters.Find(m => m.MeterNumber == mtbMeterNumber.Text)!;
                    }
                }
    
                if (meter is null)
                {
                    MessageBox.Show("There is no water meter with that number in our system.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                txtMeterDetails.Text = meter.Make + " " +
                                       meter.Model + " (Meter #: " +
                                       meter.MeterSize + ")";
            }
    
            private void btnSaveCustomerAccount_Click(object sender, EventArgs e)
            {
                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;
                }
    
                List<Customer> clients    = new List<Customer>();
                string strCustomers       = @"E:\Stellar Water Point\Customers.xml";
                XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>));
    
                FileInfo fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists == true)
                {
                    using (TextReader trCustomers = new StreamReader(fiCustomers.FullName))
                    {
                        clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!;
                    }
                }
    
                Customer client = new Customer()
                {
                    AccountNumber = mtbAccountNumber.Text,
                    MeterNumber   = mtbMeterNumber.Text,
                    FirstName     = txtFirstName.Text,
                    LastName      = txtLastName.Text,
                    Address       = txtAddress.Text,
                    City          = txtCity.Text,
                    County        = txtCounty.Text,
                    State         = txtState.Text,
                    ZIPCode       = mtbZIPCode.Text
                };
    
                clients.Add(client);
    
                using (TextWriter twCustomers = new StreamWriter(fiCustomers.FullName))
                {
                    xsCustomers.Serialize(twCustomers, clients);
                }
    
                Close();
            }
    
            private void Create_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (WaterDistribution.ClientCreateDisplaying == true)
                {
                    WaterDistribution.ClientCreateDisplaying = false;
                    Close();
                }
            }
        }
    }
  63. In the Solution Explorer, below Customers, double-click Delete
  64. On the Customers Create form, double-click the Find Water Meter button
  65. Return to the Customers Create form and double-click the Close button
  66. Change the document as follows:
    using System.Xml.Serialization;
    using StellarWaterPoint20.Models;
    
    namespace StellarWaterPoint20.Customers
    {
        public partial class Delete : Form
        {
            public Delete()
            {
                InitializeComponent();
            }
    
            private void btnFindCustomer_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(mtbAccountNumber.Text))
                {
                    MessageBox.Show("You must type an account number for a customer.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                Customer? client = null;
                List<Customer> clients = new List<Customer>();
                string strCustomers = @"E:\Stellar Water Point\Customers.xml";
                XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>));
    
                FileInfo fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists == true)
                {
                    using (TextReader trCustomers = new StreamReader(fiCustomers.FullName))
                    {
                        clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!;
    
                        client = clients.Find(cust => cust.AccountNumber == mtbAccountNumber.Text)!;
                    }
                }
    
                if (client is null)
                {
                    MessageBox.Show("There is no customer with that account number in our system.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                mtbMeterNumber.Text = client.MeterNumber!;
                txtFirstName.Text   = client.FirstName;
                txtLastName.Text    = client.LastName;
                txtAddress.Text     = client.Address;
                txtCity.Text        = client.City;
                txtCounty.Text      = client.County;
                txtState.Text       = client.State;
                mtbZIPCode.Text     = client.ZIPCode;
    
                WaterMeter? meter            = null;
                List<WaterMeter> waterMeters = new List<WaterMeter>();
                string strWaterMeters        = @"E:\Stellar Water Point\WaterMeters.xml";
                XmlSerializer xsWaterMeters  = new XmlSerializer(typeof(List<WaterMeter>));
    
                FileInfo fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists == true)
                {
                    using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName))
                    {
                        waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!;
    
                        meter = waterMeters.Find(m => m.MeterNumber == mtbAccountNumber.Text)!;
                    }
                }
    
                txtMeterDetails.Text = meter?.Make + " " +
                                       meter?.Model + " (Meter #: " +
                                       meter?.MeterSize + ")";
            }
    
            private void btnDeleteCustomerAccount_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(mtbAccountNumber.Text))
                {
                    MessageBox.Show("You must type an account number held by a customer.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                List<Customer>? clients = new List<Customer>();
                string strCustomers = @"E:\Stellar Water Point\Customers.xml";
                XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>));
    
                FileInfo fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists == true)
                {
                    using (TextReader trCustomers = new StreamReader(fiCustomers.FullName))
                    {
                        clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!;
    
                        foreach (Customer cust in clients)
                        {
                            if (cust.AccountNumber == mtbAccountNumber.Text)
                            {
                                clients.Remove(cust);
                                MessageBox.Show("The customer account will be removed from the system.",
                                                "Stellar Water Point", MessageBoxButtons.OK);
                                break;
                            }
                        }
                    }
                }
    
                TextWriter twCustomers = new StreamWriter(fiCustomers.FullName);
    
                try
                {
                    xsCustomers.Serialize(twCustomers, clients);
                }
                finally
                {
                    twCustomers.Close();
                    Close();
                }
            }
    
            private void Delete_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (WaterDistribution.ClientDeleteDisplaying == true)
                {
                    WaterDistribution.ClientDeleteDisplaying = false;
                    Close();
                }
            }
        }
    }
  67. In the Solution Explorer, below Customers, double-click Editor
  68. On the Customers Create form, double-click the Find Customer button
  69. On the Customers Create form, double-click the Find Water Meter button
  70. Return to the Customers Create form and double-click the Update Customer Account button
  71. Change the document as follows:
    using System.Xml.Serialization;
    using StellarWaterPoint2.Models;
    
    namespace StellarWaterPoint2.Customers
    {
        public partial class Editor : Form
        {
            public Editor()
            {
                InitializeComponent();
            }
    
            private void btnFindCustomer_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(mtbAccountNumber.Text))
                {
                    MessageBox.Show("You must type an account number for a customer.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                Customer? client          = null;
                List<Customer> clients    = new List<Customer>();
                string strCustomers       = @"E:\Stellar Water Point\Customers.xml";
                XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>));
    
                FileInfo fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists == true)
                {
                    using (TextReader trCustomers = new StreamReader(fiCustomers.FullName))
                    {
                        clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!;
    
                        client = clients.Find(cust => cust.AccountNumber == mtbAccountNumber.Text)!;
                    }
                }
    
                if (client is null)
                {
                    MessageBox.Show("There is no customer with that account number in our system.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                mtbMeterNumber.Text = client.MeterNumber!;
                txtFirstName.Text   = client.FirstName;
                txtLastName.Text    = client.LastName;
                txtAddress.Text     = client.Address;
                txtCity.Text        = client.City;
                txtCounty.Text      = client.County;
                txtState.Text       = client.State;
                mtbZIPCode.Text     = client.ZIPCode;
    
                WaterMeter? meter            = null;
                List<WaterMeter> waterMeters = new List<WaterMeter>();
                string strWaterMeters        = @"E:\Stellar Water Point\WaterMeters.xml";
                XmlSerializer xsWaterMeters  = new XmlSerializer(typeof(List<WaterMeter>));
    
                FileInfo fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists == true)
                {
                    using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName))
                    {
                        waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!;
    
                        meter       = waterMeters.Find(m => m.MeterNumber == mtbMeterNumber.Text)!;
                    }
                }
    
                txtMeterDetails.Text = meter?.Make + " " +
                                       meter?.Model + " (Meter #: " +
                                       meter?.MeterSize + ")";
            }
    
            private void btnFindWaterMeter_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(mtbMeterNumber.Text))
                {
                    MessageBox.Show("You must type a number for a water meter.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                WaterMeter? meter = null;
                List<WaterMeter> waterMeters = new List<WaterMeter>();
                string strWaterMeters = @"E:\Stellar Water Point\WaterMeters.xml";
                XmlSerializer xsWaterMeters = new XmlSerializer(typeof(List<WaterMeter>));
    
                FileInfo fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists == true)
                {
                    using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName))
                    {
                        waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!;
    
                        meter = waterMeters.Find(m => m.MeterNumber == mtbMeterNumber.Text)!;
                    }
                }
    
                if (meter is null)
                {
                    MessageBox.Show("There is no water meter with that number in our system.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                txtMeterDetails.Text = meter.Make + " " +
                                       meter.Model + " (Meter #: " +
                                       meter.MeterSize + ")";
            }
    
            private void btnUpdateCustomerAccount_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(mtbAccountNumber.Text))
                {
                    MessageBox.Show("You must type a customer's account number.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                List<Customer> clients = new List<Customer>();
                string strCustomers = @"E:\Stellar Water Point\Customers.xml";
                XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>));
    
                FileInfo fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists == true)
                {
                    using (TextReader trCustomers = new StreamReader(fiCustomers.FullName))
                    {
                        clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!;
    
                        clients.ForEach(client =>
                        {
                            if (client.AccountNumber == mtbAccountNumber.Text)
                            {
                                client.MeterNumber = mtbMeterNumber.Text;
                                client.FirstName   = txtFirstName.Text;
                                client.LastName    = txtLastName.Text;
                                client.Address     = txtAddress.Text;
                                client.City        = txtCity.Text;
                                client.County      = txtCounty.Text;
                                client.State       = txtState.Text;
                                client.ZIPCode     = mtbZIPCode.Text;
                            }
                        });
                    }
                }
    
                using (TextWriter twCustomers = new StreamWriter(fiCustomers.FullName))
                {
                    xsCustomers.Serialize(twCustomers, clients);
                }
    
                Close();
            }
    
            private void Editor_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (WaterDistribution.ClientEditorDisplaying == true)
                {
                    WaterDistribution.ClientEditorDisplaying = false;
                    Close();
                }
            }
        }
    }
  72. In the Solution Explorer, below Customers, double-click ViewAll
  73. Click an unoccupied area of the form
  74. In the Events section of the Properties window, double-click Activated
  75. Return to the form and, in the Events section of the Properties window, double-click FormClosing
  76. Change the document as follows:
    using System.Xml.Serialization;
    using StellarWaterPoint2.Models;
    
    namespace StellarWaterPoint2.Customers
    {
        public partial class ViewAll : Form
        {
            public ViewAll()
            {
                InitializeComponent();
            }
    
            private void ShowCustomers()
            {
                List<Customer> clients    = new List<Customer>();
                string strCustomers       = @"E:\Stellar Water Point\Customers.xml";
                XmlSerializer xsCustomers = new XmlSerializer(typeof(List<Customer>));
    
                FileInfo fiCustomers = new FileInfo(strCustomers);
    
                if (fiCustomers.Exists == true)
                {
                    using (TextReader trCustomers = new StreamReader(fiCustomers.FullName))
                    {
                        clients = (List<Customer>)xsCustomers.Deserialize(trCustomers)!;
    
                        int counter = 1;
    
                        lvwCustomers.Items.Clear();
    
                        foreach (Customer client in clients)
                        {
                            ListViewItem lviCustomer = new ListViewItem(counter++.ToString());
    
                            lviCustomer.SubItems.Add(client.AccountNumber);
                            lviCustomer.SubItems.Add(client.MeterNumber);
                            lviCustomer.SubItems.Add(client.FirstName);
                            lviCustomer.SubItems.Add(client.LastName);
                            lviCustomer.SubItems.Add(client.Address);
                            lviCustomer.SubItems.Add(client.City);
                            lviCustomer.SubItems.Add(client.County);
                            lviCustomer.SubItems.Add(client.State);
                            lviCustomer.SubItems.Add(client.ZIPCode);
    
                            lvwCustomers.Items.Add(lviCustomer);
                        }
                    }
                }
            }
    
            private void ViewAll_Activated(object sender, EventArgs e)
            {
                ShowCustomers();
            }
    
            private void ViewAll_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (WaterDistribution.ClientsDisplaying == true)
                {
                    WaterDistribution.ClientsDisplaying = false;
                    Close();
                }
            }
        }
    }
  77. In the Solution Explorer, below WaterMeters, double-click Create
  78. On the Water Meters - Create form, double-click the S&ave Water Meter button
  79. Return to the form and, in the Events section of the Properties window, double-click FormClosing
  80. Implement the events as follows:
    using StellarWaterPoint2.Models;
    using System.Xml.Serialization;
    
    namespace StellarWaterPoint2.WaterMeters
    {
        public partial class Create : Form
        {
            public Create()
            {
                InitializeComponent();
            }
    
            private void btnSaveWaterMeter_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(mtbMeterNumber.Text))
                {
                    MessageBox.Show("You must type a meter number. " +
                                    "Otherwise, the water meter cannot be set up.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                List<WaterMeter> waterMeters = new List<WaterMeter>();
                string strWaterMeters = @"E:\Stellar Water Point\WaterMeters.xml";
                XmlSerializer xsWaterMeters = new XmlSerializer(typeof(List<WaterMeter>));
    
                FileInfo fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists == true)
                {
                    using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName))
                    {
                        waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!;
                    }
                }
    
                WaterMeter wm = new WaterMeter()
                {
                    MeterNumber = mtbMeterNumber.Text,
                    Make = txtMake.Text,
                    Model = txtModel.Text,
                    MeterSize = txtMeterSize.Text
                };
    
                waterMeters.Add(wm);
    
                using (TextWriter twWaterMeters = new StreamWriter(fiWaterMeters.FullName))
                {
                    xsWaterMeters.Serialize(twWaterMeters, waterMeters);
                }
    
                Close();
            }
    
            private void Create_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (WaterDistribution.MeterCreateDisplaying == true)
                {
                    WaterDistribution.MeterCreateDisplaying = false;
                    Close();
                }
            }
        }
    }
  81. In the Solution Explorer, below WaterMeters, double-click Editor
  82. Return to the form and double-click the Update Water Meter button
  83. Return to the form and click an unoccupied area of the form
  84. In the Events section of the Properties window, double-click FormClosing
  85. Change the document as follows:
    using StellarWaterPoint2.Models;
    using System.Xml.Serialization;
    
    namespace StellarWaterPoint2.WaterMeters
    {
        public partial class Editor : Form
        {
            public Editor()
            {
                InitializeComponent();
            }
    
            private void btnFindWaterMeter_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(mtbMeterNumber.Text))
                {
                    MessageBox.Show("You must type a number for a water meter.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                WaterMeter? meter = null;
                List<WaterMeter> waterMeters = new List<WaterMeter>();
                string strWaterMeters = @"E:\Stellar Water Point\WaterMeters.xml";
                XmlSerializer xsWaterMeters = new XmlSerializer(typeof(List<WaterMeter>));
    
                FileInfo fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists == true)
                {
                    using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName))
                    {
                        waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!;
    
                        meter       = waterMeters.Find(m => m.MeterNumber == mtbMeterNumber.Text)!;
                    }
                }
    
                if (meter is null)
                {
                    MessageBox.Show("There is no water meter with that number in our system.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
    
                txtMake.Text      = meter.Make;
                txtModel.Text     = meter.Model;
                txtMeterSize.Text = meter.MeterSize;
            }
    
            private void btnUpdateWaterMeter_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(mtbMeterNumber.Text))
                {
                    MessageBox.Show("You must type a number for a water meter.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                List<WaterMeter> waterMeters = new List<WaterMeter>();
                string strWaterMeters        = @"E:\Stellar Water Point\WaterMeters.xml";
                XmlSerializer xsWaterMeters  = new XmlSerializer(typeof(List<WaterMeter>));
    
                FileInfo fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists == true)
                {
                    using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName))
                    {
                        waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!;
    
                        waterMeters.ForEach(wm =>
                        {
                            if (wm.MeterNumber == mtbMeterNumber.Text)
                            {
                                wm.Make = txtMake.Text;
                                wm.Model = txtModel.Text;
                                wm.MeterSize = txtMeterSize.Text;
                            }
                        });
                    }
                }
    
                using (TextWriter twWaterMeters = new StreamWriter(fiWaterMeters.FullName))
                {
                    xsWaterMeters.Serialize(twWaterMeters, waterMeters);
                }
    
                Close();
            }
    
            private void Editor_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (WaterDistribution.MeterEditorDisplaying == true)
                {
                    WaterDistribution.MeterEditorDisplaying = false;
                    Close();
                }
            }
        }
    }
  86. In the Solution Explorer, below WaterMeters, double-click Manage
  87. In the Events section of the Properties window, double-click Activated
  88. Return to the form and, in the Events section of the Properties window, double-click FormClosing
  89. Change the document as follows:
    using System.Xml.Serialization;
    using StellarWaterPoint2.Models;
    
    namespace StellarWaterPoint2.WaterMeters
    {
        public partial class Manage : Form
        {
            public Manage()
            {
                InitializeComponent();
            }
    
            private void ShowWaterMeters()
            {
                string strWaterMeters        = @"E:\Stellar Water Point\WaterMeters.xml";
                List<WaterMeter> waterMeters = new List<WaterMeter>();
                XmlSerializer xsWaterMeters  = new XmlSerializer(typeof(List<WaterMeter>));
    
                FileInfo fiWaterMeters = new FileInfo(strWaterMeters);
    
                if (fiWaterMeters.Exists == true)
                {
                    using (TextReader trWaterMeters = new StreamReader(fiWaterMeters.FullName))
                    {
                        waterMeters = (List<WaterMeter>)xsWaterMeters.Deserialize(trWaterMeters)!;
    
                        int counter = 1;
    
                        lvwWaterMeters.Items.Clear();
    
                        foreach (WaterMeter wm in waterMeters)
                        {
                            ListViewItem lviWaterMeter = new ListViewItem(counter++.ToString());
    
                            lviWaterMeter.SubItems.Add(wm.MeterNumber);
                            lviWaterMeter.SubItems.Add(wm.Make);
                            lviWaterMeter.SubItems.Add(wm.Model);
                            lviWaterMeter.SubItems.Add(wm.MeterSize);
    
                            lvwWaterMeters.Items.Add(lviWaterMeter);
                        }
                    }
                }
            }
    
            private void Manage_Activated(object sender, EventArgs e)
            {
                ShowWaterMeters();
            }
    
            private void Manage_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (WaterDistribution.MetersDisplaying == true)
                {
                    WaterDistribution.MetersDisplaying = false;
                    Close();
                }
            }
        }
    }

Testing the Application

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

Practical LearningPractical Learning: Tesing the Application

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

  2. On the main menu, click Water Meters and click View All Water Meters...:

  3. On the main menu, click Water Meters and click Setup Water Meter...:

  4. Enter the value for each of the following records and click Save Water Meter 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. On the main menu, click Customers and click View All Accounts:

    Stellar Water Point - Water Meters

  6. On the main menu, click Custoemrs and click Create Customer Account:

    Stellar Water Point - Customers

  7. 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

  8. On the main menu, click Water Bills and click Prepare Water Bill...

    Stellar Water Point - Water Bill Processing

  9. Fill the form with the following values:
    Water Bill #:             847384
    Account #: 	              3028-502-9418
    Meter Reading Start Date: 10/03/2022
    Meter Reading End Date:   01/06/2023
    Counter Reading Start:    16
    Counter Reading End:      21
    Billing Days:             95
    Payment Due Date:         01/21/2023
    Late Payment Due Date:    02/05/2023

    Stellar Water Point - Water Bill Processing

  10. Click Find Customer Account

    Stellar Water Point - Water Bill Processing

  11. Click Evaluate Water Bill

    Stellar Water Point - Water Bill Processing

  12. Click Save Water Bill
  13. 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 Billing Days Payment Due Date Late Payment Due Date
    330820 7028-405-9381 10/03/2022 01/03/2023 9749 9906 92 01/18/2023 02/02/2023
    468550 7518-302-6895 10/05/2022 01/09/2023 96 114 96 01/24/2023 02/08/2023
    148274 9249-379-6848 10/05/2022 01/10/2023 260504 260555 97 01/25/2023 02/09/2023
    326384 2068-258-9486 10/08/2022 01/10/2023 104837 104851 94 01/25/2023 02/09/2023
  14. On the main menu, click Water Bills and click View Water Bill
  15. In the Water Bill # text box, type 468550
  16. Click Find Water Bill
  17. On the main menu, click Window and click Tile Vertical
  18. On the main menu, click Window and click Tile Horizontal
  19. On the main menu, click Window and click Cascade
  20. On the main menu, click File and click Exit
  21. Close Microsoft Visual Studio

Home Copyright © 2010-2023, FunctionX, Inc. Sunday 11 June 2023 Home