SDI and MDI Fundamentals

Introduction

A single-document interface, SDI, is an application primarily made of a form equipped with a menu. An example is Notepad:

Notepad

In some cases, an SDI can also have a toolbar and/or a status bar. Here is an example from Microsoft Works Spreadsheet:

Microsoft Works

All these features are left to the programmer to add and configure.

Although Notepad is text-based, an SDI can be any type of application: text, graphics, spreadsheet, anything. Therefore, to create an SDI, start from a normal form, add a menu to it, and configure it to do what you want.

To create a document using an SDI, the user launches the application. The SDI then presents a rectangular window with one frame and the inside is the document the user will use. In most cases, the application itself creates the document. The user can work on it and do whatever the application allows. To create another document of the same type, the user must open another instance of the application.

Practical LearningPractical Learning: Introducing MDI Applications

  1. Start Microsoft Visual Studio
  2. Create a Windows Forms App named StellarWaterPoint1
  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
  9. To create a class, in the Solution Explorer, right-click Models -> Add -> Class...
  10. On the main menu, click Project -> Add Class...
  11. Replace the name with WaterMeter
  12. Click Add
  13. Change the code as follows:
    namespace StellarWaterPoint1.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; }
        }
    }
  14. To create another class, in the Solution Explorer, right-click Models -> Add -> Class...
  15. On the main menu, click Project -> Add Class...
  16. Replace the name with Customer
  17. Click Add
  18. 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; }
        }
    }
  19. To create another class, in the Solution Explorer, right-click Models -> Add -> Class...
  20. On the main menu, click Project -> Add Class...
  21. Replace the name with WaterBill
  22. Click Add
  23. 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; }
        }
    }
  24. To create another class, in the Solution Explorer, right-click Models -> Add -> Class...
  25. On the main menu, click Project -> Add Class...
  26. Replace the name with Repository
  27. Click Add
  28. Change the code as follows:
    namespace StellarWaterPoint1.Models
    {
        sealed internal class Repository
        {
            public static Customer[]   Customers   { get; set; }
            public static WaterBill[]  WaterBills  { get; set; }
            public static WaterMeter[] WaterMeters { get; set; }
    
            static Repository()
            {
                Customers   = new Customer[10];
                WaterBills  = new WaterBill[10];
                WaterMeters = new WaterMeter[10];
            }
    
            public static void Add(in object addition)
            {
                if (addition is WaterMeter meter)
                {
                    for (int i = 0; i < WaterMeters.Length; i++)
                    {
                        if (string.IsNullOrEmpty(WaterMeters[i].MeterNumber))
                        {
                            WaterMeters[i]  = new WaterMeter()
                            {
                                MeterNumber = meter.MeterNumber,
                                Make        = meter.Make,
                                Model       = meter.Model,
                                MeterSize   = meter.MeterSize
                            };
                            break;
                        }
                    }
                }
                else if (addition is Customer client)
                {
                    for (int i = 0; i < Customers.Length; i++)
                    {
                        if (string.IsNullOrEmpty(Customers[i].AccountNumber))
                        {
                            Customers[i]      = new Customer()
                            {
                                AccountNumber = client.AccountNumber,
                                MeterNumber   = client.MeterNumber,
                                FirstName     = client.FirstName,
                                LastName      = client.LastName,
                                Address       = client.Address,
                                City          = client.City,
                                County        = client.County,
                                State         = client.State,
                                ZIPCode       = client.ZIPCode,
                            };
                            break;
                        }
                    }
                }
                else if (addition is WaterBill pay)
                {
                    for (int i = 0; i < WaterBills.Length; i++)
                    {
                        if (WaterBills[i].BillNumber == 0)
                        {
                            WaterBills[i]             = new WaterBill()
                            {
                                BillNumber            = pay.BillNumber,
                                AccountNumber         = pay.AccountNumber,
                                MeterReadingStartDate = pay.MeterReadingStartDate,
                                MeterReadingEndDate   = pay.MeterReadingEndDate,
                                BillingDays           = pay.BillingDays,
                                CounterReadingStart   = pay.CounterReadingStart,
                                CounterReadingEnd     = pay.CounterReadingEnd,
                                TotalGallons          = pay.TotalGallons,
                                TotalCCF              = pay.TotalCCF,
                                FirstTierConsumption  = pay.FirstTierConsumption,
                                SecondTierConsumption = pay.SecondTierConsumption,
                                LastTierConsumption   = pay.LastTierConsumption,
                                WaterCharges          = pay.WaterCharges,
                                SewerCharges          = pay.SewerCharges,
                                EnvironmentCharges    = pay.EnvironmentCharges,
                                TotalCharges          = pay.TotalCharges,
                                LocalTaxes            = pay.LocalTaxes,
                                StateTaxes            = pay.StateTaxes,
                                AmountDue             = pay.AmountDue,
                                PaymentDueDate        = pay.PaymentDueDate,
                                LateAmountDue         = pay.LateAmountDue,
                                LatePaymentDueDate    = pay.LatePaymentDueDate
                            };
                            break;
                        }
                    }
                }
            }
    
            public static WaterMeter GetWaterMeter(in string number)
            {
                if (number is not null)
                {
                    for (int i = 0; i < WaterMeters.Length; i++)
                    {
                        if (WaterMeters[i].MeterNumber!.Equals(number))
                        {
                            return WaterMeters[i];
                        }
                    }
                }
    
                return new WaterMeter();
            }
    
            public static Customer GetCustomer(in string number)
            {
                if (number is null)
                    return new Customer();
    
                for (int i = 0; i < Customers.Length; i++)
                {
                    if (Customers[i].AccountNumber!.Equals(number))
                    {
                        return Customers[i];
                    }
                }
    
                return new Customer();
            }
    
            public static WaterBill GetWaterBill(in int number)
            {
                if (number == 0)
                    return new WaterBill();
    
                for (int i = 0; i < WaterBills.Length; i++)
                {
                    if (WaterBills[i].BillNumber == number)
                    {
                        return WaterBills[i];
                    }
                }
    
                return new WaterBill();
            }
        }
    }

MDI Fundamentals

A multiple-document interface, MDI, is an application that primarily has a form and a menu. Some, if not most, MDIs also have one or more toolbars and/or a status bar. Here is an example:

Multiple-Document Interface

Like a normal application, to use an MDI, the user must launch it. In some cases, when the application starts, it is empty; that is, no document is created and the title bar displays a caption, usually the name of the application. Usually, there are steps the user must follow to create a document. In some other cases, when the application is launched, it automatically creates a document. A document resides inside the parent frame of the application. That is, a child document can use only the area reserved for it. The child document has its own system icon, its own title bar, and its own system buttons (Minimize, Maximize/Restore, and Close).

To use the whole area, the user can maximize the child document. When this is done, the child merges its title bar with the parent's. The new caption of the title bar becomes made of the text of the parent, followed by -, and followed by the caption the child window was using. The system buttons of the child document display under those of the parent frame:

MDI

Once a document has been created, the user can use it. Normally, the application must give the user the ability to create other documents while still using the application. If many documents have been created, all of them are confined to the frame of the parent:

Multiple Document Interface

The user can maximize the child forms. If so, the document that was in front occupies the whole area devoted to child documents. The other child forms stay in the back but become invisible.

One of the differences between an SDI and an MDI is that, because the child document and the MDI application don't share a frame, the user can close the child document and keep the application open.

Creating an MDI Application

As mentioned already, there is nothing magical with creating an SDI application. You start with a form, add a menu to it, and specify what the application should allow a user to do with a document. As we will see, an MDI requires more steps.

You start an MDI application with a normal form. You can create a Windows Forms Application using Microsoft Visual Studio or derive a class from Form. Here is an example:

using System.Windows.Forms;

public class CommonParent : Form
{
    public CommonParent()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        
    }

    [STAThread]
    public static int Main()
    {
        Application.Run(new CommonParent());

        return 0;
    }
}

The primary form of an MDI application is referred to as the parent or MDI container. It provides the frame inside of which the documents will reside. To provide this functionality, the Form class is equipped with a Boolean property named IsMdiContainer. Therefore, after creating the first form of your application, to indicate that it acts as the main frame, set this property to true. You can do this in the Properties window if you are visually creating your application, or programmatically. Here is an example:

using System.Windows.Forms;

public class CommonParent : Form
{
    public CommonParent()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        this.IsMdiContainer = true;
    }

    [STAThread]
    public static int Main()
    {
        Application.Run(new CommonParent());

        return 0;
    }
}

This would produce:

Multiple-Document Interface

The primary characteristic of an MDI is that it contains other forms. These forms must be created and made available to the parent. Each form can be created using a predefined form or you can programmatically create one by declaring an object of type Form. To allow you to specify that a form has a parent and will act as a child, the Form class is equipped with a property named MdiParent. This is a read-write property. The set accessor indicates what form acts as this one's parent. To provide this information, assign the main form this form's MdiParent. After doing this, you can display the form when you are ready, by calling its Show() method. Here is an example:

using System.Windows.Forms;

public class CommonParent : Form
{
    public CommonParent()
    {
        InitializeComponent();
    }

    void InitializeComponent()
    {
        this.IsMdiContainer = true;

        Form frmChild = new Form();
        frmChild.MdiParent = this;

        frmChild.Show();
    }

    [STAThread]
    public static int Main()
    {
        Application.Run(new CommonParent());

        return 0;
    }
}

This would produce:

Multiple-Document Interface

Practical LearningPractical Learning: Creating an MDI Application

  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
  5. In the Solution Explorer, right-click StellarWaterPoint1 -> Add -> New Folder
  6. Type WaterMeters as the name of the folder
  7. To create a form, in the Solution Explorer, right-click WaterMeters -> Add -> Form(Windows Forms)...
  8. Type Create
  9. Press Enter
  10. 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  
  11. To create a form, in the Solution Explorer, right-click WaterMeters -> Add -> Form(Windows Forms)...
  12. Type Manage
  13. Press Enter
  14. In the Toolbox, click the ListView button and click the form
  15. On the form, right-click the list view and click Edit Columns...
  16. Create the columns as follows:
    (Name) Text Width
    colWaterMeterId Id 40
    colMeterNumber Meter # 150
    colMake Make 225
    colModel Model 100
    colMeterSize Meter Size 150
  17. Click OK
  18. 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
  19. In the Solution Explorer, right-click StellarWaterPoint1 -> Add -> New Folder
  20. Type Customers as the name of the folder
  21. To create a form, on the main menu, click Customers -> Add Form (Windows Forms)...
  22. Type Create as the name of the file
  23. Click Add
  24. 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  
  25. To create a form, in the Solution Explorer, right-click Models -> Add -> Form(Windows Forms)...
  26. Type ViewAll
  27. Press Enter
  28. In the Toolbox, click the ListView button and click the form
  29. On the form, right-click the list view and click Edit Columns...
  30. 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
  31. Click OK
  32. Complete the design of the form as follows:

    Stellar Water Point - Customers

    Control (Name) Other Properties
    ListView List View lvwCustomers FullRowSelect: True
    GridLines: True
    View: Details
    Anchor: Top, Bottom, Left, Right
  33. In the Solution Explorer, right-click StellarWaterPoint1 -> Add -> New Folder
  34. Type WaterBills as the name of the folder
  35. To create a form, in the Solution Explorer, right-click WaterBills -> Add -> Form (Windows Forms)...
  36. Type Create as the name of the file
  37. Press Enter
  38. 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:  
    MaskedTextBox Masked Text Box mtbMeterReadingStartDate   Masked: Short Date
    Label Label   Meter Reading End Date:  
    MaskedTextBox Masked Text Box mtbMeterReadingEndDate   Masked: Short Date
    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:  
    MaskedTextBox Masked Text Box mtbPaymentDueDate   Masked: Short Date
    Label Label   Amount Due:  
    TextBox Text Box txtAmountDue   TextAlign: Right
    Label Label   Late Payment Due Date:  
    MaskedTextBox Masked Text Box mtbLatePaymentDueDate   Masked: Short Date
    Label Label   Late Amount Due:  
    TextBox Text Box txtLateAmountDue   TextAlign: Right
    Button Button btnSaveWaterBill Save Water Bill  
  39. To create a new form, on the main menu, click Project and click Form (Windows Forms)...
  40. Type Details as the name of the form
  41. Click Add
  42. Make that form the same size as the New Water Bill form
  43. Select everything on the New Water Bill form. Copy that selection and paste it in the new WaterBillView form
  44. On the WaterBillView form, delete the Find Customer Account, the Evaluate Water Bill, and the Save Water Bill buttons
  45. Add a Find Water Bill button as follows:

    Stellar Water Point - Water Bill Viewer

    Control (Name) Text
    Button Button btnFindWaterBill Find Water &Bill

MDI Characteristics

Introduction to the Children of an MDI

When you create an MDI application, you must make sure you provide your users with the ability to create documents. In fact, probably one of your first assignments is to make sure the user can create as many documents as necessary. As the documents are created, you need a way to programmatically keep track of the child forms. For example, you can store the documents in a collection. To assist you with this, the Form class is equipped with a property named MdiChildren, which is a read-only array. Each element of the MdiChildren[] array is of type Form. Therefore, to access a child form of an MDI application, you can pass an index to this property.

The Layout of Child Forms

Based on the standards defined in the operating system, as child forms are created in an MDI application, they are positioned each on top of the previous one but below the next one. The arrangement uses a 3-D coordiniate system whose origin is on the lower-left corner of the parent's frame just under the title bar (or the menu, if any; or the toolbar, if any), with the Z axis moving from the monitor towards you:

Layout

The operating system allows the user to choose among different arrangements. For example, you can position the documents as vertical columns, as horizontal rows, or as tiles. To support this, the Form class is equipped with a method named LayoutMdi. Its syntax is:

public void LayoutMdi(MdiLayout value);

The LayoutMdi() method takes an argument that is a member of the MdiLayout enumeration. The members of this enumeration are Cascade, TileHorizontal, TileVertical, and ArrangeIcons.

Practical LearningPractical Learning: Laying Out the Documents

  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
    &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
    &View All Water 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 View All Accounts
  38. Return to the Stellar Water Point form
  39. Click the Water Meters menu item and double-click Setup Water Meter...
  40. Return to the Stellar Water Point form and, below Setup Water Meter..., double-click View All Water Meters...
  41. Return to the Stellar Water Point form
  42. Click the Window menu item and double-click Arrange
  43. Return to the Stellar Water Point form and, below Arrange, double-click Cascade
  44. Return to the Stellar Water Point form and, below Cascade, double-click Tile Horizontal
  45. Return to the Stellar Water Point form and, below Tile Horizontal, double-click Tile Vertical
  46. Return to the Stellar Water Point form
  47. Click the Help menu item and double-click About Stellar Water Point...
  48. Return to the Stellar Water Point form
  49. Click the File menu item and double-click Exit
  50. Change the document as follows:
    namespace StellarWaterPoint11
    {
        public partial class WaterDistribution : Form
        {
            public static bool MetersDisplaying;
            public static bool CreateMeterDisplaying;
    
            public static bool ClientsDisplaying;
            public static bool CreateClientDisplaying;
    
            public static bool ViewBillDisplaying;
            public static bool CreateBillDisplaying;
    
            private WaterMeters.Create createMeter;
            private WaterMeters.Manage meters;
    
            private Customers.Create client;
            private Customers.ViewAll clients;
    
            private WaterBills.Create createBill;
            private WaterBills.Details billDetails;
    
            public WaterDistribution()
            {
                InitializeComponent();
    
                MetersDisplaying = false;
                CreateMeterDisplaying = false;
    
                ClientsDisplaying = false;
                CreateClientDisplaying = false;
    
                ViewBillDisplaying = false;
                CreateBillDisplaying = false;
    
                createBill = new WaterBills.Create();
                billDetails = new WaterBills.Details();
    
                createMeter = new WaterMeters.Create();
                meters = new WaterMeters.Manage();
    
                client = new Customers.Create();
                clients = new Customers.ViewAll();
            }
    
            private void miWaterBillsCreate_Click(object sender, EventArgs e)
            {
                if (CreateBillDisplaying == false)
                {
                    createBill = new();
                    createBill.MdiParent = this;
                    createBill.Show();
    
                    CreateBillDisplaying = true;
                }
                else
                {
                    createBill.BringToFront();
                }
            }
    
            private void miWaterBillsView_Click(object sender, EventArgs e)
            {
                if (ViewBillDisplaying == false)
                {
                    billDetails = new();
    
                    billDetails.MdiParent = this;
                    billDetails.Show();
                }
                else
                {
                    billDetails.BringToFront();
                }
            }
    
            private void miCustomersCreate_Click(object sender, EventArgs e)
            {
                if (CreateClientDisplaying == false)
                {
                    client = new Customers.Create();
                    client.MdiParent = this;
                    client.Show();
    
                    CreateClientDisplaying = true;
                }
                else
                {
                    client.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 (CreateMeterDisplaying == false)
                {
                    createMeter = new();
                    createMeter.MdiParent = this;
                    createMeter.Show();
    
                    CreateMeterDisplaying = true;
                }
                else
                {
                    createMeter.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 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 mnuWindowTileVertical_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();
            }
        }
    }
  51. In the Solution Explorer, below Customers, double-click Create
  52. On the Customers Create form, double-click the Find Water Meter button
  53. Return to the Customers Create form and double-click the Save Customer Account button
  54. Return to the Customers Create form and click an unoccupied area of the form
  55. In the Solution Explorer, click the Events button Events
  56. While the Customers Create form is selected, in the Events section of the Properties window, double-click Activated
  57. Return to the Customers Create form and, in the Events section of the Properties window, double-click FormClosing
  58. Implement the events as follows:
    using StellarWaterPoint1.Models;
    
    namespace StellarWaterPoint1.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 the meter number associated with the customer's account.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                WaterMeter meter = Repository.GetWaterMeter(mtbMeterNumber.Text);
    
                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 for the new customer.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                Customer account = 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
                };
    
                Repository.Add(account);
                Close();
            }
    
            private void Create_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (WaterDistribution.CreateClientDisplaying == true)
                {
                    WaterDistribution.CreateClientDisplaying = false;
                    Close();
                }
            }
        }
    }
  59. In the Solution Explorer, below Customers, double-click ViewAll
  60. Click an unoccupied area of the form
  61. In the Events section of the Properties window, double-click Activated
  62. Return to the form and, in the Events section of the Properties window, double-click FormClosing
  63. Change the document as follows:
    using StellarWaterPoint1.Models;
    
    namespace StellarWaterPoint1.Customers
    {
        public partial class ViewAll : Form
        {
            public ViewAll()
            {
                InitializeComponent();
            }
    
            private void ShowCustomers()
            {
                int counter = 1;
    
                lvwCustomers.Items.Clear();
    
                foreach (Customer cust in Repository.Customers)
                {
                    if (!(string.IsNullOrEmpty(cust.AccountNumber)))
                    {
                        ListViewItem lviCustomer = new ListViewItem(counter++.ToString());
    
                        lviCustomer.SubItems.Add(cust.AccountNumber);
                        lviCustomer.SubItems.Add(cust.MeterNumber);
                        lviCustomer.SubItems.Add(cust.FirstName);
                        lviCustomer.SubItems.Add(cust.LastName);
                        lviCustomer.SubItems.Add(cust.Address);
                        lviCustomer.SubItems.Add(cust.City);
                        lviCustomer.SubItems.Add(cust.County);
                        lviCustomer.SubItems.Add(cust.State);
                        lviCustomer.SubItems.Add(cust.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();
                }
            }
        }
    }
  64. In the Solution Explorer, below WaterMeters, double-click Create
  65. On the Water Meters - Create form, double-click the S&ave Water Meter button
  66. Return to the form and, in the Events section of the Properties window, double-click Activated
  67. Return to the form and, in the Events section of the Properties window, double-click FormClosing
  68. Implement the events as follows:
    using StellarWaterPoint1.Models;
    
    namespace StellarWaterPoint1.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 the meter number. " +
                                    "Otherwise, the water meter cannot be set up.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                WaterMeter wm = new WaterMeter()
                {
                    MeterNumber = mtbMeterNumber.Text,
                    Make = txtMake.Text,
                    Model = txtModel.Text,
                    MeterSize = txtMeterSize.Text
                };
    
                Repository.Add(wm);
                Close();
            }
    
            private void Create_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (WaterDistribution.CreateMeterDisplaying == true)
                {
                    WaterDistribution.CreateMeterDisplaying = false;
                    Close();
                }
            }
        }
    }
  69. In the Solution Explorer, below WaterMeters, double-click Manage
  70. In the Events section of the Properties window, double-click Activated
  71. In the Events section of the Properties window, double-click FormClosing
  72. Change the document as follows:
    using StellarWaterPoint1.Models;
    
    namespace StellarWaterPoint1.WaterMeters
    {
        public partial class Manage : Form
        {
            public Manage()
            {
                InitializeComponent();
            }
    
            void ShowWaterMeters()
            {
                int counter = 1;
    
                lvwWaterMeters.Items.Clear();
    
                foreach (WaterMeter wm in Repository.WaterMeters)
                {
                    if (!(string.IsNullOrEmpty(wm.MeterNumber)))
                    {
                        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();
                }
            }
        }
    }
  73. In the Solution Explorer, below WaterBills, double-click Create
  74. On the Water Bills - Create form, double-click the Find Customer Account button
  75. Return to the Water Bills - Create form and double-click the Evaluate Water Bill button
  76. Return to the Water Bills - Create form and double-click the Save Water Bill button
  77. Return to the form and, in the Events section of the Properties window, double-click FormClosing
  78. Change the document as follows:
    using StellarWaterPoint1.Models;
    
    namespace StellarWaterPoint1.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 enter a bill number.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                Customer client = Repository.GetCustomer(mtbAccountNumber.Text);
    
                string strMeterNumber = string.Empty;
    
                txtCustomerName.Text = client.FirstName + " " + client.LastName;
                strMeterNumber       = client.MeterNumber!;
                txtAddress.Text      = client.Address;
                txtCity.Text         = client.City;
                txtCounty.Text       = client.County;
                txtState.Text        = client.State;
                txtZIPCode.Text      = client.ZIPCode;
    
                WaterMeter meter     = Repository.GetWaterMeter(strMeterNumber);
    
                txtMeterDetails.Text = meter.Make    + " " +
                                       meter.Model   +
                                       " (Meter #: " + meter.MeterSize + ")";
            }
    
            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;
    
                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");
                txtAmountDue.Text             = amtDue.ToString("F");
                txtLateAmountDue.Text         = (amtDue + 8.95).ToString("F");
            }
    
            private void btnSaveWaterBill_Click(object sender, EventArgs e)
            {
                WaterBill bill = new WaterBill()
                {
                    BillNumber            = int.Parse(txtBillNumber.Text),
                    AccountNumber         = mtbAccountNumber.Text,
                    MeterReadingStartDate = mtbMeterReadingStartDate.Text,
                    MeterReadingEndDate   = mtbMeterReadingEndDate.Text,
                    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        = mtbPaymentDueDate.Text,
                    LateAmountDue         = double.Parse(txtLateAmountDue.Text),
                    LatePaymentDueDate    = mtbLatePaymentDueDate.Text
                };
    
                Repository.Add(bill);
                Close();
            }
    
            private void Create_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (WaterDistribution.CreateBillDisplaying == true)
                {
                    WaterDistribution.CreateBillDisplaying = false;
                    Close();
                }
            }
        }
    }
  79. In the Solution Explorer, below WaterBills, double-click Details
  80. On the form, double-click the Find Water Bill button
  81. Return to the Water Bills - Details form and, in the Events section of the Properties window, double-click FormClosing
  82. Change the document as follows:
    using StellarWaterPoint1.Models;
    
    namespace StellarWaterPoint1.WaterBills
    {
        public partial class Details : Form
        {
            public Details()
            {
                InitializeComponent();
            }
    
            private void btnFindWaterBill_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(txtWaterBillNumber.Text))
                {
                    MessageBox.Show("You must type a water bill number.",
                                    "Stellar Water Point", MessageBoxButtons.OK);
                    return;
                }
    
                WaterBill bill = Repository.GetWaterBill(int.Parse(txtWaterBillNumber.Text));
    
                mtbAccountNumber.Text = bill.AccountNumber;
                mtbMeterReadingStartDate.Text = bill.MeterReadingStartDate;
                mtbMeterReadingEndDate.Text = 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();
                mtbPaymentDueDate.Text = bill.PaymentDueDate;
                txtLateAmountDue.Text = bill.LateAmountDue.ToString();
                mtbLatePaymentDueDate.Text = bill.LatePaymentDueDate;
    
                string strMeterNumber = string.Empty;
                Customer client = Repository.GetCustomer(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 = Repository.GetWaterMeter(strMeterNumber);
    
                txtMeterDetails.Text = meter.Make + " " +
                                       meter.Model +
                                       " (Meter #: " + meter.MeterSize + ")";
            }
    
            private void Details_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (WaterDistribution.ViewBillDisplaying == true)
                {
                    WaterDistribution.ViewBillDisplaying = false;
                    Close();
                }
            }
        }
    }
  83. To execute, on the main menu, click Debug -> Start Without Debugging:

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

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

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

  87. On the main menu, click Customers and click View All Accounts:

    Stellar Water Point - Water Meters

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

    Stellar Water Point - Customers

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

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

    Stellar Water Point - Water Bill Processing

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

  92. Click Find Customer Account

    Stellar Water Point - Water Bill Processing

  93. Click Evaluate Water Bill

    Stellar Water Point - Water Bill Processing

  94. Click Save Water Bill
  95. 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
  96. On the main menu, click Water Bills and click View Water Bill
  97. In the Water Bill # text box, type 468550
  98. Click Find Water Bill
  99. On the main menu, click Window and click Tile Vertical
  100. On the main menu, click Window and click Tile Horizontal
  101. On the main menu, click Window and click Cascade
  102. On the main menu, click File and click Exit

Activating a Child

In most MDI applications, a user can create as many documents as necessary. This also means that the application can hold many child forms. To access a child form, the user can click its title bar. You can also provide options on a menu item named Window that would display a list of open documents.

When a child window is activated, it fires an event named MdiChildActivate:

public event EventHandler MdiChildActivate;

The MdiChildActivate event is of type EventArgs.

The document that is currently active has a brighter title bar. To identify this document, the form has a property named ActiveMdiChild. This read-only property allows you to know what document is the current active one. This property is of type Form, which means it produces a Form object. When you enquire about this property, if its value is null, it means there is no current active document. Here is an example of accessing the current active child document:

private void mnuFileClose_Click(object sender, EventArgs e)
{
    SingleDocument document = (SingleDocument)ActiveMdiChild;

    if( document  != null )
    {
        document.Close();
    }

    if (MdiChildren.Length== 0)
        mnuFileClose.Enabled = false;
}

If the value of the ActiveMdiChild property is not null, a document is active and you can use it. If you want to access the objects (Windows controls) that are positioned on a child form, remember that the child form is somehow foreign. Therefore, you should set the Modifiers property of its hosted controls approppriately. For example, if you want the parent frame to access a control on the child frame, set the Modifiers of that control to Public.

Arranging the Minimized Children

In an MDI application, if the user doesn't want to display a document but doesn't want to close it, he or she can minimise the window. In the same way, the user can minimize as many child forms as necessary. When a child form has been minimized, it shows a button in the lower part of the parent. The buttons of the other minimized child forms are usually positioned next to each other:

Minimized Buttons

The user can move the buttons at will:

Minimized Buttons

A user can also close the child form using the Close button of its minimized button. At one time the minimized buttons may display as a "mess". To let you rearrange them, call the LayoutMdi() method of the Form class and pass the argument as ArrangeIcons. When you do this, the application will visit all buttons, if any, that represent minimized child documents, and position them from the left to the right, adjacently.

Microsoft Visual Studio Assistance With MDI Applications

Microsoft Visual Studio makes it easy for you to create an MDI application. It doesn't do everything for you but it provides all the primary design you may need. It does this through the MDI Parent Form of the Add New Item dialog box.

Practical LearningPractical Learning: Ending the Application


Previous Copyright © 2010-2024, FunctionX, Inc. Friday 10 June 2022 Next