Home

XML Example Application: FunDS (Fun Department Store)

   

Introduction

XML provide effective and wonderful means to create a database repository. XML by itself doesn't create or save records. It only defines how datashould be stored. On the other hand, another language, a library, or a programming environment can be used to create, save, or maintain data (for example, editing or deleting records).

We are going to create an example database application for a department store. We will name the business as FunDS, which stands for Fun Department Store.

The Employees

Naturally, we need people who can run the business.

Practical LearningPractical Learning: Introducing the Application

  1. Start Microsoft Visual Studio
  2. To start a new project, on the main menu, click File -> New -> Project...
  3. In the New Project dialog box, click Visual F# in the left list and click Console Application in the middle list
  4. Set the Name to FunDS1 and click OK
  5. On the main menu, click Project -> Add Reference...
  6. In the middle list of the Reference Manager dialog box, click the check boxes of System.Drawing, System.Windows.Forms, and System.Xml
  7. Click OK
  8. On the main menu, click Project -> FunDS1 Properties...
  9. In the Output Type combo box, select Windows Application
  10. In the Solution Explorer, right-click Program.fs -> Add Above -> New Item...
  11. In the middle list, click Source File and set the name to EmployeeNew
  12. Click Add
  13. Change the contents of the document as follows:
    module EmployeeNew
    
    open System
    open System.IO
    open System.Xml
    open System.Drawing
    open System.Windows.Forms
    
    // Dialog Box: New Employee
    let employeeNew = new Form(MaximizeBox = false, MinimizeBox = false,
                               Text = "Fun Department Store - New Employee",
                               FormBorderStyle = FormBorderStyle.FixedDialog,
                               ClientSize = new System.Drawing.Size(388, 260),
                               StartPosition = FormStartPosition.CenterScreen)
    
    // Employee Number
    employeeNew.Controls.Add(new Label(TabIndex = 0, AutoSize = true,
                                       Text = "Employee #:", Location = new Point(13, 18)))
    let txtEmployeeNumber = new TextBox(Location = new Point(94, 16),
                                        TabIndex = 1, Width = 88)
    employeeNew.Controls.Add txtEmployeeNumber
    
    // First Name
    employeeNew.Controls.Add(new Label(TabIndex = 2, Text = "First Name:",
                                       AutoSize = true, Location = new Point(13, 49)))
    
    let txtFirstName = new TextBox(TabIndex = 3, Location = new Point(94, 46), Width = 88)
    employeeNew.Controls.Add txtFirstName
    
    // Last Name
    employeeNew.Controls.Add(new Label(TabIndex = 4, AutoSize = true,
                                       Text = "Last Name:", Location = new Point(195, 49)))
    
    let txtLastName = new TextBox(Location = new Point(276, 46), TabIndex = 5, Width = 88)
    employeeNew.Controls.Add txtLastName
    
    // Address
    employeeNew.Controls.Add(new Label(TabIndex = 6, AutoSize = true,
                                       Text = "Address:", Location = new Point(13, 75)))
    let txtAddress = new TextBox(Width = 270, TabIndex = 7, Location = new Point(94, 72))
    employeeNew.Controls.Add txtAddress
    
    // City
    employeeNew.Controls.Add(new Label(TabIndex = 8, Text = "City:",
                                       AutoSize = true, Location = new Point(13, 101)))
    let txtCity = new TextBox(Location = new Point(94, 98), TabIndex = 9, Width = 270)
    employeeNew.Controls.Add txtCity
            
    // County
    employeeNew.Controls.Add(new Label(TabIndex = 10, AutoSize = true,
                                       Text = "County:", Location = new Point(13, 127)))
    let txtCounty = new TextBox(Location = new Point(94, 124), TabIndex = 11, Width = 88)
    employeeNew.Controls.Add txtCounty
    
    // State
    employeeNew.Controls.Add(new Label(TabIndex = 12, AutoSize = true,
                                       Text = "State:", Location = new Point(195, 127)))
    let txtState = new TextBox(Location = new Point(276, 124), TabIndex = 13, Width = 88)
    employeeNew.Controls.Add txtState
    
    // ZIP Code
    employeeNew.Controls.Add(new Label(AutoSize = true, TabIndex = 14,
                                       Text = "ZIP Code:", Location = new Point(13, 153)))
    let txtZIPCode = new TextBox(Location = new Point(94, 150), TabIndex = 15, Width = 88)
    employeeNew.Controls.Add txtZIPCode
    
    // Marital Status
    employeeNew.Controls.Add(new Label(TabIndex = 16, AutoSize = true,
                                       Text = "Marital Status:", Location = new Point(195, 153)))
    let cbxMaritalsStatus = new ComboBox(TabIndex = 17, Size = new Size(88, 21),
                                         Location = new Point(276, 150))
    cbxMaritalsStatus.Items.AddRange [| "Single"; "Married" |]
    employeeNew.Controls.Add cbxMaritalsStatus
    
    // Exemptions
    employeeNew.Controls.Add(new Label(TabIndex = 18, AutoSize = true,
                                       Text = "Exemptions:", Location = new Point(13, 179)))
    let txtExemptions = new TextBox(Text = "0", Width = 88,
                                    TextAlign = HorizontalAlignment.Right,
                                    TabIndex = 19, Location = new Point(94, 176))
    employeeNew.Controls.Add txtExemptions
    
    // Hourly Salary
    employeeNew.Controls.Add(new Label(TabIndex = 20, AutoSize = true,
                                       Text = "Hourly Salary:", Location = new Point(195, 180)))
    let txtHourlySalary = new TextBox(Location = new Point(276, 177), TabIndex = 21, Width = 88)
    employeeNew.Controls.Add txtHourlySalary
           
    // Button: OK
    let btnOK = new Button(TabIndex = 22, Text = "OK", Width = 75,
                           DialogResult = DialogResult.OK, Location = new Point(202, 220))
    employeeNew.Controls.Add btnOK
    
    // Button: Cancel
    let btnCancel = new Button(TabIndex = 23, Text = "Cancel",
                               DialogResult = DialogResult.Cancel,
                               Location = new Point(288, 220), Width = 75)
    employeeNew.Controls.Add btnCancel
    
    employeeNew.AcceptButton <- btnOK
    employeeNew.CancelButton <- btnCancel
  14. In the Solution Explorer, right-click EmployeeNew -> Add Above -> New Item...
  15. In the middle list, click Source File and set the name to EmployeeEditor
  16. Click Add
  17. Change the contents of the document as follows:
    module EmployeeEditor
    
    open System
    open System.IO
    open System.Xml
    open System.Drawing
    open System.Windows.Forms
    
    // Dialog Box: Employee Editor
    let editor = new Form(MaximizeBox = false, StartPosition = FormStartPosition.CenterScreen,
                          MinimizeBox = false, FormBorderStyle = FormBorderStyle.FixedDialog,
                          Text = "Fun Department Store: Employee Editor", ClientSize = new System.Drawing.Size(394, 259))
    
    // Employee Number
    editor.Controls.Add(new Label(Location = new Point(13, 18),
                                  TabIndex = 0, AutoSize = true, Text = "Employee #:"))
    
    // Employee Number
    let txtEmployeeNumber = new TextBox(Width = 88, TabIndex = 1, Location = new Point(94, 16))
    
    editor.Controls.Add txtEmployeeNumber
    
    // Button: Find
    let btnFind = new Button(TabIndex = 2, Text = "Find", Location = new Point(201, 18), Width = 75)
    editor.Controls.Add btnFind
    
    // First Name
    editor.Controls.Add(new Label(AutoSize = true, Location = new Point(13, 49), TabIndex = 5, Text = "First Name:"))
    
    let txtFirstName = new TextBox(Location = new Point(94, 46), Width = 88, TabIndex = 6)
    editor.Controls.Add txtFirstName
    
    // Last Name
    editor.Controls.Add(new Label(AutoSize = true, Location = new Point(195, 49), TabIndex = 7, Text = "Last Name:"))
    let txtLastName = new TextBox(Location = new Point(276, 46), Width = 88, TabIndex = 8)
    editor.Controls.Add txtLastName
    
    // Address
    editor.Controls.Add(new Label(AutoSize = true, Location = new Point(13, 75), TabIndex = 9, Text = "Address:"))
    let txtAddress = new TextBox(Location = new Point(94, 72), Size = new System.Drawing.Size(270, 20), TabIndex = 10)
    editor.Controls.Add txtAddress
    
    // City
    editor.Controls.Add(new Label(AutoSize = true, Location = new Point(13, 101), TabIndex = 11, Text = "City:"))
    let txtCity = new TextBox(Location = new Point(94, 98), Width = 270, TabIndex = 12)
    editor.Controls.Add txtCity
    
    // County
    editor.Controls.Add(new Label(AutoSize = true, Location = new Point(13, 127), TabIndex = 13, Text = "County:"));
    let txtCounty = new TextBox(Location = new Point(94, 124), Width = 88, TabIndex = 14)
    editor.Controls.Add txtCounty
    
    // State
    editor.Controls.Add(new Label(AutoSize = true, Location = new Point(195, 127), TabIndex = 15, Text = "State:"))
    let txtState = new TextBox(Location = new Point(276, 124), Width = 88, TabIndex = 16)
    editor.Controls.Add txtState
    
    // ZIP Code
    editor.Controls.Add(new Label(AutoSize = true, Location = new Point(13, 153), TabIndex = 17, Text = "ZIP Code:"))
    let txtZIPCode = new TextBox(Location = new Point(94, 150), Width = 88, TabIndex = 18)
    editor.Controls.Add txtZIPCode
    
    // Marital Status
    editor.Controls.Add(new Label(AutoSize = true, Location = new Point(195, 153), TabIndex = 19, Text = "Marital Status:"))
    let cbxMaritalsStatus = new ComboBox(Location = new Point(276, 150), Width = 88, TabIndex = 20)
    cbxMaritalsStatus.Items.AddRange [| "Single"; "Married" |]
    editor.Controls.Add cbxMaritalsStatus
    
    // Exemptions
    editor.Controls.Add(new Label(AutoSize = true, Location = new Point(13, 179), TabIndex = 21, Text = "Exemptions:"))
    let txtExemptions = new TextBox(Location = new Point(94, 176), Width = 88,
                                    TabIndex = 22, Text = "0", TextAlign = HorizontalAlignment.Right)
    editor.Controls.Add txtExemptions
    
    // Hourly Salary
    editor.Controls.Add(new Label(AutoSize = true, Location = new Point(195, 180), TabIndex = 23, Text = "Hourly Salary:"))
    
    let txtHourlySalary = new TextBox(Location = new Point(276, 177), Width = 88, TabIndex = 24)
    editor.Controls.Add txtHourlySalary
    
    let btnFindClick e =
        let mutable employeeFound : bool  = false
        let xdEmployees : XmlDocument = new XmlDocument()
        let strEmployeesFile : string = @"G:\Fun Department Store\Employees.xml"
    
        if String.IsNullOrEmpty(txtEmployeeNumber.Text) then
            MessageBox.Show("You must enter an employee number.", "FunDS - Employees Records",
                            MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
        else
            if File.Exists(strEmployeesFile) then
                use fsEmployees : FileStream = new FileStream(strEmployeesFile, FileMode.Open, FileAccess.Read)
                xdEmployees.Load fsEmployees
                fsEmployees.Close()
    
                let xnlEmployees : XmlNodeList = xdEmployees.GetElementsByTagName("EmployeeNumber")
    
                for xnEmployee : XmlNode in xnlEmployees do
                    if xnEmployee.InnerText = txtEmployeeNumber.Text then
                        txtFirstName.Text <- xnEmployee.NextSibling.InnerText // First Name
                        txtLastName.Text <- xnEmployee.NextSibling.NextSibling.InnerText // Last Name
                        txtAddress.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.InnerText // Address
                        txtCity.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.InnerText // City
                        txtCounty.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText // County
                        txtState.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText // State
                        txtZIPCode.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText // ZIP Code
                        cbxMaritalsStatus.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText // Marital Status
                        txtExemptions.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText // Exemptions
                        txtHourlySalary.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText // Hourly Salary
    
                        employeeFound <- true
    
                if employeeFound = false then
                    MessageBox.Show("There is no staff member with that employee number.",
                                    "FunDS - Employees Records", MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
    btnFind.Click.Add btnFindClick
    
    // Button: Submit
    let btnSubmit = new Button(Location = new Point(207, 218), Width = 84, TabIndex = 3, Text = "Submit")
    editor.Controls.Add btnSubmit
    
    let btnSubmitClick e =
        let xdEmployees : XmlDocument = new XmlDocument()
        let strEmployeesFile : string = @"G:\Fun Department Store\Employees.xml"
    
        if String.IsNullOrEmpty(txtEmployeeNumber.Text) then
            MessageBox.Show("You must enter an employee number.",  "FunDS - Employees Records",
                            MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
        else
            if File.Exists(strEmployeesFile) then
                use fsEmployees : FileStream = new FileStream(strEmployeesFile, FileMode.Open, FileAccess.Read)
                xdEmployees.Load fsEmployees
                fsEmployees.Close()
    
                let xnlEmployees : XmlNodeList = xdEmployees.GetElementsByTagName("EmployeeNumber");
    
                for xnEmployee : XmlNode in xnlEmployees do
                    if xnEmployee.InnerText = txtEmployeeNumber.Text then
                        xnEmployee.ParentNode.InnerXml <- "<EmployeeNumber>" + txtEmployeeNumber.Text + "</EmployeeNumber>" +
                                                          "<FirstName>" + txtFirstName.Text + "</FirstName>" +
                                                          "<LastName>" + txtLastName.Text + "</LastName>" +
                                                          "<Address>" + txtAddress.Text + "</Address>" +
                                                          "<City>" + txtCity.Text + "</City>" +
                                                          "<County>" + txtCounty.Text + "</County>" +
                                                          "<State>" + txtState.Text + "</State>" +
                                                          "<ZIPCode>" + txtZIPCode.Text + "</ZIPCode>" +
                                                          "<MaritalStatus>" + cbxMaritalsStatus.Text + "</MaritalStatus>" +
                                                          "<Exemptions>" + txtExemptions.Text + "</Exemptions>" +
                                                          "<HourlySalary>" + txtHourlySalary.Text + "</HourlySalary>"
    
                        use fsEmployees : FileStream = new FileStream(strEmployeesFile, FileMode.Create, FileAccess.Write)
                        xdEmployees.Save fsEmployees
                    
                        MessageBox.Show("The employee's record has been updated.",
                                        "FunDS - Employees Records",
                                        MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
                        fsEmployees.Close()
                        editor.Close()
    
    btnSubmit.Click.Add btnSubmitClick
    
    // Button: Close
    let btnClose = new Button(Location = new Point(297, 218), Width = 75, TabIndex = 4, Text = "Close")
    editor.Controls.Add btnClose
    
    let btnCloseClick e = editor.Close()
    btnClose.Click.Add btnCloseClick
  18. In the Solution Explorer, right-click EmployeeEditor -> Add Above -> New Item...
  19. In the middle list, click Source File and set the name to Employees
  20. Click Add
  21. Change the contents of the document as follows:
    module Employees
    
    open System
    open System.IO
    open System.Xml
    open System.Drawing
    open System.Windows.Forms
    
    open EmployeeNew
    open EmployeeEditor
    
    type Employees() as this =
        inherit Form()
    
        let mutable colEmployeeNumber : ColumnHeader = null
        let mutable colFirstName      : ColumnHeader = null
        let mutable colLastName       : ColumnHeader = null
        let mutable colAddress        : ColumnHeader = null
        let mutable colCity           : ColumnHeader = null
        let mutable colCounty         : ColumnHeader = null
        let mutable colState          : ColumnHeader = null
        let mutable colZIPCode        : ColumnHeader = null
        let mutable colMaritalStatus  : ColumnHeader = null
        let mutable colExemptions     : ColumnHeader = null
        let mutable colHourlySalary   : ColumnHeader = null
        let mutable lvwEmployees      : ListView     = null
    
        let mutable lblNumberOfEmployees : Label   = null
        let mutable txtNumberOfEmployees : TextBox = null
        let mutable btnNewEmployee       : Button  = null
        let mutable btnEmployeeEditor    : Button  = null
        let mutable btnClose             : Button  = null
    
        do //member this.InitializeComponent() =
            // Column: Employee Number
            colEmployeeNumber <- new ColumnHeader()
            colEmployeeNumber.Text <- "Employee #"
            colEmployeeNumber.Width <- 70
    
            // Column: First Name
            colFirstName <- new ColumnHeader()
            colFirstName.Text <- "First Name"
            colFirstName.Width <- 65
    
            // Column: Last Name
            colLastName <- new ColumnHeader()
            colLastName.Text <- "Last Name"
            colLastName.Width <- 70
    
            // Column: Address
            colAddress <- new ColumnHeader()
            colAddress.Text <- "Address"
            colAddress.Width <- 125
    
            // Column: City
            colCity <- new ColumnHeader()
            colCity.Text <- "City"
            colCity.Width <- 75
    
            // Column: Username
            colCounty <- new ColumnHeader()
            colCounty.Text <- "County"
    
            // Column: State
            colState <- new ColumnHeader()
            colState.Text <- "State"
            colState.Width <- 40
    
            // Column: ZIP Code
            colZIPCode <- new ColumnHeader()
            colZIPCode.Text <- "ZIP Code"
    
            // Column: Marital Status
            colMaritalStatus <- new ColumnHeader()
            colMaritalStatus.Text <- "Marital Status"
            colMaritalStatus.Width <- 80
    
            // Column: Exemptions
            colExemptions <- new ColumnHeader()
            colExemptions.Text <- "Exemptions"
            colExemptions.TextAlign <- HorizontalAlignment.Right
            colExemptions.Width <- 70
    
            // Column: Hourly Salary
            colHourlySalary <- new ColumnHeader()
            colHourlySalary.Text <- "Salary"
            colHourlySalary.TextAlign <- HorizontalAlignment.Right
            colHourlySalary.Width <- 45
    
            // List View: Employees
            lvwEmployees <- new ListView()
            lvwEmployees.Anchor <- AnchorStyles.Top ||| AnchorStyles.Bottom ||| AnchorStyles.Left ||| AnchorStyles.Right
            lvwEmployees.Columns.AddRange[| colEmployeeNumber; colFirstName; colLastName;
                                            colAddress; colCity; colCounty; colState; colZIPCode;
                                            colMaritalStatus; colExemptions; colHourlySalary |]
    
            lvwEmployees.FullRowSelect <- true
            lvwEmployees.GridLines <- true
            lvwEmployees.Location <- new System.Drawing.Point(16, 12)
            lvwEmployees.Size <- new System.Drawing.Size(785, 125)
            lvwEmployees.TabIndex <- 25
            lvwEmployees.View <- View.Details
            // lvwEmployees.DoubleClick += new EventHandler(lvwEmployeesDoubleClick)
    
            // Label: NumberOfEmployees
            lblNumberOfEmployees <- new Label()
            lblNumberOfEmployees.Anchor <- AnchorStyles.Bottom ||| AnchorStyles.Left
            lblNumberOfEmployees.AutoSize <- true
            lblNumberOfEmployees.Location <- new Point(12, 158)
            lblNumberOfEmployees.Size <- new System.Drawing.Size(113, 13)
            lblNumberOfEmployees.TabIndex <- 28
            lblNumberOfEmployees.Text <- "Number of Employees:"
    
            // Text Box: NumberOfEmployees
            txtNumberOfEmployees <- new TextBox()
            txtNumberOfEmployees.Anchor <- AnchorStyles.Bottom ||| AnchorStyles.Left
            txtNumberOfEmployees.Location <- new Point(131, 155)
            txtNumberOfEmployees.Size <- new System.Drawing.Size(60, 20)
            txtNumberOfEmployees.TabIndex <- 29
            txtNumberOfEmployees.TextAlign <- HorizontalAlignment.Right
    
            // Button: NewEmployee
            btnNewEmployee <- new Button()
            btnNewEmployee.Anchor <- AnchorStyles.Bottom ||| AnchorStyles.Right
            btnNewEmployee.Location <- new Point(493, 153)
            btnNewEmployee.Size <- new System.Drawing.Size(109, 23)
            btnNewEmployee.TabIndex <- 27
            btnNewEmployee.Text <- "New Employee ..."
    
            // Button: Employee Editor
            btnEmployeeEditor <- new Button()
            btnEmployeeEditor.Anchor <- AnchorStyles.Bottom ||| AnchorStyles.Right
            btnEmployeeEditor.Location <- new Point(605, 153)
            btnEmployeeEditor.Size <- new System.Drawing.Size(109, 23)
            btnEmployeeEditor.TabIndex <- 27
            btnEmployeeEditor.Text <- "Employee Editor..."
    
            // Button: Close
            btnClose <- new Button()
            btnClose.Anchor <- AnchorStyles.Bottom ||| AnchorStyles.Right
            btnClose.Location <- new Point(718, 153)
            btnClose.Size <- new System.Drawing.Size(75, 23)
            btnClose.TabIndex <- 26
            btnClose.Text <- "Close"
            btnClose.Click.Add(fun e -> this.Close())
    
            // Form: Employees
            this.ClientSize <- new System.Drawing.Size(820, 185)
    
            this.Controls.Add lvwEmployees
            this.Controls.Add lblNumberOfEmployees
            this.Controls.Add txtNumberOfEmployees
            this.Controls.Add btnEmployeeEditor
            this.Controls.Add btnNewEmployee
            this.Controls.Add btnClose
    
            this.MaximizeBox <- false
            this.StartPosition <- FormStartPosition.CenterScreen
            this.Text <- "Fun Department Store - Employees"
    
        let ShowEmployees() =
            let xdEmployees : XmlDocument = new XmlDocument()
            let strEmployeesFile : string = @"G:\Fun Department Store\Employees.xml"
    
            if File.Exists(strEmployeesFile) then
                lvwEmployees.Items.Clear()
                use fsEmployees : FileStream = new FileStream(strEmployeesFile, FileMode.Open, FileAccess.Read)
                xdEmployees.Load fsEmployees
    
                let xnlEmployees : XmlNodeList = xdEmployees.GetElementsByTagName("EmployeeNumber")
    
                for xnEmployee : XmlNode in xnlEmployees do
                    let lviEmployee : ListViewItem = new ListViewItem(xnEmployee.InnerText) // Employee Number
                    let mutable result = lviEmployee.SubItems.Add(xnEmployee.NextSibling.InnerText) // First Name
                    result <- lviEmployee.SubItems.Add(xnEmployee.NextSibling.NextSibling.InnerText) // Last Name
                    result <- lviEmployee.SubItems.Add(xnEmployee.NextSibling.NextSibling.NextSibling.InnerText) // Address
                    result <- lviEmployee.SubItems.Add(xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.InnerText) // City
                    result <- lviEmployee.SubItems.Add(xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText) // County
                    result <- lviEmployee.SubItems.Add(xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText) // State
                    result <- lviEmployee.SubItems.Add(xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText) // ZIP Code
                    result <- lviEmployee.SubItems.Add(xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText) // Marital Status
                    result <- lviEmployee.SubItems.Add(xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText) // Exemptions
                    result <- lviEmployee.SubItems.Add(xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText) // Hourly Salary
    
                    let mutable lvi = lvwEmployees.Items.Add lviEmployee
                    lvi <- null
                    txtNumberOfEmployees.Text <- sprintf "%i" xnlEmployees.Count
    
                    fsEmployees.Close()
    
        let lvwEmployeesDoubleClick e =
            let xdEmployees : XmlDocument = new XmlDocument()
            let strEmployeesFile : string = @"G:\Fun Department Store\Employees.xml"
    
            if lvwEmployees.Items.Count > 0 then
                use fsEmployees : FileStream = new FileStream(strEmployeesFile, FileMode.Open, FileAccess.Read)
                xdEmployees.Load fsEmployees
    
                let xnlEmployees : XmlNodeList = xdEmployees.GetElementsByTagName("EmployeeNumber")
    
                for xnEmployee : XmlNode in xnlEmployees do
                    if xnEmployee.InnerText = lvwEmployees.SelectedItems.[0].Text then
                        let mutable result = EmployeeEditor.txtEmployeeNumber.Text <- lvwEmployees.SelectedItems.[0].Text // 
                        result <- EmployeeEditor.txtFirstName.Text <- xnEmployee.NextSibling.InnerText // First Name
                        result <- EmployeeEditor.txtLastName.Text <- xnEmployee.NextSibling.NextSibling.InnerText // Last Name
                        result <- EmployeeEditor.txtAddress.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.InnerText // Address
                        result <- EmployeeEditor.txtCity.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.InnerText // City
                        result <- EmployeeEditor.txtCounty.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText // County
                        result <- EmployeeEditor.txtState.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText // State
                        result <- EmployeeEditor.txtZIPCode.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText // ZIP Code
                        result <- EmployeeEditor.cbxMaritalsStatus.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText // Marital Status
                        result <- EmployeeEditor.txtExemptions.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText // Exemptions
                        result <- EmployeeEditor.txtHourlySalary.Text <- xnEmployee.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText // Hourly Salary
                        
            editor.ShowDialog() |> ignore
    
        let btnEmployeeEditorClick e =
            EmployeeEditor.txtEmployeeNumber.Text <- ""
    
            EmployeeEditor.txtFirstName.Text <- ""
            EmployeeEditor.txtLastName.Text <- ""
            EmployeeEditor.txtAddress.Text <- ""
            EmployeeEditor.txtCity.Text <- ""
            EmployeeEditor.txtCounty.Text <- ""
            EmployeeEditor.txtState.Text <- ""
            EmployeeEditor.txtZIPCode.Text <- ""
            EmployeeEditor.cbxMaritalsStatus.Text <- ""
            EmployeeEditor.txtExemptions.Text <- "0"
            EmployeeEditor.txtHourlySalary.Text <- "0.00"
    
            EmployeeEditor.editor.ShowDialog() |> ignore
    
        do
            lvwEmployees.DoubleClick.Add lvwEmployeesDoubleClick
            btnEmployeeEditor.Click.Add btnEmployeeEditorClick
            ShowEmployees()
    
        let btnNewEmployeeClick e = 
            let mutable strEmployeeNumber : string = ""
            let mutable strFirstName      : string = ""
            let mutable strLastName       : string = ""
            let mutable strCounty         : string = ""
            let mutable strAddress        : string = ""
            let mutable strCity           : string = ""
            let mutable strState          : string = ""
            let mutable strZIPCode        : string = ""
            let mutable strMaritalStatus  : string = ""
            let mutable iExemptions       : int    = 0
            let mutable fHourlySalary   : float  = 0.00
    
            let rndEmployeeNumber : Random = new Random()
            let xdEmployees : XmlDocument  = new XmlDocument()
            let strEmployeesFile : string = @"G:\Fun Department Store\Employees.xml"
    
            EmployeeNew.txtEmployeeNumber.Text <- sprintf "%i" (rndEmployeeNumber.Next(100000, 999999))
    
            EmployeeNew.txtFirstName.Text <- ""
            EmployeeNew.txtLastName.Text <- ""
            EmployeeNew.txtAddress.Text <- ""
            EmployeeNew.txtCity.Text <- ""
            EmployeeNew.txtCounty.Text <- ""
            EmployeeNew.txtState.Text <- ""
            EmployeeNew.txtZIPCode.Text <- ""
            EmployeeNew.cbxMaritalsStatus.Text <- ""
            EmployeeNew.txtExemptions.Text <- "0"
            EmployeeNew.txtHourlySalary.Text <- "0.00"
    
            if employeeNew.ShowDialog() = DialogResult.OK then
                strEmployeeNumber <- EmployeeNew.txtEmployeeNumber.Text
                strFirstName <- EmployeeNew.txtFirstName.Text
                strLastName <- EmployeeNew.txtLastName.Text
                strMaritalStatus <- EmployeeNew.cbxMaritalsStatus.Text
                iExemptions <- int EmployeeNew.txtExemptions.Text
                strAddress <- EmployeeNew.txtAddress.Text
                strCity <- EmployeeNew.txtCity.Text
                strCounty <- EmployeeNew.txtCounty.Text
                strState <- EmployeeNew.txtState.Text
                strZIPCode <- EmployeeNew.txtZIPCode.Text
                fHourlySalary <- float EmployeeNew.txtHourlySalary.Text
    
                if File.Exists(strEmployeesFile) = false then
                    xdEmployees.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                        "<Employees></Employees>")
                    xdEmployees.Save(strEmployeesFile)
    
                xdEmployees.Load(strEmployeesFile)
    
                let elmXML : XmlElement = xdEmployees.CreateElement("Employee")
                // Create the XML code of the child element of Employee
                let strNewEmployee = "<EmployeeNumber>" + strEmployeeNumber + "</EmployeeNumber>" +
                                     "<FirstName>" + strFirstName + "</FirstName>" +
                                     "<LastName>" + strLastName + "</LastName>" +
                                     "<Address>" + strAddress + "</Address>" +
                                     "<City>" + strCity + "</City>" +
                                     "<County>" + strCounty + "</County>" +
                                     "<State>" + strState + "</State>" +
                                     "<ZIPCode>" + strZIPCode + "</ZIPCode>" +
                                     "<MaritalStatus>" + strMaritalStatus + "</MaritalStatus>" +
                                     "<Exemptions>" + sprintf "%i" iExemptions + "</Exemptions>" +
                                     "<HourlySalary>" + sprintf "%0.02f" fHourlySalary + "</HourlySalary>"
                elmXML.InnerXml <- strNewEmployee
                // Append the new element as a child of employees
                let mutable xn =xdEmployees.DocumentElement.AppendChild elmXML
                xn <- null
    
                // Save the XML file
                xdEmployees.Save strEmployeesFile
    
                ShowEmployees()
        
        do
            btnNewEmployee.Click.Add btnNewEmployeeClick
    
        member this.EmployeesLoad e =
            ShowEmployees()
  22. Save the files

Handling Store Items

Items (such as clothing, jewelry, and accessories, etc) are the basis of the business. For our database, the three most important pieces of information about each item are the item number (which must be unique for each item), a name or short description, and a price. Other pieces of information we will consider for some items are the manufacturer, the category, and the subcategory. We will also apply a discount rate to some items.

Practical LearningPractical Learning: Creating Store Items

  1. In the Solution Explorer, right-click EmployeeNew -> Add Above -> New Item...
  2. In the middle list, click Source File and set the name to Manufacturers
  3. Click Add
  4. Change the contents of the document as follows:
    module Manufacturers
    
    open System
    open System.Drawing
    open System.Windows.Forms
    
    type Manufacturer() as this =
        inherit Form()
    
        let mutable lblManufacturer : Label = null
        let mutable txtManufacturer : TextBox = null
        let mutable btnOK : Button = null
        let mutable btnCancel : Button = null
    
        let mutable strManufacturer = ""
    
        do
            // Label: Manufacturer
            lblManufacturer <- new Label()
            lblManufacturer.AutoSize <- true
            lblManufacturer.Location <- new Point(21, 20)
            lblManufacturer.TabIndex <- 0
            lblManufacturer.Text <- "Manufacturer:"
            this.Controls.Add lblManufacturer
    
            // Text Box: Manufacturer
            txtManufacturer <- new TextBox()
            txtManufacturer.Location <- new Point(100, 17)
            txtManufacturer.Size <- new System.Drawing.Size(156, 20)
            txtManufacturer.TabIndex <- 1
            this.Controls.Add txtManufacturer
    
            // Button: OK
            btnOK <- new Button()
            btnOK.DialogResult <- DialogResult.OK
            btnOK.Location <- new Point(100, 53)
            btnOK.Size <- new System.Drawing.Size(75, 23)
            btnOK.TabIndex <- 3
            btnOK.Text <- "OK"
            this.Controls.Add btnOK
    
            // Button: Cancel
            btnCancel <- new Button()
            btnCancel.DialogResult <- DialogResult.Cancel
            btnCancel.Location <- new Point(181, 53)
            btnCancel.Size <- new System.Drawing.Size(75, 23)
            btnCancel.TabIndex <- 2
            btnCancel.Text <- "Cancel"
            this.Controls.Add btnCancel
    
            // Dialog Box: Manufacturer
            this.AcceptButton <- btnOK
            this.CancelButton <- btnCancel
            this.ClientSize <- new System.Drawing.Size(276, 92)
            this.FormBorderStyle <- FormBorderStyle.FixedDialog
            this.MaximizeBox <- false
            this.MinimizeBox <- false
            this.ShowInTaskbar <- false
            this.Text <- "FunDS - Manufacturer"
            this.StartPosition <- FormStartPosition.CenterScreen
    
        member this.Maker with get() = txtManufacturer.Text and set(value) = txtManufacturer.Text <- value
  5. In the Solution Explorer, right-click EmployeeNew -> Above -> New Item...
  6. In the middle list, click Source File and set the name to Categories
  7. Click Add
  8. Change the contents of the document as follows:
    module Categories
    
    open System
    open System.Drawing
    open System.Windows.Forms
    
    type Category() as this =
        inherit Form()
    
        let mutable lblCategory : Label   = null
        let mutable txtValue    : TextBox = null
        let mutable btnOK       : Button  = null
        let mutable btnCancel   : Button  = null
        
        do
            // Label: Category
            lblCategory <- new Label()
            lblCategory.AutoSize <- true
            lblCategory.Location <- new Point(21, 20)
            lblCategory.TabIndex <- 0
            lblCategory.Text <- "Category:"
            this.Controls.Add lblCategory
    
            // Text Box: Category
            txtValue <- new TextBox()
            txtValue.Location <- new Point(100, 17)
            txtValue.Size <- new System.Drawing.Size(156, 20)
            txtValue.TabIndex <- 1
            this.Controls.Add txtValue
    
            // Button: OK
            btnOK <- new Button()
            btnOK.DialogResult <- DialogResult.OK
            btnOK.Location <- new Point(100, 53)
            btnOK.Size <- new System.Drawing.Size(75, 23)
            btnOK.TabIndex <- 2
            btnOK.Text <- "OK"
            this.Controls.Add btnOK
    
            // Button: Cancel
            btnCancel <- new Button()
            btnCancel.DialogResult <- DialogResult.Cancel
            btnCancel.Location <- new Point(181, 53)
            btnCancel.Size <- new System.Drawing.Size(75, 23)
            btnCancel.TabIndex <- 3
            btnCancel.Text <- "Cancel"
            this.Controls.Add btnCancel
    
            // Dialog Box: Category 
            this.AcceptButton <- btnOK
            this.CancelButton <- btnCancel
            this.ClientSize <- new System.Drawing.Size(276, 93)
            this.FormBorderStyle <- FormBorderStyle.FixedDialog
            this.MaximizeBox <- false
            this.MinimizeBox <- false
            this.ShowInTaskbar <- false
            this.StartPosition <- FormStartPosition.CenterScreen
            this.Text <- "FunDS - Category"
    
        member this.txtCategory with get() = txtValue and set(value) = txtValue <- value
  9. In the Solution Explorer, right-click EmployeeNew -> Above -> New Item...
  10. In the middle list, click Source File and set the name to SubCategories
  11. Click Add
  12. Change the contents of the document as follows:
    module SubCategories
    
    open System
    open System.Drawing
    open System.Windows.Forms
    
    type SubCategory() as this =
        inherit Form()
    
        let mutable lblSubCategory : Label   = null
        let mutable txtValue       : TextBox = null
        let mutable btnOK          : Button  = null
        let mutable btnCancel      : Button  = null
    
        do
            lblSubCategory <- new Label()
            lblSubCategory.AutoSize <- true
            lblSubCategory.Location <- new Point(21, 20)
            lblSubCategory.TabIndex <- 0
            lblSubCategory.Text <- "Sub-Category:"
            this.Controls.Add lblSubCategory
    
            txtValue <- new TextBox()
            txtValue.Location <- new Point(100, 17)
            txtValue.Size <- new System.Drawing.Size(156, 20)
            txtValue.TabIndex <- 1
            this.Controls.Add txtValue
    
            btnOK <- new Button()
            btnOK.DialogResult <- DialogResult.OK
            btnOK.Location <- new System.Drawing.Point(100, 53)
            btnOK.Size <- new System.Drawing.Size(75, 23)
            btnOK.TabIndex <- 2
            btnOK.Text <- "OK"
            this.Controls.Add btnOK
    
            btnCancel <- new Button()
            btnCancel.DialogResult <- DialogResult.Cancel
            btnCancel.Location <- new System.Drawing.Point(181, 53)
            btnCancel.Size <- new System.Drawing.Size(75, 23)
            btnCancel.TabIndex <- 3
            btnCancel.Text <- "Cancel"
            this.Controls.Add btnCancel
    
            this.AcceptButton <- btnOK
            this.CancelButton <- btnCancel
            this.ClientSize <- new System.Drawing.Size(276, 93)
            this.FormBorderStyle <- FormBorderStyle.FixedDialog
            this.MaximizeBox <- false
            this.MinimizeBox <- false
            this.ShowInTaskbar <- false
            this.StartPosition <- FormStartPosition.CenterScreen
            this.Text <- "FunDS - Sub-Category"
    
        member this.txtSubCategory with get() = txtValue and set(value) = txtValue <- value
    
  13. In the Solution Explorer, right-click EmployeeNew -> Above -> New Item...
  14. In the middle list, click Source File and set the name to StoreItemNew
  15. Click Add
  16. Change the contents of the document as follows:
    module StoreItemNew
    
    open System
    open System.IO
    open System.Xml
    open System.Drawing
    open System.Windows.Forms
    
    open Categories
    open SubCategories
    open Manufacturers
    
    // Dialog Box: New Store Item
    let storeItemNew = new Form(MaximizeBox = false, MinimizeBox = false,
                                ClientSize = new System.Drawing.Size(372, 280),
                                FormBorderStyle = FormBorderStyle.FixedDialog, ShowInTaskbar = false,
                                StartPosition = FormStartPosition.CenterScreen, Text = "FunDS - New Store Item")
    
    // Item Number
    storeItemNew.Controls.Add(new Label(TabIndex = 0, AutoSize = true,
                                        Location = new Point(17, 24), Text = "Item Number:"))
    let txtItemNumber = new TextBox(Location = new Point(96, 21), Width = 94, TabIndex = 1)
    storeItemNew.Controls.Add txtItemNumber
    
    // Label: Manufacturer
    storeItemNew.Controls.Add(new Label(AutoSize = true, TabIndex = 2,
                                        Location = new Point(17, 54), Text = "Manufacturer:"))
    let cbxManufacturers = new ComboBox(Location = new Point(96, 50), Width = 200,
                                        DropDownStyle = ComboBoxStyle.DropDownList, TabIndex = 3)
    storeItemNew.Controls.Add cbxManufacturers
    
    // Button: New Manufacturer
    let btnNewManufacturer = new Button(Text = "New...", Location = new Point(302, 50),
                                        TabIndex = 21, Size = new System.Drawing.Size(50, 23))
    storeItemNew.Controls.Add btnNewManufacturer
    
    // Category
    storeItemNew.Controls.Add(new Label(AutoSize = true, Text = "Category:",
                                        Location = new Point(17, 82), TabIndex = 4))
    let cbxCategories = new ComboBox(TabIndex = 5, Location = new Point(96, 79),
                                     DropDownStyle = ComboBoxStyle.DropDownList, Width = 200)
    storeItemNew.Controls.Add cbxCategories
    
    // Button: New Category
    let btnNewCategory = new Button(Text = "New...", Location = new Point(302, 79),
                                    Size = new System.Drawing.Size(50, 23), TabIndex = 22)
    storeItemNew.Controls.Add btnNewCategory
    
    // Sub-Category
    storeItemNew.Controls.Add(new Label(AutoSize = true, Text = "Sub-Category:",
                                        Location = new Point(17, 113), TabIndex = 6))
    let cbxSubCategories = new ComboBox(Location = new Point(96, 109), Width = 200,
                                        DropDownStyle = ComboBoxStyle.DropDownList, TabIndex = 7)
    storeItemNew.Controls.Add cbxSubCategories
    
    // Button: New Sub-Category
    let btnNewSubCategory = new Button(Width = 50, TabIndex = 23,
                                       Text = "New...", Location = new Point(302, 109))
    storeItemNew.Controls.Add btnNewSubCategory
    
    // Item Name
    storeItemNew.Controls.Add(new Label(Text = "Item Name:", AutoSize = true,
                                        Location = new Point(17, 142), TabIndex = 12))
    let txtItemName = new TextBox(Width = 256, Location = new Point(96, 139), TabIndex = 13)
    storeItemNew.Controls.Add txtItemName
    
    // Item Size
    storeItemNew.Controls.Add(new Label(TabIndex = 14, AutoSize = true, Text = "Item Size:",
                                        Location = new Point(17, 172)))
    let txtItemSize = new TextBox(Location = new Point(96, 169), Width = 256, TabIndex = 15)
    storeItemNew.Controls.Add txtItemSize
    
    // Unit Price
    storeItemNew.Controls.Add(new Label(AutoSize = true, TabIndex = 16,
                                        Location = new Point(17, 201), Text = "Unit Price:"))
    let txtUnitPrice = new TextBox(Width = 94, Location = new Point(96, 198),
                                  TabIndex = 17, Text = "0.00", TextAlign = HorizontalAlignment.Right)
    storeItemNew.Controls.Add txtUnitPrice
    
    // Discount Rate
    storeItemNew.Controls.Add(new Label(AutoSize = true, Location = new Point(200, 201),
                                        Width = 78, TabIndex = 18, Text = "Discount Rate:"))
    let txtDiscountRate = new TextBox(Text = "0.00", TextAlign = HorizontalAlignment.Right,
                                      Location = new Point(284, 198), Width = 47, TabIndex = 19) 
    storeItemNew.Controls.Add txtDiscountRate
    
    // Discount Percent
    storeItemNew.Controls.Add(new Label(Text = "%", AutoSize = true,
                                        TabIndex = 20, Location = new Point(334, 201)))
    
    // Button: Submit
    let btnSubmit = new Button(Text = "Submit", Width = 75,
                               Location = new Point(113, 236), TabIndex = 25)
    storeItemNew.Controls.Add btnSubmit
    
    // Button: Reset
    let btnReset = new Button(Location = new Point(194, 236), Width = 75, TabIndex = 26, Text = "Reset")
    storeItemNew.Controls.Add btnReset
    
    // Close
    let btnClose = new Button(Location = new Point(275, 236), Width = 75, TabIndex = 24, Text = "Close")
    storeItemNew.Controls.Add btnClose
    
    let populateStoreItem() =
        let mutable item = 0
        let rndNumber : Random = new Random()
        let xdStoreItems : XmlDocument = new XmlDocument()
        let strStoreItemsFile : string = @"G:\Fun Department Store\StoreItems.xml"
    
        // Set some default values on the New Store Item dialog box before the user opens it
        // Create a random item number. The user can change it if necessary
        txtItemNumber.Text <- sprintf "%i" (rndNumber.Next(100000, 999999))
    
        cbxManufacturers.Items.Clear()
        cbxCategories.Items.Clear()
        cbxSubCategories.Items.Clear()
    
        if File.Exists(strStoreItemsFile)  then
            use fsStoreItems : FileStream = new FileStream(strStoreItemsFile, FileMode.Open, FileAccess.Read)
            xdStoreItems.Load fsStoreItems
    
            let xnlCategories : XmlNodeList = xdStoreItems.SelectNodes("/StoreItems/StoreItem/Category")
            let xnlSubCategories : XmlNodeList = xdStoreItems.SelectNodes("/StoreItems/StoreItem/SubCategory")
            let xnlManufacturers : XmlNodeList = xdStoreItems.SelectNodes("/StoreItems/StoreItem/Manufacturer")
    
            for xnManufacturer : XmlNode in xnlManufacturers do
                if not(cbxManufacturers.Items.Contains(xnManufacturer.InnerText)) && not(String.IsNullOrEmpty(xnManufacturer.InnerText)) then
                    item <- cbxManufacturers.Items.Add(xnManufacturer.InnerText)
    
            for xnCategory : XmlNode in xnlCategories do
                if not(cbxCategories.Items.Contains(xnCategory.InnerText)) && not(String.IsNullOrEmpty(xnCategory.InnerText)) then
                    item <- cbxCategories.Items.Add(xnCategory.InnerText)
    
            for xnSubCategory : XmlNode in xnlSubCategories do
                if not(cbxSubCategories.Items.Contains(xnSubCategory.InnerText)) && not(String.IsNullOrEmpty(xnSubCategory.InnerText)) then
                    item <- cbxSubCategories.Items.Add(xnSubCategory.InnerText)
    
            cbxManufacturers.Sorted <- true
            cbxCategories.Sorted <- true
            cbxSubCategories.Sorted <- true
    
            cbxManufacturers.Text <- "N/A"
            cbxCategories.Text <- "N/A"
            cbxSubCategories.Text <- "N/A"
            txtItemName.Text <- ""
            txtItemSize.Text <- ""
            txtUnitPrice.Text <- "0.00"
            txtDiscountRate.Text <- ""
    
    storeItemNew.Load.Add(fun e -> populateStoreItem())
    
    btnNewManufacturer.Click.Add(fun e ->
        let mutable item = 0
        let man = new Manufacturers.Manufacturer()
    
        // Show the New Manufacturer dialog box.
        // Find out if the user clicked OK after using the dialog box
        if man.ShowDialog() = DialogResult.OK then
            // If the user clicked OK...
            // ... if the Manufacturer text box was empty, do nothing
            if String.IsNullOrEmpty(man.Maker) then
                MessageBox.Show("You must enter a manufacturer's name.", "FunDS - Fun Department Store",
                                MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
            else
                if cbxManufacturers.Items.Contains(man.Maker) = false then
                    item <- cbxManufacturers.Items.Add(man.Maker)
                    cbxManufacturers.Text <- man.Maker)
    
    btnNewCategory.Click.Add(fun e ->
        let mutable item = 0
        let cat = new Categories.Category()
    
        if cat.ShowDialog() = DialogResult.OK then
            if String.IsNullOrEmpty(cat.txtCategory.Text) then
                MessageBox.Show("You must enter a category's name.", "FunDS - Fun Department Store",
                                MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
            else
                if cbxCategories.Items.Contains(cat.txtCategory.Text) = false then
                    item <- cbxCategories.Items.Add(cat.txtCategory.Text)
                    cbxCategories.Text <- cat.txtCategory.Text)
    
    btnNewSubCategory.Click.Add(fun e ->
        let mutable item = 0
        let sc = new SubCategories.SubCategory()
    
        if sc.ShowDialog() = DialogResult.OK then
            if String.IsNullOrEmpty(sc.txtSubCategory.Text) then
                MessageBox.Show("You must enter a sub-category's name.", "FunDS - Fun Department Store",
                                MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
            else
                if cbxSubCategories.Items.Contains(sc.txtSubCategory.Text) = false then
                    item <- cbxSubCategories.Items.Add(sc.txtSubCategory.Text)
                    cbxSubCategories.Text <- sc.txtSubCategory.Text)
     
    btnReset.Click.Add(fun e -> populateStoreItem())
    
    btnSubmit.Click.Add(fun e ->
        let xdStoreItems : XmlDocument = new XmlDocument()
        let strStoreItemsFile : string = @"G:\Fun Department Store\StoreItems.xml"
    
        if String.IsNullOrEmpty(txtItemNumber.Text) then
            MessageBox.Show("You must provide at least an item number.", "FunDS - Fun Department Store",
                            MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
        elif String.IsNullOrEmpty(txtItemName.Text) then
            MessageBox.Show("You must specify the name of the item or a (short) description.",
                            "FunDS - Fun Department Store",
                            MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
    
        if File.Exists(strStoreItemsFile) = false then
            use fsStoreItems : FileStream = new FileStream(strStoreItemsFile, FileMode.Create, FileAccess.Write)
            xdStoreItems.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                 "<StoreItems></StoreItems>")
            xdStoreItems.Save fsStoreItems
            fsStoreItems.Close()
            
        use fsStoreItems : FileStream = new FileStream(strStoreItemsFile, FileMode.Open, FileAccess.Read)
        xdStoreItems.Load fsStoreItems
        fsStoreItems.Close()
    
        use fsStoreItems : FileStream = new FileStream(strStoreItemsFile, FileMode.Create, FileAccess.Write)
        let xeStoreItem : XmlElement = xdStoreItems.CreateElement("StoreItem")
        xeStoreItem.InnerXml <- "<ItemNumber>" + txtItemNumber.Text + "</ItemNumber>" +
                                "<Manufacturer>" + cbxManufacturers.Text + "</Manufacturer>" +
                                "<Category>" + cbxCategories.Text + "</Category>" +
                                "<SubCategory>" + cbxSubCategories.Text + "</SubCategory>" +
                                "<ItemName>" + txtItemName.Text + "</ItemName>" +
                                "<ItemSize>" + txtItemSize.Text + "</ItemSize>" +
                                "<UnitPrice>" + txtUnitPrice.Text + "</UnitPrice>" +
                                "<DiscountRate>" + txtDiscountRate.Text + "</DiscountRate>"
    
        let mutable xn = xdStoreItems.DocumentElement.AppendChild(xeStoreItem)
        xdStoreItems.Save fsStoreItems
        fsStoreItems.Close()
    
        xn <- null
        populateStoreItem())
    
    btnClose.Click.Add(fun e -> storeItemNew.Close())
  17. Save the file

Editing a Store Item

Editing an item consists of changing any of its aspects. Since this is an XML-based application, you can simply open a file in a text editor and change anything. As for us, we will provide a form that can be used to enter an item number and click a button to find it. If the item is found, the employee can make any changes, and save it.

Practical LearningPractical Learning: Editing a Store Item

  1. In the Solution Explorer, right-click EmployeeNew -> Above -> New Item...
  2. In the middle list, click Source File and set the name to StoreItemEditor
  3. Click Add
  4. Change the contents of the document as follows:
    module StoreItemEditor
    
    open System
    open System.IO
    open System.Xml
    open System.Drawing
    open System.Windows.Forms
    
    // Dialog Box: New Store Item
    let storeItemEditor = new Form(FormBorderStyle = FormBorderStyle.FixedDialog,
                                   StartPosition = FormStartPosition.CenterScreen,
                                   MinimizeBox = false, MaximizeBox = false, ShowInTaskbar = false,
                                   Text = "FunDS - Edit Store Item", ClientSize = new System.Drawing.Size(372, 276))
    
    // Item Number
    storeItemEditor.Controls.Add(new Label(TabIndex = 0, Text = "Item Number:",
                                           AutoSize = true, Location = new Point(17, 24)))
    let txtItemNumber = new TextBox(Size = new System.Drawing.Size(75, 20),
                                    TabIndex = 1, Location = new Point(96, 21))
    storeItemEditor.Controls.Add txtItemNumber
    
    // Button: New Find
    let btnFind = new Button(Location = new Point(180, 20),
                             Width = 50, TabIndex = 21, Text = "Find")
    storeItemEditor.Controls.Add btnFind
    
    //  Manufacturer
    storeItemEditor.Controls.Add(new Label(TabIndex = 6, Text = "Manufacturer:",
                                           AutoSize = true, Location = new Point(17, 54)))
    let cbxManufacturers = new ComboBox(Location = new Point(96, 50), Width = 200, TabIndex = 7)
    storeItemEditor.Controls.Add cbxManufacturers
    
    // Button: New Manufacturer
    let btnNewManufacturer = new Button(Location = new Point(302, 49),
                                        Width = 50, TabIndex = 21, Text = "New...")
    storeItemEditor.Controls.Add btnNewManufacturer
    
    //  Category
    storeItemEditor.Controls.Add(new Label(TabIndex = 8, Text = "Category:",
                                           AutoSize = true, Location = new Point(17, 82)))
    let cbxCategories = new ComboBox(Location = new Point(96, 79), Width = 200, TabIndex = 9)
    storeItemEditor.Controls.Add cbxCategories
    
    // Button: New Category
    let btnNewCategory = new Button(Location = new Point(302, 77),
                                    Width = 50, TabIndex = 22, Text = "New...")
    storeItemEditor.Controls.Add btnNewCategory
    
    //  Sub-Category
    storeItemEditor.Controls.Add(new Label(AutoSize = true, Text = "Sub-Category:",
                                           Location = new Point(17, 113), TabIndex = 10))
    let cbxSubCategories = new ComboBox(Location = new Point(96, 109), Width = 200, TabIndex = 11)
    storeItemEditor.Controls.Add cbxSubCategories
    
    // Button: New Sub-Category
    let btnNewSubCategory = new Button(TabIndex = 23, Text = "New...",
                                       Location = new Point(302, 107), Width = 50)
    storeItemEditor.Controls.Add btnNewSubCategory
    
    // Item Name
    storeItemEditor.Controls.Add(new Label(Text = "Item Name:", AutoSize = true,
                                           Location = new Point(17, 142), TabIndex = 12))
    
    let txtItemName = new TextBox(Location = new Point(96, 139), Width = 256, TabIndex = 13)
    storeItemEditor.Controls.Add txtItemName
    
    //  Item Size
    storeItemEditor.Controls.Add(new Label(AutoSize = true, Text = "Item Size:",
                                           Location = new Point(17, 172), TabIndex = 14))
    let txtItemSize = new TextBox(Location = new Point(96, 169), Width = 256, TabIndex = 15)
    storeItemEditor.Controls.Add txtItemSize
    
    //  Unit Price
    storeItemEditor.Controls.Add(new Label(AutoSize = true, Text = "Unit Price:",
                                           Location = new Point(17, 201), TabIndex = 16))
    let txtUnitPrice = new TextBox(Text = "0.00", TextAlign = HorizontalAlignment.Right,
                                   Location = new Point(96, 198), Width = 94, TabIndex = 17)
    storeItemEditor.Controls.Add txtUnitPrice
    
    //  Discount Rate
    storeItemEditor.Controls.Add(new Label(AutoSize = true, Location = new Point(200, 201),
                                           Width = 78, TabIndex = 18, Text = "Discount Rate:"))
    let txtDiscountRate = new TextBox(Text = "0.00", TextAlign = HorizontalAlignment.Right,
                                      Location = new Point(284, 198), Width = 47, TabIndex = 19)
    storeItemEditor.Controls.Add txtDiscountRate
    
    //  Discount Percent
    storeItemEditor.Controls.Add(new Label(Location = new Point(334, 201),
                                           Text = "%", AutoSize = true, TabIndex = 20))
    
    // Button: Update
    let btnUpdate = new Button(Location = new Point(196, 231), Width = 75, TabIndex = 25, Text = "Update")
    storeItemEditor.Controls.Add btnUpdate
    
    let populateStoreItem() =
        let mutable i = 0
        let xdStoreItems : XmlDocument = new XmlDocument()
        let strStoreItemsFile : string = @"G:\Fun Department Store\StoreItems.xml"
    
        cbxManufacturers.Items.Clear()
        cbxCategories.Items.Clear()
        cbxSubCategories.Items.Clear()
    
        if File.Exists(strStoreItemsFile) then
            use fsStoreItems : FileStream = new FileStream(strStoreItemsFile, FileMode.Open, FileAccess.Read)
            xdStoreItems.Load fsStoreItems
    
            let xnlCategories : XmlNodeList = xdStoreItems.SelectNodes("/StoreItems/StoreItem/Category")
            let xnlSubCategories : XmlNodeList = xdStoreItems.SelectNodes("/StoreItems/StoreItem/SubCategory")
            let xnlManufacturers : XmlNodeList = xdStoreItems.SelectNodes("/StoreItems/StoreItem/Manufacturer")
    
            for xnManufacturer : XmlNode in xnlManufacturers do
                if cbxManufacturers.Items.Contains(xnManufacturer.InnerText) = false then
                    i <- cbxManufacturers.Items.Add(xnManufacturer.InnerText)
    
            for xnCategory : XmlNode in xnlCategories do
                if cbxCategories.Items.Contains(xnCategory.InnerText) = false then
                    i <- cbxCategories.Items.Add(xnCategory.InnerText)
    
    
            for xnSubCategory : XmlNode in xnlSubCategories do
                if cbxSubCategories.Items.Contains(xnSubCategory.InnerText) = false then
                    i <- cbxSubCategories.Items.Add(xnSubCategory.InnerText)
    
            cbxManufacturers.Sorted <- true
            cbxCategories.Sorted <- true
            cbxSubCategories.Sorted <- true
    
            cbxManufacturers.Text <- "N/A"
            cbxCategories.Text <- "N/A"
            cbxSubCategories.Text <- "N/A"
            txtItemName.Text <- ""
            txtItemSize.Text <- ""
            txtUnitPrice.Text <- "0.00"
            txtDiscountRate.Text <- "0.00"
    
    storeItemEditor.Load.Add(fun e -> populateStoreItem())
    
    btnNewManufacturer.Click.Add(fun e ->
        let mutable item = 0
        let man = new Manufacturers.Manufacturer()
    
        // Show the New Manufacturer dialog box.
        // Find out if the user clicked OK after using the dialog box
        if man.ShowDialog() = DialogResult.OK then
            // If the user clicked OK...
            // ... if the Manufacturer text box was empty, do nothing
            if String.IsNullOrEmpty(man.Maker) then
                MessageBox.Show("You must enter a manufacturer's name.", "FunDS - Fun Department Store",
                                MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
            else
                if cbxManufacturers.Items.Contains(man.Maker) = false then
                    item <- cbxManufacturers.Items.Add(man.Maker)
                    cbxManufacturers.Text <- man.Maker)
    
    btnNewCategory.Click.Add(fun e ->
        let mutable item = 0
        let cat = new Categories.Category()
    
        if cat.ShowDialog() = DialogResult.OK then
            if String.IsNullOrEmpty(cat.txtCategory.Text) then
                MessageBox.Show("You must enter a category's name.", "FunDS - Fun Department Store",
                                MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
            else
                if cbxCategories.Items.Contains(cat.txtCategory.Text) = false then
                    item <- cbxCategories.Items.Add(cat.txtCategory.Text)
                    cbxCategories.Text <- cat.txtCategory.Text)
    
    btnNewSubCategory.Click.Add(fun e ->
        let mutable item = 0
        let sc = new SubCategories.SubCategory()
    
        if sc.ShowDialog() = DialogResult.OK then
            if String.IsNullOrEmpty(sc.txtSubCategory.Text) then
                MessageBox.Show("You must enter a sub-category's name.", "FunDS - Fun Department Store",
                                MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
            else
                if cbxSubCategories.Items.Contains(sc.txtSubCategory.Text) = false then
                    item <- cbxSubCategories.Items.Add(sc.txtSubCategory.Text)
                    cbxSubCategories.Text <- sc.txtSubCategory.Text)
    
    btnFind.Click.Add(fun e ->
        let mutable itemFound : bool = false
        let xdStoreItems : XmlDocument = new XmlDocument()
        let strStoreItemsFile : string = @"G:\Fun Department Store\StoreItems.xml"
    
        if String.IsNullOrEmpty(txtItemNumber.Text) then
            MessageBox.Show("You must provide an item number.", "FunDS - Fun Department Store",
                            MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
         
        else
            if File.Exists(strStoreItemsFile) then
                use fsStoreItems : FileStream = new FileStream(strStoreItemsFile, FileMode.Open, FileAccess.Read)
                xdStoreItems.Load fsStoreItems
    
                let xnlStoreItems : XmlNodeList = xdStoreItems.GetElementsByTagName("ItemNumber")
    
                for xnStoreItem in xnlStoreItems do
                    if xnStoreItem.InnerText = txtItemNumber.Text then
                        itemFound <- true
                        cbxManufacturers.Text <- xnStoreItem.NextSibling.InnerText
                        cbxCategories.Text    <- xnStoreItem.NextSibling.NextSibling.InnerText
                        cbxSubCategories.Text <- xnStoreItem.NextSibling.NextSibling.NextSibling.InnerText
                        txtItemName.Text      <- xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
                        txtItemSize.Text      <- xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
                        txtUnitPrice.Text     <- xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
                        txtDiscountRate.Text  <- xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
    
                if itemFound = false then
                    MessageBox.Show("There is no item with that number.", "FunDS - Fun Department Store",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
                fsStoreItems.Close())
    
    btnUpdate.Click.Add(fun e ->
        let mutable itemFound = false
        let xdStoreItems = new XmlDocument()
        let strStoreItemsFile = @"G:\Fun Department Store\StoreItems.xml"
    
        if String.IsNullOrEmpty(txtItemNumber.Text) then
            MessageBox.Show("You must provide an item number.", "FunDS - Fun Department Store",
                            MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
        //else
        if File.Exists(strStoreItemsFile) then
                //use fsStoreItems = new FileStream(strStoreItemsFile, FileMode.Open, FileAccess.Read)
                xdStoreItems.Load strStoreItemsFile // fsStoreItems
                //fsStoreItems.Close()
    
                let xnlStoreItems = xdStoreItems.GetElementsByTagName("ItemNumber")
    
                for xnStoreItem in xnlStoreItems do
                    if xnStoreItem.InnerText = txtItemNumber.Text then
                        itemFound <- true
                        xnStoreItem.ParentNode.InnerXml <- "<ItemNumber>" + txtItemNumber.Text + "</ItemNumber>" +
                                                           "<Manufacturer>" + cbxManufacturers.Text + "</Manufacturer>" +
                                                           "<Category>" + cbxCategories.Text + "</Category>" +
                                                           "<SubCategory>" + cbxSubCategories.Text + "</SubCategory>" +
                                                           "<ItemName>" + txtItemName.Text + "</ItemName>" +
                                                           "<ItemSize>" + txtItemSize.Text + "</ItemSize>" +
                                                           "<UnitPrice>" + txtUnitPrice.Text + "</UnitPrice>" +
                                                           "<DiscountRate>" + txtDiscountRate.Text + "</DiscountRate>"
    
                if itemFound = true then
                    // use fsStoreItems = new FileStream(strStoreItemsFile, FileMode.Create, FileAccess.Write)
                    xdStoreItems.Save strStoreItemsFile // fsStoreItems
                    MessageBox.Show("The store item has been updated.", "FunDS - Fun Department Store",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
                    //fsStoreItems.Close()
    
        populateStoreItem())
    
    // Button: Close
    let btnClose = new Button(Location = new Point(275, 231), Width = 75, TabIndex = 24, Text = "Close")
    btnClose.Click.Add(fun e -> storeItemEditor.Close())
    storeItemEditor.Controls.Add btnClose
  5. Save the file

Deleting a Store Item

To make sure we cover most aspects of data maintenance are covered, we will give the company the ability to delete an item from the inventory.

Practical LearningPractical Learning: Deleting an Item

  1. In the Solution Explorer, right-click EmployeeNew -> Above -> New Item...
  2. In the middle list, click Source File and set the name to StoreItemDelete
  3. Click Add
  4. Change the contents of the document as follows:
    module StoreItemDelete
    
    open System
    open System.IO
    open System.Xml
    open System.Drawing
    open System.Windows.Forms
    
    // Dialog Box: New Store Item
    let itemDeletion = new Form(MaximizeBox = false, MinimizeBox = false, ShowInTaskbar = false,
                                ClientSize = new Size(372, 276), FormBorderStyle = FormBorderStyle.FixedDialog,
                                StartPosition = FormStartPosition.CenterScreen, Text = "FunDS - Delete Store Item")
    
    // Item Number
    itemDeletion.Controls.Add(new Label(AutoSize = true, Location = new Point(17, 24), TabIndex = 2, Text = "Item Number:"))
    let txtItemNumber = new TextBox(Location = new Point(96, 21), Width = 75, TabIndex = 3)
    itemDeletion.Controls.Add txtItemNumber
    
    // Button: New Find
    let btnFind = new Button(Location = new Point(180, 20), Width = 50, TabIndex = 21, Text = "Find")
    itemDeletion.Controls.Add btnFind
    
    //  Manufacturer
    itemDeletion.Controls.Add(new Label(AutoSize = true, Location = new Point(17, 54), TabIndex = 6, Text = "Manufacturer:"))
    let cbxManufacturers = new ComboBox(Location = new Point(96, 50), Width = 200, TabIndex = 7)
    itemDeletion.Controls.Add cbxManufacturers
    
    // Button: New Manufacturer
    let btnNewManufacturer = new Button(Location = new Point(302, 49), Width = 50, TabIndex = 21, Text = "New...")
    itemDeletion.Controls.Add btnNewManufacturer
    
    //  Category
    itemDeletion.Controls.Add(new Label(AutoSize = true, Location = new Point(17, 82), TabIndex = 8, Text = "Category:"))
    let cbxCategories = new ComboBox(Location = new Point(96, 79), Width = 200, TabIndex = 9)
    itemDeletion.Controls.Add cbxCategories
    
    // Button: New Category
    let btnNewCategory = new Button(Location = new Point(302, 77), Width = 50, TabIndex = 22, Text = "New...")
    itemDeletion.Controls.Add btnNewCategory
    
    //  Sub-Category
    itemDeletion.Controls.Add(new Label(AutoSize = true, Location = new Point(17, 113), TabIndex = 10, Text = "Sub-Category:"))
    let cbxSubCategories = new ComboBox(Location = new Point(96, 109), Width = 200, TabIndex = 11)
    itemDeletion.Controls.Add cbxSubCategories
    
    // Button: New Sub-Category
    let btnNewSubCategory = new Button(Location = new Point(302, 107), Width = 50, TabIndex = 23, Text = "New...")
    itemDeletion.Controls.Add btnNewSubCategory
    
    //  Item Name
    itemDeletion.Controls.Add(new Label(AutoSize = true, Location = new Point(17, 142), TabIndex = 12, Text = "Item Name:"))
    let txtItemName = new TextBox(Location = new Point(96, 139), Width = 256, TabIndex = 13)
    itemDeletion.Controls.Add txtItemName
    
    //  Item Size
    itemDeletion.Controls.Add(new Label(AutoSize = true, Location = new Point(17, 172), TabIndex = 14, Text = "Item Size:"))
    let txtItemSize = new TextBox(Location = new Point(96, 169), Width = 256, TabIndex = 15)
    itemDeletion.Controls.Add txtItemSize
    
    //  Unit Price
    itemDeletion.Controls.Add(new Label(AutoSize = true, Location = new Point(17, 201), TabIndex = 16, Text = "Unit Price:"))
    let txtUnitPrice = new TextBox(Location = new Point(96, 198), Width = 94,
                                   Text = "0.00", TextAlign = HorizontalAlignment.Right)
    itemDeletion.Controls.Add txtUnitPrice
    
    //  Discount Rate
    itemDeletion.Controls.Add(new Label(AutoSize = true, Location = new Point(200, 201), Width = 78, Text = "Discount Rate:"))
    let txtDiscountRate = new TextBox(Location = new Point(284, 198), Width = 47,
                                      Text = "0.00", TextAlign = HorizontalAlignment.Right)
    itemDeletion.Controls.Add txtDiscountRate
    
    //  Discount Percent
    itemDeletion.Controls.Add(new Label(AutoSize = true, Location = new Point(334, 201), TabIndex = 20, Text = "%"))
    
    // Button: Delete
    let btnDelete = new Button(Location = new Point(196, 231), Width = 75, TabIndex = 25, Text = "Delete")
    itemDeletion.Controls.Add btnDelete
    
    let populateStoreItem() =
        let mutable i = 0
        let xdStoreItems : XmlDocument = new XmlDocument()
        let strStoreItemsFile : string = @"G:\Fun Department Store\StoreItems.xml"
    
        cbxManufacturers.Items.Clear()
        cbxCategories.Items.Clear()
        cbxSubCategories.Items.Clear()
    
        if File.Exists(strStoreItemsFile) then
            use fsStoreItems : FileStream = new FileStream(strStoreItemsFile, FileMode.Open, FileAccess.Read)
            xdStoreItems.Load fsStoreItems
    
            let xnlCategories    : XmlNodeList = xdStoreItems.SelectNodes("/StoreItems/StoreItem/Category")
            let xnlSubCategories : XmlNodeList = xdStoreItems.SelectNodes("/StoreItems/StoreItem/SubCategory")
            let xnlManufacturers : XmlNodeList = xdStoreItems.SelectNodes("/StoreItems/StoreItem/Manufacturer")
    
            for xnManufacturer : XmlNode in xnlManufacturers do
                if not (cbxManufacturers.Items.Contains(xnManufacturer.InnerText)) then
                    i <- cbxManufacturers.Items.Add(xnManufacturer.InnerText)
    
            for xnCategory : XmlNode in xnlCategories do
                if not (cbxCategories.Items.Contains(xnCategory.InnerText)) then
                    i <- cbxCategories.Items.Add(xnCategory.InnerText)
            
            for xnSubCategory : XmlNode in xnlSubCategories do
                if not (cbxSubCategories.Items.Contains(xnSubCategory.InnerText)) then
                    i <- cbxSubCategories.Items.Add(xnSubCategory.InnerText)
    
            cbxManufacturers.Sorted <- true
            cbxCategories.Sorted    <- true
            cbxSubCategories.Sorted <- true
    
            cbxManufacturers.Text <- "N/A"
            cbxCategories.Text <- "N/A"
            cbxSubCategories.Text <- "N/A"
            txtItemName.Text <- ""
            txtItemSize.Text <- ""
            txtUnitPrice.Text <- "0.00"
            txtDiscountRate.Text <- "0.00"
    
            fsStoreItems.Close()
    
    itemDeletion.Load.Add(fun e -> populateStoreItem())
    
    btnNewManufacturer.Click.Add(fun e ->
        let mutable item = 0
        let man = new Manufacturers.Manufacturer()
    
        // Show the New Manufacturer dialog box.
        // Find out if the user clicked OK after using the dialog box
        if man.ShowDialog() = DialogResult.OK then
            // If the user clicked OK...
            // ... if the Manufacturer text box was empty, do nothing
            if String.IsNullOrEmpty(man.Maker) then
                MessageBox.Show("You must enter a manufacturer's name.", "FunDS - Fun Department Store",
                                MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
            else
                if cbxManufacturers.Items.Contains(man.Maker) = false then
                    item <- cbxManufacturers.Items.Add(man.Maker)
                    cbxManufacturers.Text <- man.Maker)
    
    btnNewCategory.Click.Add(fun e ->
        let mutable item = 0
        let cat = new Categories.Category()
    
        if cat.ShowDialog() = DialogResult.OK then
            if String.IsNullOrEmpty(cat.txtCategory.Text) then
                MessageBox.Show("You must enter a category's name.", "FunDS - Fun Department Store",
                                MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
            else
                if cbxCategories.Items.Contains(cat.txtCategory.Text) = false then
                    item <- cbxCategories.Items.Add(cat.txtCategory.Text)
                    cbxCategories.Text <- cat.txtCategory.Text)
    
    btnNewSubCategory.Click.Add(fun e ->
        let mutable item = 0
        let sc = new SubCategories.SubCategory()
    
        if sc.ShowDialog() = DialogResult.OK then
            if String.IsNullOrEmpty(sc.txtSubCategory.Text) then
                MessageBox.Show("You must enter a sub-category's name.", "FunDS - Fun Department Store",
                                MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
            else
                if cbxSubCategories.Items.Contains(sc.txtSubCategory.Text) = false then
                    item <- cbxSubCategories.Items.Add(sc.txtSubCategory.Text)
                    cbxSubCategories.Text <- sc.txtSubCategory.Text)
    
    btnFind.Click.Add(fun e ->
        let mutable itemFound : bool = false
        let xdStoreItems : XmlDocument = new XmlDocument()
        let strStoreItemsFile : string = @"G:\Fun Department Store\StoreItems.xml"
    
        if String.IsNullOrEmpty(txtItemNumber.Text) then
            MessageBox.Show("You must provide an item number.", "FunDS - Fun Department Store",
                            MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
         
        else
            if File.Exists(strStoreItemsFile) then
                use fsStoreItems : FileStream = new FileStream(strStoreItemsFile, FileMode.Open, FileAccess.Read)
                xdStoreItems.Load fsStoreItems
    
                let xnlStoreItems : XmlNodeList = xdStoreItems.GetElementsByTagName("ItemNumber")
    
                for xnStoreItem in xnlStoreItems do
                    if xnStoreItem.InnerText = txtItemNumber.Text then
                        itemFound <- true
                        cbxManufacturers.Text <- xnStoreItem.NextSibling.InnerText
                        cbxCategories.Text    <- xnStoreItem.NextSibling.NextSibling.InnerText
                        cbxSubCategories.Text <- xnStoreItem.NextSibling.NextSibling.NextSibling.InnerText
                        txtItemName.Text      <- xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
                        txtItemSize.Text      <- xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
                        txtUnitPrice.Text     <- xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
                        txtDiscountRate.Text  <- xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
    
                if itemFound = false then
                    MessageBox.Show("There is no item with that number.", "FunDS - Fun Department Store",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
                fsStoreItems.Close())
    
    btnDelete.Click.Add(fun e ->
        let mutable itemFound = false
        let xdStoreItems = new XmlDocument()
        let strStoreItemsFile = @"G:\Fun Department Store\StoreItems.xml"
    
        if String.IsNullOrEmpty(txtItemNumber.Text) then
            MessageBox.Show("You must provide an item number.", "FunDS - Fun Department Store",
                            MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
        else
            if File.Exists(strStoreItemsFile) then
                use fsStoreItems = new FileStream(strStoreItemsFile, FileMode.Open, FileAccess.Read)
                xdStoreItems.Load fsStoreItems
    
                let xnlStoreItems = xdStoreItems.GetElementsByTagName("ItemNumber")
                
                for xnStoreItem in xnlStoreItems do
                    if xnStoreItem.InnerText = txtItemNumber.Text then
                        itemFound <- true
                        let mutable xn = xdStoreItems.DocumentElement.RemoveChild(xnStoreItem.ParentNode)
                        xn <- null
                fsStoreItems.Close()
    
                if itemFound = true then
                    use fsStoreItems = new FileStream(strStoreItemsFile, FileMode.Create, FileAccess.Write)
                    xdStoreItems.Save fsStoreItems
                    MessageBox.Show("The store item has been deleted.", "FunDS - Fun Department Store",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
                    fsStoreItems.Close()
    
        populateStoreItem())
    
    // Button: Close
    let btnClose = new Button(Location = new Point(275, 231), Width = 75, TabIndex = 24, Text = "Close")
    btnClose.Click.Add(fun e -> itemDeletion.Close())
    itemDeletion.Controls.Add btnClose
  5. In the Solution Explorer, right-click EmployeeNew -> Above -> New Item...
  6. In the middle list, click Source File and set the name to Inventory
  7. Change the contents of the document as follows:
    module StoreItems
    
    open System
    open System.IO
    open System.Xml
    open System.Drawing
    open System.Windows.Forms
    
    open Categories
    open SubCategories
    open Manufacturers
    
    type StoreItems() as this =
        inherit Form()
    
        let mutable colStoreItemID     : ColumnHeader = null
        let mutable colItemNumber      : ColumnHeader = null
        let mutable colManufacturer    : ColumnHeader = null
        let mutable colCategory        : ColumnHeader = null
        let mutable colSubCategory     : ColumnHeader = null
        let mutable colItemName        : ColumnHeader = null
        let mutable colItemSize        : ColumnHeader = null
        let mutable colUnitPrice       : ColumnHeader = null
        let mutable colDiscountRate    : ColumnHeader = null
        let mutable colDiscountAmount  : ColumnHeader = null
        let mutable colMarkedPrice     : ColumnHeader = null
        let mutable lvwStoreItems      : ListView     = null
        let mutable lblNumberOfItems   : Label        = null
        let mutable txtNumberOfItems   : TextBox      = null
        let mutable btnNewStoreItem    : Button       = null
        let mutable btnEditStoreItem   : Button       = null
        let mutable btnDeleteStoreItem : Button       = null
        let mutable btnClose           : Button       = null
    
        let showStoreItems() =
            let mutable itemName : string = ""
            let mutable itemSize = ""
            let mutable strDiscountRate = ""
            let mutable itemNumber = ""
            let mutable manufacturer = ""
            let mutable category = ""
            let mutable subCategory = ""
            let mutable unitPrice = 0.00
            let mutable discountRate = 0.00
            let mutable discountAmount = 0.00
            let mutable markedPrice = 0.00
            let xdStoreItems : XmlDocument = new XmlDocument()
            let strStoreItemsFile : string = @"G:\Fun Department Store\StoreItems.xml"
    
            if File.Exists(strStoreItemsFile) then
                let mutable lvi = null
                lvwStoreItems.Items.Clear()
    
                use fsStoreItems : FileStream = new FileStream(strStoreItemsFile, FileMode.Open, FileAccess.Read)
                xdStoreItems.Load fsStoreItems
    
                let xnlStoreItems : XmlNodeList = xdStoreItems.GetElementsByTagName("ItemNumber")
    
                let mutable i : int = 1
    
                for xnStoreItem : XmlNode in xnlStoreItems do
                    itemNumber      <- xnStoreItem.InnerText
                    manufacturer    <- xnStoreItem.NextSibling.InnerText
                    category        <- xnStoreItem.NextSibling.NextSibling.InnerText
                    subCategory     <- xnStoreItem.NextSibling.NextSibling.NextSibling.InnerText
                    itemName        <- xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
                    itemSize        <- xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
                    unitPrice       <- float xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
                    strDiscountRate <- xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
    
                    if String.IsNullOrEmpty(strDiscountRate) || (float strDiscountRate) <= 0.00 then
                        discountRate   <- 0.00
                        discountAmount <- 0.00
                        markedPrice    <- unitPrice
                    else
                        discountRate <- (float strDiscountRate) / 100.00
                        discountAmount <- unitPrice * discountRate
                        markedPrice <- unitPrice - discountAmount
    
                    let lviStoreItem : ListViewItem = new ListViewItem(i.ToString())
                    lvi <- lviStoreItem.SubItems.Add(itemNumber)   // Item Number
                    lvi <- lviStoreItem.SubItems.Add(manufacturer) // Manufacturer
                    lvi <- lviStoreItem.SubItems.Add(category)     // Category
                    lvi <- lviStoreItem.SubItems.Add(subCategory)  // Sub-Category
                    lvi <- lviStoreItem.SubItems.Add(itemName)     // Item Name
                    lvi <- lviStoreItem.SubItems.Add(itemSize)     // Item Size
                    lvi <- lviStoreItem.SubItems.Add(unitPrice.ToString("F"))
    
                    if discountRate = 0.00 then
                        lvi <- lviStoreItem.SubItems.Add("") // Discount Rate
                        lvi <- lviStoreItem.SubItems.Add("") // Discount Amount
                        lvi <- lviStoreItem.SubItems.Add(sprintf "%0.02f" unitPrice) // Marked Price
                    else
                        lvi <- lviStoreItem.SubItems.Add(sprintf "%0.02f%c" (discountRate * 100.00) '%')
                        lvi <- lviStoreItem.SubItems.Add(sprintf "%0.02f" discountAmount)
                        lvi <- lviStoreItem.SubItems.Add(sprintf "%0.02f" markedPrice) // Marked Price
                    lvi <- null
                    lvwStoreItems.Items.Add(lviStoreItem) |> ignore
                    i <- i + 1
    
                txtNumberOfItems.Text <- sprintf "%i" (xnlStoreItems.Count)
                fsStoreItems.Close()
    
        let InitializeComponent() =
            // Column: umn: Store Item ID
            colStoreItemID <- new ColumnHeader()
            colStoreItemID.Text <- "Item ID"
            colStoreItemID.Width <- 50
    
            // Column: umn: Item Number
            colItemNumber <- new ColumnHeader()
            colItemNumber.Text <- "Item #"
            colItemNumber.TextAlign <- HorizontalAlignment.Center
    
            // Column: umn: Manufacturer
            colManufacturer <- new ColumnHeader()
            colManufacturer.Text <- "Manufacturer"
            colManufacturer.Width <- 130
    
            // Column: umn: Category
            colCategory <- new ColumnHeader()
            colCategory.Text <- "Category"
            colCategory.Width <- 70
    
            // Column: umn: Sub-Category
            colSubCategory <- new ColumnHeader()
            colSubCategory.Text <- "Sub-Category"
            colSubCategory.Width <- 80
    
            // Column: umn: Item Name
            colItemName <- new ColumnHeader()
            colItemName.Text <- "Item Name"
            colItemName.Width <- 300
    
            // Column: umn: Item Size
            colItemSize <- new ColumnHeader()
            colItemSize.Text <- "Size"
            colItemSize.Width <- 80
    
            // Column: umn: Unit Price
            colUnitPrice <- new ColumnHeader()
            colUnitPrice.Text <- "Unit Price"
            colUnitPrice.TextAlign <- HorizontalAlignment.Right
    
            // Column: umn: Discount Rate
            colDiscountRate <- new ColumnHeader()
            colDiscountRate.Text <- "Disc Rate"
            colDiscountRate.TextAlign <- HorizontalAlignment.Right
            colDiscountRate.Width <- 60
    
            // Column: umn: Discount Amount
            colDiscountAmount <- new ColumnHeader()
            colDiscountAmount.Text <- "Disc Amt"
            colDiscountAmount.TextAlign <- HorizontalAlignment.Right
    
            // Column: umn: Marked Price
            colMarkedPrice <- new ColumnHeader()
            colMarkedPrice.Text <- "Marked Price"
            colMarkedPrice.TextAlign <- HorizontalAlignment.Right
            colMarkedPrice.Width <- 75
    
            lvwStoreItems <- new ListView()
            lvwStoreItems.Anchor <- AnchorStyles.Top ||| AnchorStyles.Bottom ||| AnchorStyles.Left ||| AnchorStyles.Right
            lvwStoreItems.Columns.AddRange [| colStoreItemID; colItemNumber; colManufacturer;
                                              colCategory; colSubCategory; colItemName; colItemSize;
                                              colUnitPrice; colDiscountRate; colDiscountAmount; colMarkedPrice |]
            lvwStoreItems.FullRowSelect <- true
            lvwStoreItems.GridLines <- true
            lvwStoreItems.Location <- new Point(15, 15)
            lvwStoreItems.Size <- new System.Drawing.Size(1050, 340)
            lvwStoreItems.View <- View.Details
    
            lblNumberOfItems <- new Label()
            lblNumberOfItems.Anchor <- AnchorStyles.Bottom ||| AnchorStyles.Left
            lblNumberOfItems.AutoSize <- true
            lblNumberOfItems.Location <- new Point(15, 370)
            lblNumberOfItems.Text <- "Number of Items:"
    
            // Text Box: Number of Items
            txtNumberOfItems <- new TextBox()
            txtNumberOfItems.Anchor <- AnchorStyles.Bottom ||| AnchorStyles.Left
            txtNumberOfItems.Location <- new Point(111, 368)
            txtNumberOfItems.Size <- new System.Drawing.Size(60, 20)
            txtNumberOfItems.TextAlign <- HorizontalAlignment.Right
    
            btnNewStoreItem <- new Button()
            btnNewStoreItem.Anchor <- AnchorStyles.Bottom ||| AnchorStyles.Right
            btnNewStoreItem.Location <- new Point(530, 366)
            btnNewStoreItem.Size <- new System.Drawing.Size(125, 32)
            btnNewStoreItem.Text <- "New Store Item ..."
            btnNewStoreItem.Click.Add(fun e ->
                StoreItemNew.storeItemNew.ShowDialog() |> ignore
                showStoreItems())
    
            // Button: Edit Item
            btnEditStoreItem <- new Button()
            btnEditStoreItem.Location <- new Point(659, 366)
            btnEditStoreItem.Size <- new System.Drawing.Size(125, 32)
            btnEditStoreItem.Text <- "Edit Store Item..."
            btnEditStoreItem.Anchor <- AnchorStyles.Bottom ||| AnchorStyles.Right
            btnEditStoreItem.Click.Add(fun e ->
                StoreItemEditor.storeItemEditor.ShowDialog() |> ignore
                showStoreItems())
    
            // Button: Remove Item
            btnDeleteStoreItem <- new Button()
            btnDeleteStoreItem.Location <- new Point(792, 366)
            btnDeleteStoreItem.Size <- new System.Drawing.Size(125, 32)
            btnDeleteStoreItem.Text <- "Delete Store Item..."
            btnDeleteStoreItem.Anchor <- AnchorStyles.Bottom ||| AnchorStyles.Right
            btnDeleteStoreItem.Click.Add(fun e ->
                StoreItemDelete.itemDeletion.ShowDialog() |> ignore
                showStoreItems())
    
            btnClose <- new Button()
            btnClose.Location <- new Point(922, 366)
            btnClose.Size <- new System.Drawing.Size(125, 32)
            btnClose.Text <- "Close"
            btnClose.Anchor <- AnchorStyles.Bottom ||| AnchorStyles.Right
            btnClose.Click.Add(fun e -> this.Close())
    
            this.ClientSize <- new System.Drawing.Size(1080, 410)
    
            this.Controls.Add(txtNumberOfItems)
            this.Controls.Add(lblNumberOfItems)
            this.Controls.Add(btnNewStoreItem)
            this.Controls.Add(btnEditStoreItem)
            this.Controls.Add(btnDeleteStoreItem)
            this.Controls.Add(btnClose)
            this.Controls.Add(lvwStoreItems)
    
            this.StartPosition <- FormStartPosition.CenterScreen
            this.Text <- "Fun Department Store - Store Items"
    
        do
            InitializeComponent()
            showStoreItems()
  8. Save the file
 
   
 

The Point of Sale

A poinit of sale is the workstation where customers purchases are handled. Point of sales used to be a big issue. You had to purchase special machines and have a special setup. Although you still need setup, you can build the whole thing yourself (but we will not discuss all of that this time).

In our application, when a customer brings one or more items to check out, the cashier (or employee) will enter each item number in a text box and press enter. This will display information about the item, including the discount if any. The employee will do this for all items brought by the customer. The employee will also have the ability to remove an item. When all items have been entered, the employee can save the order and start another order or purchase.

Practical LearningPractical Learning: Creating a Point of Sale Tool

  1. In the Solution Explorer, right-click Program.fs -> Add Above -> New Item...
  2. In the middle list, click Source File and set the name to PointOfSale
  3. Click Add
  4. Change the contents of the document as follows:
    module PointOfSale
    
    open System
    open System.IO
    open System.Xml
    open System.Drawing
    open System.Windows.Forms
    
    let shoppingSession = new Form(ClientSize = new System.Drawing.Size(1454, 611),
                                   MaximizeBox = false, StartPosition = FormStartPosition.CenterScreen,
                                   MinimizeBox = false, Text = "Fun Department Store - New Shopping Session")
    
    // Item Number to Add
    let lblItemToAdd = new Label(AutoSize = true, Location = new Point(16, 22), TabIndex = 2, Text = "Item # to Add:")
    lblItemToAdd.Font <- new System.Drawing.Font("Georgia", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
    shoppingSession.Controls.Add lblItemToAdd
    let txtItemNumber = new TextBox(Location = new Point(235, 18), Size = new System.Drawing.Size(155, 41), TabIndex = 3,
                                    Font = new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy))
    shoppingSession.Controls.Add txtItemNumber
    
    // Receipt Number
    shoppingSession.Controls.Add(new Label(AutoSize = true, Location = new Point(1081, 22), Text = "Receipt #:",
                                           Font = new System.Drawing.Font("Georgia", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)))
    
    let txtReceiptNumber = new TextBox(Location = new Point(1260, 18), Text = "000000", Size = new System.Drawing.Size(105, 41),
                                       Font = new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy))
    shoppingSession.Controls.Add txtReceiptNumber
    
    // Columns
    let colItemNumber = new ColumnHeader(Text = "Item #", Width = 100)
    let colItemName = new ColumnHeader(Text = "Item Name/Description", Width = 610)
    let colItemSize = new ColumnHeader(Text = "Size", Width = 150)
    let colUnitPrice = new ColumnHeader(Text = "Unit Price", TextAlign = HorizontalAlignment.Right, Width = 140)
    let colDiscountRate = new ColumnHeader(Text = "Dscnt Rt", TextAlign = HorizontalAlignment.Right, Width = 120)
    let colDiscountAmount = new ColumnHeader(Text = "Dscnt Amt", TextAlign = HorizontalAlignment.Right, Width = 140)
    let colSalePrice = new ColumnHeader(Text = "Sale Price", TextAlign = HorizontalAlignment.Right, Width = 130)
    
    // List View: Selected Items
    let lvwSoldItems = new ListView(FullRowSelect = true, GridLines = true, Location = new Point(16, 71), Size = new System.Drawing.Size(1424, 321), View = View.Details)
    lvwSoldItems.Columns.AddRange [| colItemNumber; colItemName; colItemSize; colUnitPrice;
                                     colDiscountRate; colDiscountAmount; colSalePrice |]
    lvwSoldItems.Font <- new System.Drawing.Font("Times New Roman", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
    shoppingSession.Controls.Add lvwSoldItems
     
     // Date/Time Picker: Sale Date
    let dtpSaleDate = new DateTimePicker(Location = new Point(16, 469),
                                         Size = new System.Drawing.Size(402, 39),
                                         Font = new System.Drawing.Font("Times New Roman", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy))
    shoppingSession.Controls.Add dtpSaleDate
    
    // Label: Sale Time
    let lblSaleTime = new Label(Location = new Point(429, 469), Text = "Sale Time", Size = new System.Drawing.Size(177, 39))
    lblSaleTime.Font <- new System.Drawing.Font("Times New Roman", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
    shoppingSession.Controls.Add lblSaleTime
    
    // Amount Tendered
    shoppingSession.Controls.Add(new Label(AutoSize = true, Location = new Point(1089, 449), Text = "Tendered:", TabIndex = 4,
                                           Font = new System.Drawing.Font("Georgia", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)))
    let txtAmountTendered = new TextBox(Text = "0.00", TextAlign = HorizontalAlignment.Right, TabIndex = 5,
                                        Location = new Point(1278, 445), Size = new System.Drawing.Size(130, 41),
                                        Font = new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy))
    shoppingSession.Controls.Add txtAmountTendered
    
    // Item Number to Remove
    shoppingSession.Controls.Add(new Label(AutoSize = true, Location = new Point(16, 416), Text = "Item # to Remove:",
                                           Font = new System.Drawing.Font("Georgia", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)))
    let txtItemNumberRemove = new TextBox(Location = new Point(290, 412), Size = new System.Drawing.Size(155, 41))
    txtItemNumberRemove.Font <- new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
    shoppingSession.Controls.Add txtItemNumberRemove
    
    // Button: Remove Item
    let btnRemoveItem = new Button(Location = new Point(451, 408), Size = new System.Drawing.Size(155, 46), Text = "Remove")
    btnRemoveItem.Font <- new System.Drawing.Font("Times New Roman", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
    shoppingSession.Controls.Add btnRemoveItem
    
    // Order Total
    shoppingSession.Controls.Add(new Label(AutoSize = true, Location = new Point(1089, 401), Text = "Order Total:",
                                           Font = new System.Drawing.Font("Georgia", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)))
    let txtOrderTotal = new TextBox(Location = new Point(1278, 396), Size = new System.Drawing.Size(130, 41), Text = "0.00", TextAlign = HorizontalAlignment.Right,
                                    Font = new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy))
    shoppingSession.Controls.Add txtOrderTotal
    
    // Change
    shoppingSession.Controls.Add(new Label(AutoSize = true, Location = new Point(1089, 496), Text = "Change:",
                                           Font = new System.Drawing.Font("Georgia", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)))
    let txtChange = new TextBox(Location = new Point(1278, 492), Size = new System.Drawing.Size(129, 41), Text = "0.00", TextAlign = HorizontalAlignment.Right,
                                Font = new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy))
    shoppingSession.Controls.Add txtChange
    
    txtItemNumber.KeyUp.Add(fun e ->
        let mutable itemNumber = ""
        let mutable itemName = ""
        let mutable itemSize = ""
        let mutable strDiscountRate = ""
        let mutable unitPrice = 0.00
        let mutable discountRate = 0.00
        let mutable discountAmount = 0.00
        let mutable salePrice = 0.00
        let mutable total : float = 0.00
    
        let mutable itemFound : bool = false
        let xdStoreItems : XmlDocument = new XmlDocument()
        let strStoreItemsFile : string = @"G:\Fun Department Store\StoreItems.xml"
    
        let mutable lvSubItem : ListViewItem.ListViewSubItem = null
    
        if e.KeyCode = Keys.Enter then
            if String.IsNullOrEmpty(txtItemNumber.Text) then
                MessageBox.Show("You must enter an item number.", "FunDS - Fun Department Store",
                                MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
            else
                if File.Exists(strStoreItemsFile) then
                    use fsStoreItems : FileStream = new FileStream(strStoreItemsFile, FileMode.Open, FileAccess.Read)
                    xdStoreItems.Load fsStoreItems
    
                    let xnlStoreItems : XmlNodeList = xdStoreItems.GetElementsByTagName("ItemNumber")
    
                    for xnStoreItem : XmlNode in xnlStoreItems do
                        if xnStoreItem.InnerText = txtItemNumber.Text then
                            itemFound <- true
    
                            itemNumber <- xnStoreItem.InnerText
                            itemName <- xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
                            itemSize <- xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
                            unitPrice <- float (xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText)
                            strDiscountRate <- xnStoreItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
    
                            if String.IsNullOrEmpty(strDiscountRate) || ((float strDiscountRate) <= 0.00) then
                                discountRate <- 0.00
                                discountAmount <- 0.00
                                salePrice <- unitPrice
                            else
                                discountRate <- (float strDiscountRate) / 100.00
                                discountAmount <- unitPrice * discountRate
                                salePrice <- unitPrice - discountAmount
                                   
                            let lviStoreItem : ListViewItem = new ListViewItem(itemNumber) // Item Number
                            lvSubItem <- lviStoreItem.SubItems.Add(itemName) // Item Name
                            lvSubItem <- lviStoreItem.SubItems.Add(itemSize) // Item Size
                            lvSubItem <- lviStoreItem.SubItems.Add(sprintf "%0.02f" unitPrice)
    
                            if discountRate = 0.00 then
                                lvSubItem <- lviStoreItem.SubItems.Add("") // Discount Rate
                                lvSubItem <- lviStoreItem.SubItems.Add("") // Discount Amount
                                lvSubItem <- lviStoreItem.SubItems.Add(unitPrice.ToString("F")) // Unit Price
                            else
                                lvSubItem <- lviStoreItem.SubItems.Add((discountRate * 100.00).ToString() + "%")
                                lvSubItem <- lviStoreItem.SubItems.Add(discountAmount.ToString("F"))
                                lvSubItem <- lviStoreItem.SubItems.Add(salePrice.ToString("F"))
                            
                            let mutable lvItem : ListViewItem = lvwSoldItems.Items.Add(lviStoreItem)
    
                            txtItemNumber.Text <- ""
    
                    if itemFound = false then
                        MessageBox.Show("There is no item with that item number.", "FunDS - Fun Department Store",
                                        MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
    
                    if lvwSoldItems.Items.Count > 0 then
                        for lviStoreItem : ListViewItem in lvwSoldItems.Items do
                            total <- total + (float lviStoreItem.SubItems.[6].Text)
    
                        txtOrderTotal.Text <- sprintf "%0.02f" total)
    
    // Employee Number
    shoppingSession.Controls.Add(new Label(AutoSize = true, Location = new Point(10, 558), Text = "Employee #:", TabIndex = 0,
                                           Font = new System.Drawing.Font("Georgia", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)))
    let txtEmployeeNumber = new TextBox(Location = new Point(206, 554), Size = new System.Drawing.Size(155, 41), TabIndex = 1,
                                        Font = new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy))
    shoppingSession.Controls.Add txtEmployeeNumber
    
    // Text Box: Employee Name
    let txtEmployeeName = new TextBox(Location = new Point(370, 554), Size = new System.Drawing.Size(499, 41),
                                      Font = new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy))
    shoppingSession.Controls.Add txtEmployeeName
    
    txtEmployeeNumber.Leave.Add(fun e ->
        let mutable employeeFound : bool = false
        let xdEmployees : XmlDocument = new XmlDocument()
        let strEmployeesFile : string = @"G:\Fun Department Store\Employees.xml"
    
        if not (String.IsNullOrEmpty(txtEmployeeNumber.Text)) && (File.Exists(strEmployeesFile)) then
            use fsEmployees : FileStream = new FileStream(strEmployeesFile, FileMode.Open, FileAccess.Read)
            xdEmployees.Load fsEmployees
    
            let xnlEmployees : XmlNodeList = xdEmployees.GetElementsByTagName("EmployeeNumber")
    
            for xnEmployee : XmlNode in xnlEmployees do
                if txtEmployeeNumber.Text = xnEmployee.InnerText then
                    employeeFound <- true
                    txtEmployeeName.Text <- String.Concat(xnEmployee.NextSibling.NextSibling.InnerText, ", ", xnEmployee.NextSibling.InnerText)
    
            if employeeFound = false then
                let mutable response = MessageBox.Show("There is no employee with that number.", "FunDS - Fun Department Store",
                                                       MessageBoxButtons.OK, MessageBoxIcon.Information)
                response <- DialogResult.Cancel
        )
    // Button: Reset
    let btnReset = new Button(Location = new Point(923, 551), Size = new System.Drawing.Size(168, 46), Text = "Reset",
                              Font = new System.Drawing.Font("Times New Roman", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy))
    shoppingSession.Controls.Add btnReset
    
    let btnResetClick e =
        let mutable iReceiptNumber : int = 100000
        let xdStoreSales : XmlDocument = new XmlDocument()
        let strStoreSalesFile : string = @"G:\Fun Department Store\StoreSales.xml"
    
        if File.Exists(strStoreSalesFile) then
            use fsStoreSales : FileStream = new FileStream(strStoreSalesFile, FileMode.Open, FileAccess.Read)
            xdStoreSales.Load fsStoreSales
            fsStoreSales.Close()
    
            let xnlStoreSales : XmlNodeList = xdStoreSales.GetElementsByTagName("ReceiptNumber")
        
            for xnStoreSale : XmlNode in xnlStoreSales do
                iReceiptNumber <- int xnStoreSale.InnerText
    
        txtReceiptNumber.Text <- sprintf "%i" (iReceiptNumber + 1)
        txtItemNumber.Text <- ""
        lvwSoldItems.Items.Clear()
        txtItemNumberRemove.Text <- ""
        dtpSaleDate.Value <- DateTime.Now
        lblSaleTime.Text <- DateTime.Now.ToString()
        txtEmployeeNumber.Text <- "" 
        txtEmployeeName.Text <- ""
        txtOrderTotal.Text <- "0.00"
        txtAmountTendered.Text <- "0.00"
        txtChange.Text <- "0.00"
    
    btnReset.Click.Add btnResetClick
    
    shoppingSession.Load.Add(fun e -> btnResetClick(e))
    
    // Button: Submit
    let btnSubmit = new Button(Location = new Point(1097, 551), Size = new System.Drawing.Size(177, 46), Text = "Submit", TabIndex = 6,
                               Font = new System.Drawing.Font("Times New Roman", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy))
    shoppingSession.Controls.Add btnSubmit
    
    txtAmountTendered.KeyUp.Add(fun e ->
        let mutable orderTotal = 0.00
        let mutable amountTendered = 0.00
        let mutable change = 0.00
    
        if (e.KeyCode = Keys.Tab) || (e.KeyCode = Keys.Enter) then
            if not (String.IsNullOrEmpty(txtOrderTotal.Text)) && not (String.IsNullOrEmpty(txtAmountTendered.Text)) then
                orderTotal <- float txtOrderTotal.Text
                amountTendered <- float txtAmountTendered.Text
                change <- amountTendered - orderTotal
    
        txtChange.Text <- sprintf "%0.02f" change)
    
    txtAmountTendered.Leave.Add(fun e ->
        let mutable orderTotal = 0.00
        let mutable amountTendered = 0.00
        let mutable change = 0.00
    
        if not (String.IsNullOrEmpty(txtOrderTotal.Text)) && not (String.IsNullOrEmpty(txtAmountTendered.Text)) then
                orderTotal <- float txtOrderTotal.Text
                amountTendered <- float txtAmountTendered.Text
                change <- amountTendered - orderTotal
    
        txtChange.Text <- sprintf "%0.02f" change)
    
    btnRemoveItem.Click.Add(fun e ->
        let mutable total = 0.00
        let mutable itemFound = false
    
        if lvwSoldItems.Items.Count = 0 then
            MessageBox.Show("The list view is empty.",
                            "FunDS", MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
        elif String.IsNullOrEmpty(txtItemNumberRemove.Text) then
            MessageBox.Show("You must enter an item number and that exists in the list view.",
                                "FunDS", MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
        else
            for lviStoreItem : ListViewItem in lvwSoldItems.Items do
                if lviStoreItem.SubItems.[0].Text = txtItemNumberRemove.Text then
                    itemFound <- true
                    lvwSoldItems.Items.Remove(lviStoreItem)
    
            if itemFound = false then
                MessageBox.Show("That item number is not in the list view.",
                                "FunDS", MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
    
            if lvwSoldItems.Items.Count > 0 then
                for lviStoreItem : ListViewItem in lvwSoldItems.Items do
                    total <- total + (float lviStoreItem.SubItems.[6].Text)
    
                txtOrderTotal.Text <- total.ToString("F")
                txtAmountTendered.Text <- "0.00"
                txtChange.Text <- "0.00"
            else
                txtOrderTotal.Text <- "0.00"
                txtAmountTendered.Text <- "0.00"
                txtChange.Text <- "0.00"
    
            txtItemNumberRemove.Text <- "")
    
    let exitFunction() = () //shoppingSession.Close()
    
    btnSubmit.Click.Add(fun e ->
        let mutable xnResult = null
        let mutable iSoldItemID  : int = 0
        let xdSoldItems  : XmlDocument = new XmlDocument()
        let xdStoreSales : XmlDocument = new XmlDocument()
        let xdStoreItems : XmlDocument = new XmlDocument()
        let strSoldItemsFile  = @"G:\Fun Department Store\SoldItems.xml"
        let strStoreSalesFile = @"G:\Fun Department Store\StoreSales.xml"
        let strStoreItemsFile = @"G:\Fun Department Store\StoreItems1.xml"
    
        if lvwSoldItems.Items.Count = 0 then
            MessageBox.Show("There is no customer order to save.",
                            "FunDS", MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
            exitFunction()               
        else
            if not (File.Exists(strStoreSalesFile)) then
                use fsStoreSales : FileStream = new FileStream(strStoreSalesFile, FileMode.Create, FileAccess.Write)
                xdStoreSales.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                     "<StoreSales></StoreSales>")
                xdStoreSales.Save fsStoreSales
                fsStoreSales.Close()
    
            use fsStoreSales : FileStream = new FileStream(strStoreSalesFile, FileMode.Open, FileAccess.Read)
            xdStoreSales.Load fsStoreSales
            fsStoreSales.Close()
            
            use fsStoreSales : FileStream = new FileStream(strStoreSalesFile, FileMode.Create, FileAccess.Write)
            let xeStoreSale  : XmlElement = xdStoreSales.CreateElement("StoreSale")
            xeStoreSale.InnerXml <- "<ReceiptNumber>" + txtReceiptNumber.Text + "</ReceiptNumber>" +
                                    "<EmployeeNumber>" + txtEmployeeNumber.Text + "</EmployeeNumber>" +
                                    "<SaleDate>" + dtpSaleDate.Value.ToShortDateString() + "</SaleDate>" +
                                    "<SaleTime>" + lblSaleTime.Text + "</SaleTime>" +
                                    "<OrderTotal>" + txtOrderTotal.Text + "</OrderTotal>" +
                                    "<AmountTendered>" + txtAmountTendered.Text + "</AmountTendered>" +
                                    "<Change>" + txtChange.Text + "</Change>"
            xnResult <- xdStoreSales.DocumentElement.AppendChild(xeStoreSale)
    
            xdStoreSales.Save fsStoreSales
            fsStoreSales.Close()
    
            if not (File.Exists(strSoldItemsFile)) then
                use fsSoldItems : FileStream = new FileStream(strSoldItemsFile, FileMode.Create, FileAccess.Write)
                xdSoldItems.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                        "<SoldItems></SoldItems>")
                xdSoldItems.Save fsSoldItems
                fsSoldItems.Close()
    
            use fsSoldItems : FileStream = new FileStream(strSoldItemsFile, FileMode.Open, FileAccess.Read)
            xdSoldItems.Load fsSoldItems
            fsSoldItems.Close()
    
            let xnlSoldItems : XmlNodeList = xdSoldItems.GetElementsByTagName("SoldItemID")
    
            for xnSoldItem : XmlNode in xnlSoldItems do
                iSoldItemID <- int xnSoldItem.InnerText
    
            iSoldItemID <- iSoldItemID + 1
    
            use fsSoldItems : FileStream = new FileStream(strSoldItemsFile, FileMode.Create, FileAccess.Write)
            for lviSoldItem : ListViewItem in lvwSoldItems.Items do
                let xeSoldItem : XmlElement = xdSoldItems.CreateElement("SoldItem")
                xeSoldItem.InnerXml <- "<SoldItemID>" + sprintf "%i" iSoldItemID + "</SoldItemID>" +
                                       "<ReceiptNumber>" + txtReceiptNumber.Text + "</ReceiptNumber>" +
                                       "<ItemNumber>" + lviSoldItem.SubItems.[0].Text + "</ItemNumber>" +
                                       "<ItemName>" + lviSoldItem.SubItems.[1].Text + "</ItemName>" +
                                       "<ItemSize>" + lviSoldItem.SubItems.[2].Text + "</ItemSize>" +
                                       "<UnitPrice>" + lviSoldItem.SubItems.[3].Text + "</UnitPrice>" +
                                       "<DiscountRate>" + lviSoldItem.SubItems.[4].Text + "</DiscountRate>" +
                                       "<DiscountAmount>" + lviSoldItem.SubItems.[5].Text + "</DiscountAmount>" +
                                       "<SalePrice>" + lviSoldItem.SubItems.[6].Text + "</SalePrice>"
                xnResult <- xdSoldItems.DocumentElement.AppendChild(xeSoldItem)
                iSoldItemID <- iSoldItemID + 1
    
            xdSoldItems.Save fsSoldItems
    
            MessageBox.Show("The customer's order has been saved.",
                                    "FunDS", MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
            fsSoldItems.Close()
    
            if File.Exists(strStoreItemsFile) then
                use fsStoreItems : FileStream = new FileStream(strStoreItemsFile, FileMode.Open, FileAccess.Read)
                xdStoreItems.Load fsStoreItems
                fsStoreItems.Close()
    
                let xnlStoreItems : XmlNodeList = xdStoreItems.GetElementsByTagName("ItemNumber")
    
                // Remove the items of the list view from the StoreItems table
                for lviStoreItem : ListViewItem in lvwSoldItems.Items do
                    for xnStoreItem : XmlNode in xnlStoreItems do
                        if xnStoreItem.InnerText = lviStoreItem.SubItems.[0].Text then
                            xnResult <- xdStoreItems.DocumentElement.RemoveChild(xnStoreItem.ParentNode)
                fsSoldItems.Close()
    
                use fsStoreItems : FileStream = new FileStream(strStoreItemsFile, FileMode.Create, FileAccess.Write)
                xdStoreItems.Save fsStoreItems
                fsSoldItems.Close()
    
        btnResetClick e)
    
    let tmrDateTime = new Timer(Enabled = true)
    
    tmrDateTime.Tick.Add(fun e ->
        dtpSaleDate.Value <- DateTime.Today
        lblSaleTime.Text <- DateTime.Now.ToLongTimeString())
    
    // Button: Close
    let btnClose = new Button(Location = new Point(1281, 551), Size = new System.Drawing.Size(129, 46), Text = "Close",
                              Font = new System.Drawing.Font("Times New Roman", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy))
    btnClose.Click.Add(fun e -> shoppingSession.Close())
    shoppingSession.Controls.Add btnClose
  5. Save the file

Reviewing a Shopping Session

Some time to time, the company management must review store sales. Also, a customer may come with a complaint about anything. The first thing to do is to review a customer order. To handle this, we will create a form in which a user can enter a receipt number and click a button to locate its record. If the purchase is found, the form will display (that's all we will do at this time; otherwise, there are many actions that can be taken such as deleting an items from the receipt (and re-imbursing the customer) and putting the information about the returned item to another list, etc).

Practical LearningPractical Learning: Reviewing a Shopping Session

  1. In the Solution Explorer, right-click Program.fs -> Add Above -> New Item...
  2. In the middle list, click Source File and set the name to ShoppingSessionReview
  3. Click Add
  4. Change the contents of the document as follows:
    module ShoppingSessionReview
    
    open System
    open System.IO
    open System.Xml
    open System.Drawing
    open System.Windows.Forms
    
    type CustomerOrder() as this =
        inherit Form()
    
        let mutable lblReceiptNumber      : Label          = null
        let mutable txtReceiptNumber      : TextBox        = null
        let mutable btnFind               : Button         = null
        let mutable colItemNumber         : ColumnHeader   = null
        let mutable colItemName           : ColumnHeader   = null
        let mutable colItemSize           : ColumnHeader   = null
        let mutable colUnitPrice          : ColumnHeader   = null
        let mutable colDiscountRate       : ColumnHeader   = null
        let mutable colDiscountAmount     : ColumnHeader   = null
        let mutable colSalePrice          : ColumnHeader   = null
        let mutable lvwSoldItems          : ListView       = null
    
        let mutable lblEmployeeNumber     : Label          = null
        let mutable txtEmployeeNumber     : TextBox        = null
        let mutable dtpSaleDate           : DateTimePicker = null
        let mutable lblSaleTime           : Label          = null
        let mutable lblTendered           : Label          = null
        let mutable txtAmountTendered     : TextBox        = null
        let mutable lblChange             : Label          = null
        let mutable txtChange             : TextBox        = null
        let mutable lblOrderTotal         : Label          = null
        let mutable txtOrderTotal         : TextBox        = null
        let mutable txtEmployeeName       : TextBox        = null
        let mutable lblItemNumberToRemove : Label          = null
        let mutable txtItemNumberRemove   : TextBox        = null
        let mutable btnRemoveItem         : Button         = null
        let mutable btnClose              : Button         = null
    
        let exitMethod() = ()
        
        let ResetForm() =
            txtReceiptNumber.Text <- ""
            lvwSoldItems.Items.Clear()
            txtItemNumberRemove.Text <- ""
            txtEmployeeNumber.Text <- "" 
            txtEmployeeName.Text <- ""
            txtOrderTotal.Text <- "0.00"
            txtAmountTendered.Text <- "0.00"
            txtChange.Text <- "0.00"
    
        let txtEmployeeNumberLeave e =
            let mutable employeeFound : bool = false
            let xdEmployees : XmlDocument = new XmlDocument()
            let strEmployeesFile : string = @"G:\Fun Department Store\Employees.xml"
    
            if not (String.IsNullOrEmpty(txtEmployeeNumber.Text)) && (File.Exists(strEmployeesFile)) then
                use fsEmployees : FileStream = new FileStream(strEmployeesFile, FileMode.Open, FileAccess.Read)
                xdEmployees.Load fsEmployees
    
                let xnlEmployees : XmlNodeList = xdEmployees.GetElementsByTagName("EmployeeNumber")
    
                for xnEmployee : XmlNode in xnlEmployees do
                    if txtEmployeeNumber.Text = xnEmployee.InnerText then
                        employeeFound <- true
                        txtEmployeeName.Text <- String.Concat(xnEmployee.NextSibling.NextSibling.InnerText, ", ", xnEmployee.NextSibling.InnerText)
    
                if employeeFound = false then
                    let mutable response = MessageBox.Show("There is no employee with that number.", "FunDS - Fun Department Store",
                                                           MessageBoxButtons.OK, MessageBoxIcon.Information)
                    response <- DialogResult.Cancel
    
        let InitializeComponent() =
            // Label: Receipt Number
            lblReceiptNumber <- new Label()
            lblReceiptNumber.AutoSize <- true
            lblReceiptNumber.Font <- new System.Drawing.Font("Georgia", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            lblReceiptNumber.Location <- new Point(16, 22)
            lblReceiptNumber.Text <- "Receipt #:"
            this.Controls.Add lblReceiptNumber
    
            // Text Box: Receipt Number
            txtReceiptNumber <- new TextBox()
            txtReceiptNumber.Font <- new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            txtReceiptNumber.Location <- new Point(180, 18)
            txtReceiptNumber.Size <- new System.Drawing.Size(105, 41)
            this.Controls.Add txtReceiptNumber
    
            // Button: Find
            btnFind <- new Button()
            btnFind.Font <- new System.Drawing.Font("Times New Roman", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            btnFind.Location <- new Point(308, 16)
            btnFind.Size <- new System.Drawing.Size(168, 46)
            btnFind.Text <- "Find"
            this.Controls.Add btnFind
    
            // Column: umn: Item Number
            colItemNumber <- new ColumnHeader()
            colItemNumber.Text <- "Item #"
            colItemNumber.Width <- 100
    
            // Column: umn: Item Name
            colItemName <- new ColumnHeader()
            colItemName.Text <- "Item Name/Description"
            colItemName.Width <- 610
    
            // Column: umn: Item Size
            colItemSize <- new ColumnHeader()
            colItemSize.Text <- "Size"
            colItemSize.Width <- 150
    
            // Column: umn: Unit Price
            colUnitPrice <- new ColumnHeader()
            colUnitPrice.Text <- "Unit Price"
            colUnitPrice.TextAlign <- HorizontalAlignment.Right
            colUnitPrice.Width <- 140
    
            // Column: umn: Discount Rate
            colDiscountRate <- new ColumnHeader()
            colDiscountRate.Text <- "Dscnt Rt"
            colDiscountRate.TextAlign <- HorizontalAlignment.Right
            colDiscountRate.Width <- 120
    
            // Column: umn: Discount Amount
            colDiscountAmount <- new ColumnHeader()
            colDiscountAmount.Text <- "Dscnt Amt"
            colDiscountAmount.TextAlign <- HorizontalAlignment.Right
            colDiscountAmount.Width <- 140
    
            // Column: umn: Sale Price
            colSalePrice <- new ColumnHeader()
            colSalePrice.Text <- "Sale Price"
            colSalePrice.TextAlign <- HorizontalAlignment.Right
            colSalePrice.Width <- 130
    
            // List View: Selected Items
            lvwSoldItems <- new ListView()
            lvwSoldItems.Columns.AddRange [| colItemNumber; colItemName; colItemSize; colUnitPrice;
                                             colDiscountRate; colDiscountAmount; colSalePrice |]
            lvwSoldItems.Font <- new System.Drawing.Font("Times New Roman", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            lvwSoldItems.FullRowSelect <- true
            lvwSoldItems.GridLines <- true
            lvwSoldItems.Location <- new Point(16, 71)
            lvwSoldItems.Size <- new System.Drawing.Size(1424, 321)
            lvwSoldItems.View <- View.Details
            this.Controls.Add lvwSoldItems
    
            // Date/Time Picker: Sale Date
            dtpSaleDate <- new DateTimePicker()
            dtpSaleDate.Font <- new System.Drawing.Font("Times New Roman", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            dtpSaleDate.Location <- new Point(16, 469)
            dtpSaleDate.Size <- new System.Drawing.Size(402, 39)
            this.Controls.Add dtpSaleDate
    
            lblSaleTime <- new Label()
            lblSaleTime.Font <- new System.Drawing.Font("Times New Roman", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            lblSaleTime.Location <- new Point(429, 469)
            lblSaleTime.Text <- "Sale Time"
            lblSaleTime.Size <- new System.Drawing.Size(177, 39)
            this.Controls.Add lblSaleTime
    
            // Label: Tendered
            lblTendered <- new Label()
            lblTendered.AutoSize <- true
            lblTendered.Font <- new System.Drawing.Font("Georgia", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            lblTendered.Location <- new Point(1089, 449)
            lblTendered.Text <- "Tendered:"
            this.Controls.Add lblTendered
    
            // Text Box: Amount Tendered
            txtAmountTendered <- new TextBox()
            txtAmountTendered.Font <- new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            txtAmountTendered.Location <- new Point(1278, 445)
            txtAmountTendered.Size <- new System.Drawing.Size(130, 41)
            txtAmountTendered.Text <- "0.00"
            txtAmountTendered.TextAlign <- HorizontalAlignment.Right
            this.Controls.Add txtAmountTendered
    
            // Label: Item Number to Remove
            lblItemNumberToRemove <- new Label()
            lblItemNumberToRemove.AutoSize <- true
            lblItemNumberToRemove.Font <- new System.Drawing.Font("Georgia", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            lblItemNumberToRemove.Location <- new Point(16, 416)
            lblItemNumberToRemove.Text <- "Item # to Remove:"
            this.Controls.Add lblItemNumberToRemove
    
            // Text Box: Item Number to Remove
            txtItemNumberRemove <- new TextBox()
            txtItemNumberRemove.Font <- new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            txtItemNumberRemove.Location <- new Point(290, 412)
            txtItemNumberRemove.Size <- new System.Drawing.Size(155, 41)
            this.Controls.Add txtItemNumberRemove
    
            // Button: Remove Item
            btnRemoveItem <- new Button()
            btnRemoveItem.Font <- new System.Drawing.Font("Times New Roman", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            btnRemoveItem.Location <- new Point(451, 408)
            btnRemoveItem.Size <- new System.Drawing.Size(155, 46)
            btnRemoveItem.Text <- "Remove"
            this.Controls.Add btnRemoveItem
    
            // Label: Employee Number
            lblEmployeeNumber <- new Label()
            lblEmployeeNumber.AutoSize <- true
            lblEmployeeNumber.Font <- new System.Drawing.Font("Georgia", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            lblEmployeeNumber.Location <- new Point(10, 558)
            lblEmployeeNumber.Text <- "Employee #:"
            this.Controls.Add lblEmployeeNumber
    
            // Text Box: Employee Number
            txtEmployeeNumber <- new TextBox()
            txtEmployeeNumber.Font <- new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            txtEmployeeNumber.Location <- new Point(206, 554)
            txtEmployeeNumber.Size <- new System.Drawing.Size(155, 41)
            txtEmployeeNumber.Leave.Add txtEmployeeNumberLeave
            this.Controls.Add txtEmployeeNumber
    
            // Text Box: Employee Name
            txtEmployeeName <- new TextBox()
            txtEmployeeName.Font <- new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            txtEmployeeName.Location <- new Point(370, 554)
            txtEmployeeName.Size <- new System.Drawing.Size(499, 41)
            this.Controls.Add txtEmployeeName
    
            btnFind.Click.Add(fun e ->
                let mutable receiptFound = false
                let mutable lvSubItem = null
                let xdSoldItems : XmlDocument = new XmlDocument()
                let xdStoreSales : XmlDocument = new XmlDocument()
                let strSoldItemsFile : string = @"G:\Fun Department Store\SoldItems.xml"
                let strStoreSalesFile : string = @"G:\Fun Department Store\StoreSales.xml"
    
                if String.IsNullOrEmpty(txtReceiptNumber.Text) then
                    MessageBox.Show("You must enter a receipt number.", "FunDS - Fun Department Store",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore
                    exitMethod()
    
                if File.Exists(strStoreSalesFile) then
                    use fsStoreSales : FileStream = new FileStream(strStoreSalesFile, FileMode.Open, FileAccess.Read)
                    xdStoreSales.Load fsStoreSales
                    fsStoreSales.Close()
    
                    let xnlStoreSales : XmlNodeList = xdStoreSales.GetElementsByTagName("ReceiptNumber")
    
                    for xnStoreSale : XmlNode in xnlStoreSales do
                        if xnStoreSale.InnerText = txtReceiptNumber.Text then
                            receiptFound <- true
    
                            txtEmployeeNumber.Text <- xnStoreSale.NextSibling.InnerText
                            dtpSaleDate.Value      <- DateTime.Parse(xnStoreSale.NextSibling.NextSibling.InnerText)
                            lblSaleTime.Text       <- xnStoreSale.NextSibling.NextSibling.NextSibling.InnerText
                            txtOrderTotal.Text     <- xnStoreSale.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
                            txtAmountTendered.Text <- xnStoreSale.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
                            txtChange.Text         <- xnStoreSale.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText
    
                            txtEmployeeNumberLeave(e)
    
                if File.Exists(strSoldItemsFile) then
                    use fsSoldItems : FileStream = new FileStream(strSoldItemsFile, FileMode.Open, FileAccess.Read)
                    xdSoldItems.Load fsSoldItems
                    fsSoldItems.Close()
    
                    let xnlSoldItems : XmlNodeList = xdSoldItems.GetElementsByTagName("ReceiptNumber")
    
                    lvwSoldItems.Items.Clear()
    
                    for xnSoldItem : XmlNode in xnlSoldItems do
                        if xnSoldItem.InnerText = txtReceiptNumber.Text then
                            let lviStoreItem : ListViewItem = new ListViewItem(xnSoldItem.NextSibling.InnerText) // Item Number
                            lvSubItem <- lviStoreItem.SubItems.Add(xnSoldItem.NextSibling.NextSibling.InnerText) // Item Name
                            lvSubItem <- lviStoreItem.SubItems.Add(xnSoldItem.NextSibling.NextSibling.NextSibling.InnerText) // Item Size
                            lvSubItem <- lviStoreItem.SubItems.Add(xnSoldItem.NextSibling.NextSibling.NextSibling.NextSibling.InnerText) // Unit Price
                            lvSubItem <- lviStoreItem.SubItems.Add(xnSoldItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText) // Discount Rate
                            lvSubItem <- lviStoreItem.SubItems.Add(xnSoldItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText) // Discount Amount
                            lvSubItem <- lviStoreItem.SubItems.Add(xnSoldItem.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText) // Sale Price
    
                            let mutable lvNewItem = lvwSoldItems.Items.Add(lviStoreItem)
                            lvNewItem <- null
                if receiptFound = false then
                    MessageBox.Show("There is no sale order with that receipt number.", "FunDS - Fun Department Store",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information) |> ignore)
    
            // Label: Order Total
            lblOrderTotal <- new Label()
            lblOrderTotal.AutoSize <- true
            lblOrderTotal.Font <- new System.Drawing.Font("Georgia", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            lblOrderTotal.Location <- new Point(1089, 401)
            lblOrderTotal.Text <- "Order Total:"
            this.Controls.Add lblOrderTotal
    
            // Text Box: Order Total
            txtOrderTotal <- new TextBox()
            txtOrderTotal.Font <- new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            txtOrderTotal.Location <- new Point(1278, 396)
            txtOrderTotal.Size <- new System.Drawing.Size(130, 41)
            txtOrderTotal.Text <- "0.00"
            txtOrderTotal.TextAlign <- HorizontalAlignment.Right
            this.Controls.Add txtOrderTotal
    
            // Label: Change
            lblChange <- new Label()
            lblChange.AutoSize <- true
            lblChange.Font <- new System.Drawing.Font("Georgia", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            lblChange.Location <- new Point(1089, 496)
            lblChange.Text <- "Change:"
            this.Controls.Add lblChange
    
            // Text Box: Change
            txtChange <- new TextBox()
            txtChange.Font <- new System.Drawing.Font("Times New Roman", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            txtChange.Location <- new Point(1278, 492)
            txtChange.Size <- new System.Drawing.Size(129, 41)
            txtChange.Text <- "0.00"
            txtChange.TextAlign <- HorizontalAlignment.Right
            this.Controls.Add txtChange
    
            // Button: Close
            btnClose <- new Button()
            btnClose.Font <- new System.Drawing.Font("Times New Roman", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            btnClose.Location <- new Point(1281, 551)
            btnClose.Size <- new System.Drawing.Size(129, 46)
            btnClose.Text <- "Close"
            btnClose.Click.Add(fun e -> this.Close())
            this.Controls.Add btnClose
    
            this.ClientSize <- new System.Drawing.Size(1454, 611)
            this.MaximizeBox <- false
            this.MinimizeBox <- false
            this.StartPosition <- FormStartPosition.CenterScreen
            this.Text <- "Fun Department Store - Shopping Session Review"
    
        do
            InitializeComponent()
  5. Save the file

A Switchboard

A switchboard serves as the central point of an application. It holds a list of the forms used in an application.

Practical LearningPractical Learning: Creating a Switchboard

  1. Acccess the Program.fs file and change the contents of the document as follows:
    open System
    open System.IO
    open System.Xml
    open System.Drawing
    open System.Windows.Forms
    
    open StoreItems
    open Categories
    open EmployeeNew
    open StoreItemNew
    open ShoppingSessionReview
    
    // Form: Fun Department Store
    type FunDS() as this =
        inherit Form()
        
        let btnNewShoppingSession = new Button()
        let btnStoreItems = new Button()
        let btnShoppingSessionReview = new Button()
        let btnNewStoreItem = new Button()
        let btnEmployees = new Button()
        let btnEditStoreItem = new Button()
        let btnNewEmployee = new Button()
        let btnDeleteStoteItem = new Button()
        let btnClose = new Button()
    
        let btnNewEmployeeClick e =
            let mutable strEmployeeNumber : string = ""
            let mutable strFirstName : string = ""
            let mutable strLastName : string = ""
            let mutable strCounty : string = ""
            let mutable strAddress : string = ""
            let mutable strCity : string = ""
            let mutable strState : string = ""
            let mutable strZIPCode : string = ""
            let mutable strMaritalStatus : string = ""
            let mutable iExemptions : int = 0
            let mutable fHourlySalary : float = 0.00
    
            let rndEmployeeNumber : Random = new Random()
            let xdEmployees : XmlDocument = new XmlDocument()
            let strEmployeesFile = @"G:\Fun Department Store\Employees.xml"
    
            EmployeeNew.txtEmployeeNumber.Text <- ""
            EmployeeNew.txtFirstName.Text <- ""
            EmployeeNew.txtLastName.Text <- ""
            EmployeeNew.txtAddress.Text <- ""
            EmployeeNew.txtCity.Text <- ""
            EmployeeNew.txtCounty.Text <- ""
            EmployeeNew.txtState.Text <- ""
            EmployeeNew.txtZIPCode.Text <- ""
            EmployeeNew.cbxMaritalsStatus.Text <- ""
            EmployeeNew.txtExemptions.Text <- "0"
            EmployeeNew.txtHourlySalary.Text <- "0.00"
    
            EmployeeNew.txtEmployeeNumber.Text <- (sprintf "%i" (rndEmployeeNumber.Next(100000, 999999)))
    
            if employeeNew.ShowDialog() = DialogResult.OK then
                strEmployeeNumber <- EmployeeNew.txtEmployeeNumber.Text
                strFirstName <- EmployeeNew.txtFirstName.Text
                strLastName <- EmployeeNew.txtLastName.Text
                strMaritalStatus <- EmployeeNew.cbxMaritalsStatus.Text
                iExemptions <- int EmployeeNew.txtExemptions.Text
                strAddress <- EmployeeNew.txtAddress.Text
                strCity <- EmployeeNew.txtCity.Text
                strCounty <- EmployeeNew.txtCounty.Text
                strState <- EmployeeNew.txtState.Text
                strZIPCode <- EmployeeNew.txtZIPCode.Text
                fHourlySalary <- float EmployeeNew.txtHourlySalary.Text
                    
                if not (File.Exists(strEmployeesFile)) then
                    xdEmployees.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                        "<Employees></Employees>")
                    xdEmployees.Save strEmployeesFile
    
                xdEmployees.Load strEmployeesFile
    
                let elmXML : XmlElement = xdEmployees.CreateElement("Employee")
                        
                // Create the XML code of the child element of Employee
                let strNewEmployee = "<EmployeeNumber>" + strEmployeeNumber + "</EmployeeNumber>" +
                                     "<FirstName>" + strFirstName + "</FirstName>" +
                                     "<LastName>" + strLastName + "</LastName>" +
                                     "<Address>" + strAddress + "</Address>" +
                                     "<City>" + strCity + "</City>" +
                                     "<County>" + strCounty + "</County>" +
                                     "<State>" + strState + "</State>" +
                                     "<ZIPCode>" + strZIPCode + "</ZIPCode>" +
                                     "<MaritalStatus>" + strMaritalStatus + "</MaritalStatus>" +
                                     "<Exemptions>" + (sprintf "%i" iExemptions) + "</Exemptions>" +
                                     "<HourlySalary>" + (sprintf "%0.02f" fHourlySalary) + "</HourlySalary>"
                elmXML.InnerXml <- strNewEmployee
    
                // Append the new element as a child of employees
                xdEmployees.DocumentElement.AppendChild(elmXML) |> ignore
    
                // Save the XML file
                xdEmployees.Save strEmployeesFile
    
        let InitializeComponent() =
            // Button: New Shopping Session
            btnNewShoppingSession.Font <- new System.Drawing.Font("Palatino Linotype", 26.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            btnNewShoppingSession.Location <- new Point(22, 22)
            btnNewShoppingSession.Size <- new System.Drawing.Size(478, 67)
            btnNewShoppingSession.Text <- "New Shopping Session ..."
            btnNewShoppingSession.Click.Add(fun e -> PointOfSale.shoppingSession.Show())
            this.Controls.Add btnNewShoppingSession
    
            // Button: Store Items
            btnStoreItems.Font <- new System.Drawing.Font("Palatino Linotype", 26.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            btnStoreItems.Location <- new Point(518, 22)
            btnStoreItems.Size <- new System.Drawing.Size(478, 67)
            btnStoreItems.Text <- "Store Items ..."
            btnStoreItems.Click.Add(fun e ->
                let sis = new StoreItems.StoreItems()
                sis.Show() |> ignore)
            this.Controls.Add btnStoreItems
    
            // Button: Shopping Session  Review
            btnShoppingSessionReview.Font <- new System.Drawing.Font("Palatino Linotype", 26.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            btnShoppingSessionReview.Location <- new Point(22, 108)
            btnShoppingSessionReview.Size <- new Size(478, 67)
            btnShoppingSessionReview.Text <- "Shopping Session Review ..."
            btnShoppingSessionReview.Click.Add(fun e ->
                let orderReview = new ShoppingSessionReview.CustomerOrder()
                orderReview.Show())
            this.Controls.Add btnShoppingSessionReview
    
            // Button: New Store Item
            btnNewStoreItem.Font <- new System.Drawing.Font("Palatino Linotype", 26.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            btnNewStoreItem.Location <- new Point(518, 108)
            btnNewStoreItem.Size <- new Size(478, 67)
            btnNewStoreItem.Text <- "New Store Item ..."
            btnNewStoreItem.Click.Add(fun e -> storeItemNew.ShowDialog() |> ignore)
            this.Controls.Add btnNewStoreItem
    
            // Button: Employees
            btnEmployees.Font <- new System.Drawing.Font("Palatino Linotype", 26.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            btnEmployees.Location <- new Point(22, 194)
            btnEmployees.Size <- new Size(478, 67)
            btnEmployees.Text <- "Employees ..."
            btnEmployees.Click.Add(fun e ->
                let staff : Employees.Employees = new Employees.Employees()
                //staff.InitializeComponent()
                staff.Show())
            this.Controls.Add btnEmployees
    
            // Button: Edit Store Item
            btnEditStoreItem.Font <- new System.Drawing.Font("Palatino Linotype", 26.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            btnEditStoreItem.Location <- new Point(518, 194)
            btnEditStoreItem.Size <- new Size(478, 67)
            btnEditStoreItem.Text <- "Edit Store Item ..."
            btnEditStoreItem.Click.Add(fun e -> StoreItemEditor.storeItemEditor.ShowDialog() |> ignore)
            this.Controls.Add btnEditStoreItem
    
            // Button: New Employee
            btnNewEmployee.Font <- new System.Drawing.Font("Palatino Linotype", 26.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            btnNewEmployee.Location <- new Point(22, 283)
            btnNewEmployee.Size <- new Size(478, 67)
            btnNewEmployee.Text <- "New Employee ..."
            btnNewEmployee.Click.Add btnNewEmployeeClick
            // btnNewEmployee.Click.Add(fun e -> EmployeeNew.employeeNew.ShowDialog() |> ignore)
            (*btnNewEmployee.Click.Add(fun e ->
                let strEmployeeNumber : string = ""
                let strFirstName : string = ""
                let strLastName : string = ""
                let strCounty : string = ""
                let strAddress : string = ""
                let strCity : string = ""
                let strState : string = ""
                let strZIPCode : string = ""
                let strMaritalStatus : string = ""
                let iExemptions : int = 0
                let dblHourlySalary : float = 0.00
    
                //let en : EmployeeNew.NewEmployee = new EmployeeNew.NewEmployee()
                let rndEmployeeNumber : Random = new Random()
                let xdEmployees : XmlDocument = new XmlDocument()
                let strEmployeesFile = @"G:\Fun Department Store\Employees.xml"
    
                en.txtEmployeeNumber.Text <- (sprintf "%i" (rndEmployeeNumber.Next(100000, 999999)))
    
                if en.ShowDialog() = DialogResult.OK then
                    strEmployeeNumber <- en.txtEmployeeNumber.Text
                    strFirstName <- EmployeeNew.NewEmployee.txtFirstName.Text
                    strLastName <- EmployeeNew.NewEmployee.txtLastName.Text
                    strMaritalStatus = en.cbxMaritalsStatus.Text
                    iExemptions <- int EmployeeNew.NewEmployee.txtExemptions.Text
                    strAddress <- EmployeeNew.NewEmployee.txtAddress.Text
                    strCity <- EmployeeNew.NewEmployee.txtCity.Text
                    strCounty <- EmployeeNew.NewEmployee.txtCounty.Text
                    strState <- EmployeeNew.NewEmployee.txtState.Text
                    strZIPCode <- EmployeeNew.NewEmployee.txtZIPCode.Text
                    dblHourlySalary <- float EmployeeNew.NewEmployee.txtHourlySalary.Text
                    
                    if File.Exists(strEmployeesFile) = false then
                        xdEmployees.LoadXml "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                            "<Employees></Employees>"
                        xdEmployees.Save strEmployeesFile
    
                        xdEmployees.Load strEmployeesFile
    
                        XmlElement elmXML = xdEmployees.CreateElement("Employee")
                        // Create the XML code of the child element of Employee
                        let strNewEmployee = "<EmployeeNumber>" + strEmployeeNumber + "</EmployeeNumber>" +
                                             "<FirstName>" + strFirstName + "</FirstName>" +
                                             "<LastName>" + strLastName + "</LastName>" +
                                             "<Address>" + strAddress + "</Address>" +
                                             "<City>" + strCity + "</City>" +
                                             "<County>" + strCounty + "</County>" +
                                             "<State>" + strState + "</State>" +
                                             "<ZIPCode>" + strZIPCode + "</ZIPCode>" +
                                             "<MaritalStatus>" + strMaritalStatus + "</MaritalStatus>" +
                                             "<Exemptions>" + iExemptions + "</Exemptions>" +
                                             "<HourlySalary>" + dblHourlySalary + "</HourlySalary>";
                                             elmXML.InnerXml = strNewEmployee
    
                        // Append the new element as a child of employees
                        xdEmployees.DocumentElement.AppendChild elmXML
    
                        // Save the XML file
                        xdEmployees.Save strEmployeesFile*)
    
            this.Controls.Add btnNewEmployee
    
            // Button: Delete Stote Item
            btnDeleteStoteItem.Font <- new System.Drawing.Font("Palatino Linotype", 26.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            btnDeleteStoteItem.Location <- new Point(518, 283)
            btnDeleteStoteItem.Size <- new Size(478, 67)
            btnDeleteStoteItem.Text <- "Delete Stote Item ..."
            btnDeleteStoteItem.Click.Add(fun e -> StoreItemDelete.itemDeletion.ShowDialog() |> ignore)
            this.Controls.Add btnDeleteStoteItem
    
            // Button: Close
            btnClose.Font <- new System.Drawing.Font("Palatino Linotype", 27.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, 0uy)
            btnClose.Location <- new Point(22, 374)
            btnClose.Size <- new Size(974, 67)
            btnClose.Text <- "Close"
            btnClose.Click.Add(fun e -> this.Close())
            this.Controls.Add btnClose
    
            this.Text <- "FunDS - Fun Department Store"
            this.ClientSize <- new System.Drawing.Size(1018, 463)
            this.StartPosition <- FormStartPosition.CenterScreen
            this.Load.Add(fun e ->
                let di : DirectoryInfo  = Directory.CreateDirectory(@"G:\Fun Department Store")
                di.Create())
    
        do
            InitializeComponent()
    
    [<STAThread>]
    [<EntryPoint>]
    let main argv =
        //let fds = new FunDS()
        
        Application.Run(new FunDS())
        0
  2. Save the file

Building the Application

Microsoft Visual Studio provides the tools necessary to build an F# project.

Practical LearningPractical Learning: Creating a Switchboard

  1. On the main menu, click Debug -> Start Without Debugging

Application Testing

If you want to test the application, use the following values.

 
 
   
                  

Practical LearningPractical Learning: Testing the Application

  1. Click the New Employee button to open its dialog box
  2. Fill the controls with the following values:
    Employee #: 941148
    First Name: Catherine
    Last Name: Watts
    Address: 4242 Sightings Str
    City: Baltimore
    Country: Baltimore
    State: MD
    ZIP Code: 21205
    Marital Status: Married
    Exemptions: 3
    Hourly Salary: 38.85
  3. Click OK
  4. On the switchboard, click the New Store Item... button
  5. Create items as follows (create the manufacturers, the categories, and the sub-categories by clicking the corresponding buttons):
     
    Item # Manufacturer Category Sub-Category Item Name Item Size Unit Price Discount Rate
    177314 Ralph Lauren Girls Shirts Girls 2-6X Short-Sleeved Mesh Polo Shirt 3T 34.95  
    729530 Kenneth Cole Women Dresses Three-Quarter Sleeved Dress M 164.5 50
    307368 Polo Ralph Lauren Men Pants Classic Straight-Leg Jeans 30W - 29L 84.85 15
    220573 Nautica Baby Girls   Baby Girls 12-24 Months Lace Two-Piece Set 12M 40  
    806888 Guess Girls Dresses Girls 2-6X Denim Print Ruffled Dress 2T 34.95  
    683079 Anne Klein Women Skirts Pencil Skirt 2 54  
    848428 Ralph Lauren Boys Sweaters Boys 2-7 Long-Sleeved Cable Crewneck T-Shirt 4 55  
    683626 Ralph Lauren Women Dresses Structured Scoopneck Ponte Dress 0 195 60
  6. Close the New Store Item dialog box
  7. On the switchboard, click the New Shopping Session button
  8. Set the employee number as 941148 and press Tab
  9. In the Item # To Add text box, type 848428 and press Enter
  10. Type 729530 and press Enter
  11. In the Tendered text box, enter 200 and press Enter:

    Fun Department Store - New Shopping Session

  12. Click Submit
  13. Start a new shopping session with employee number as 941148 and press Tab
  14. Add the shopping items with the following numbers: 683626, 307368, 683079, and 806888
  15. In the Item # to Remove text box, type 683079

    Fun Department Store - New Shopping Session

  16. Click Remove
  17. In the Tendered text box, type 200 and press Enter

    Fun Department Store - New Shopping Session

  18. Click Submit
  19. Close the New Shopping Session form
  20. On the Switchboard, click the Shopping Session Review button
  21. In the Receipt Number text box, type 100001 and click Find

    Fun Department Store - Shopping Session Review

  22. Closse the Shopping Session Review form
  23. On the switchboard, click the Employees button
  24. Use the New Employee button to create a few records as follows:
     
    Employee # First Name Last Name Address City Country State ZIP Code Marital Status Exemptions Hourly Salary
    952748 David Evans 5102 Piedmont Rd Silver Spring Montgomery MD 20910 Single 0 17.25
    606384 Robert Gibson 10324 Marina Ave College Park Prince George MD 20742 Single 1 22.25
  25. Close the Employees form
  26. Click the New Shopping Session button and create a new shopping session as follows:
     
    Employee # Item # Tendered
    606384 177314 50
  27. Click Submit
  28. Close the New Shopping Session form
  29. Click the Employees button and create a few emplyees records as follows:
     
    Employee # First Name Last Name Address City Country State ZIP Code Marital Status Exemptions Hourly Salary
    428041 Jeannine Hewsen  2418 Woodwell Rd Rockville Montgomery MD 20850 Married 2 34.05
    172847 Carl Lowry 7447 Emiry Str Alexandria (Independent) VA 22314 Single 2 26.85
    927048 Henry Meuer 802 Wheeler St York York PA 17401 Married 0 8.95
    837405 Herbert Mann  6218 Willimon Ave Wilmington New Castle DE 19801 Married 2 14.75
  30. Close the Employees form
  31. On the switchboard, click the Store Items button
  32. Click New Store Item...
  33. Create items as follows:
     
    Item # Manufacturer Category Sub-Category Item Name Item Size Unit Price Discount Rate
    580040 Cole Haan Women Handbags Victoria Zip-Top Tote Bag   298  
    795081 Lauren by Ralph Lauren Men Pants Mid-Weight Flat-Front Wool Trouser Pants 36W 32L 65 25
    948596 Tommy Hilfiger Men Shirts Texture Oxford Slim Fit Long Sleeve Dress Shirt 17 - 34/35 47.75  
    360825 Lauren by Ralph Lauren Women Accessories Printed Silk Scarf   45  
    383511 Calvin Klein Men Pants Straight Leg Jean in Black Wash 32/30 45  
    294148 Lauren by Ralph Lauren Men Pants Mid-Weight Flat-Front Wool Trouser Pants 36W 29L 65  
    559717 Guess Girls Dresses Girls 2-6X Denim Print Ruffled Dress 3T 34.95  
    830486 AK Anne Klein Women Skirts Seamless Textured Pencil Skirt S 65.95  
  34. Close the New Store Item dialog box
  35. Close the Store Items form
  36. Click the New Shopping Session button and create a new shopping session as follows:
     
    Employee # Item # Tendered
    428041 683079  
      360825  
      830486  
      383511  
      948596 260
  37. Close the New Shopping Session form
  38. On the Switchboard, click the Shopping Session Review button
  39. In the Receipt Number text box, type 100003 and click Find

    Fun Department Store - Shopping Session Review

  40. Close the form and close Microsoft Access

Previous Copyright © 2015 FunctionX Next