Home

Linked List Example Application: Lambda Properties Management

   

Fundamentals of Linked Lists

 

Introduction

A linked list is a collection that defines:

  • Each item or object also called a node
  • Its beginning object, also referred to as the first or the head
  • Ifs end object, also called the last or referred to as the tail

To explore the functionality of a linked list, we are going to create an application used to manage house rent for a real estate company. Actually, we started with a company that owned an apartment building. This time, the company has acquired another apartment building. Also, the company hs been awarded various contracts to manage rents for many types privately owned houses, including condominiums, townhouses, and single families.

ApplicationPractical Learning: Introducing Linked Lists

  1. Start Microsoft Visual Studio
  2. To create a new application, on the main menu, click FILE -> New Project...
  3. In the middle list, click Windows Forms Application
  4. Change the Name to LambdaPropertiesManagement1
  5. Click OK
  6. To create a new class, on the main menu, click PROJECT -> Add Class...
  7. Set the Name to Employee
  8. Click Add
  9. Change the file as follows:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace LambdaPropertiesManagement1
    {
        [Serializable]
        public class Employee
        {
            public string EmployeeNumber { get; set; }
            public string FirstName      { get; set; }
            public string LastName       { get; set; }
            public string Title          { get; set; }
        }
    }
  10. To create a new form, on the main menu, click PROJECT -> Add Windows Form...
  11. Set the name to EmployeeEditor
  12. Click Add
  13. Design the form as follows:
     
    Lambda Properties Management - Employee Editor
    Control (Name) Text Modifiers Other Properties
    Label Label   Employee Number:    
    TextBox Text Box txtEmployeeNumber   Public  
    Label Label   First Name:    
    TextBox Text Box txtFirstName   Public  
    Label Label   Last Name:    
    TextBox Text Box txtLastName   Public  
    Label Label   Employee Title:    
    TextBox Text Box txtTitle   Public  
    Button btnOK OK   DialogResult: OK
    Button btnCancel Cancel   DialogResult: Cancel
    Form
    FormBorderStyle: FixedDialog
    StartPosition: CenterScreen
    AcceptButton: btnOK
    CancelButton: btnCancel
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskBar: False
  14. To create a new form, on the main menu, click PROJECT -> Add Windows Form...
  15. Set the name to Employees
  16. Click Add
  17. Add a list view to the form and create the columns as follows:
     
    (Name) Text Width
    colEmployeeNumber Employee # 70
    colFirstName First Name 80
    colLastName Last Name 80
    colTitle Title 120
  18. Click OK
  19. Design the form as follows:
     
    Lambda Properties Management - Employees Records
    Control (Name) Text Other Properties
    ListView List View lvwEmployees   FullRowSelect: True
    GridLines: True
    View: Details
    Button btnNewEmployee New Employee...  
    Button btnClose Close  
  20. To create a new class, on the main menu, click PROJECT -> Add Class...
  21. Set the Name to RentalProperty
  22. Click Add
  23. Change the file as follows:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace LambdaPropertiesManagement1
    {
        [Serializable]
        public class RentalProperty
        {
            public string PropertyNumber  { get; set; }
            public string PropertyType    { get; set; }
            public string Address         { get; set; }
            public string UnitNumber      { get; set; }
            public string City            { get; set; }
            public string State           { get; set; }
            public string ZIPCode         { get; set; }
            public short  Stories         { get; set; }
            public short  Bedrooms        { get; set; }
            public float  Bathrooms       { get; set; }
            public double MonthlyRate     { get; set; }
            public double SecurityDeposit { get; set; }
            public string OccupancyStatus { get; set; }
            public string PictureFile     { get; set; }
        }
    }
  24. To create a new form, on the main menu, click PROJECT -> Add Windows Form...
  25. Set the name to PropertyTypeEditor
  26. Click Add
  27. Design the form as follows:
     
    Lambda Properties Management - New Property Type
    Control (Name) Text Modifiers Other Properties
    Label Label   Property Type:    
    TextBox Text Box txtPropertyType   Public  
    Button btnOK OK   DialogResult: OK
    Button btnCancel Cancel   DialogResult: Cancel
    Form
    FormBorderStyle: FixedDialog
    StartPosition: CenterScreen
    AcceptButton: btnOK
    CancelButton: btnCancel
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskBar: False
  28. To create a new form, on the main menu, click PROJECT -> Add Windows Form...
  29. Set the name to RentalPropertyEditor
  30. Click Add
  31. Design the form as follows:
     

    Lambda Properties Management - New Property

    Control (Name) Text Modifiers Other Properties
    Label Label   Property #:    
    TextBox Text Box txtPropertyNumber   Public  
    Label Label   Property Type:    
    ComboBox Combo Box cbxPropertiesTypes   Public  
    Button btnNewPropertyType New Property Type...  
    Label Label   Address:    
    TextBox Text Box txtAddress   Public  
    Label Label   Unit #:    
    TextBox Text Box txtUnitNumber   Public  
    Label Label   City:    
    TextBox Text Box txtCity   Public  
    Label Label   State:    
    TextBox Text Box txtState   Public  
    Label Label   ZIP Code:    
    TextBox Text Box txtZIPCode   Public  
    Label Label   Stories:    
    TextBox Text Box txtStories 1 Public  
    Label Label   Bedrooms:   AlignRight: Right
    TextBox Text Box txtBedrooms 1 Public  
    Label Label   Bathrooms:    
    TextBox Text Box txtBathrooms 1.00 Public  
    Label Label   Monthly Rate:   AlignRight: Right
    TextBox Text Box txtMonthlyRate 1.00 Public  
    Label Label   Sec. Deposit:    
    TextBox Text Box txtSecurityDeposit 0.00 Public  
    Label Label   Occupancy Status:    
    ComboBox Combo Box cbxOccupanciesStatus   Public Items:
    Other
    Available
    Occupied
    Not Ready
    Needs Repair
    Button btnSelectPicture Select Picture...  
    Button btnOK OK   DialogResult: OK
    Button btnCancel Cancel   DialogResult: Cancel
    PictureBox PictureBox pbxProperty     BorderStyle: FixedSingle
    SizeMode: Zoom
    Form
    FormBorderStyle: FixedDialog
    StartPosition: CenterScreen
    AcceptButton: btnOK
    CancelButton: btnCancel
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskBar: False
  32. Double-click an unoccupied area of the form
  33. Return to the Rental Property Editor and double-click the Select Picture button
  34. Return to the Rental Property Editor and double-click the New Property Type button
  35. Change the document as follows:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.IO;
    using System.Windows.Forms;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace LambdaPropertiesManagement1
    {
        public partial class RentalPropertyEditor : Form
        {
            public string PictureFile;
    
            public RentalPropertyEditor()
            {
                InitializeComponent();
            }
    
            private void RentalPropertyEditor_Load(object sender, EventArgs e)
            {
                PictureFile = "C:\\Microsoft Visual C# Application Design\\Lambda Properties Management\\000-000.jpg";
            }
    
            private void btnSelectPicture_Click(object sender, EventArgs e)
            {
                if (dlgPicture.ShowDialog() == DialogResult.OK)
                {
                    pbxProperty.Image = Image.FromFile(dlgPicture.FileName);
                    PictureFile = dlgPicture.FileName;
                }
            }
    
            private void btnNewPropertyType_Click(object sender, EventArgs e)
            {
                PropertyTypeEditor editor = new PropertyTypeEditor();
    
                if (editor.ShowDialog() == DialogResult.OK)
                {
                    if (string.IsNullOrEmpty(editor.txtPropertyType.Text))
                    {
                        MessageBox.Show("You must enter a new property type.",
                                "Lambda Properties Management",
                                MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return;
                    }
    
                    if (!cbxPropertiesTypes.Items.Contains(editor.txtPropertyType.Text))
                    {
                        cbxPropertiesTypes.Items.Add(editor.txtPropertyType.Text);
                        cbxPropertiesTypes.Text = editor.txtPropertyType.Text;
                    }
                }
            }
        }
    }
  36. To create a new form, on the main menu, click PROJECT -> Add Windows Form...
  37. Set the name to RentalProperties
  38. Click Add
  39. Add a list view to the form and create the columns as follows:
     
    (Name) Text TextAlign Width
    colPropertyNumber Property #   65
    colPropertyType Type   75
    colAddress Address   150
    colUnitNumber Unit #   45
    colCity City   90
    colState State Center 40
    colZIPCode ZIP Code Center  
    colStories Stories Right 50
    colBedrooms Beds Right 40
    colBathrooms Baths Right 40
    colMonthlyRate Rate Right  
    colSecurityDeposit Deposit Right  
    colOccupancyStatus Status   100
  40. Click OK
  41. Design the form as follows:
     

    Lambda Properties Management - Rental Properties

    Control (Name) Text Other Properties
    ListView List View lvwRentalProperties   FullRowSelect: True
    GridLines: True
    View: Details
    Button btnNewRentalProperty New Rental Property ...  
    Button btnUpdateRentalProperty Update Rental Property ...  
    Button btnDeleteRentalProperty Delete Rental Property ...  
    Button btnClose Close  
    PictureBox PictureBox pbxProperty   BorderStyle: FixedSingle
    SizeMode: Zoom
  42. To create a new class, on the main menu, click PROJECT -> Add Class...
  43. Set the Name to TenantRegistration
  44. Click Add
  45. Change the file as follows:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace LambdaPropertiesManagement1
    {
        [Serializable]
        public class TenantRegistration
        {
            public int      RegistrationNumber { get; set; }
            public DateTime RegistrationDate   { get; set; }
            public string   EmployeeNumber     { get; set; }
            public string   TenantCode         { get; set; }
            public string	FirstName          { get; set; }
            public string	LastName           { get; set; }
            public string	MaritalStatus      { get; set; }
            public ushort	NumberOfChildren   { get; set; }
            public string	PhoneNumber        { get; set; }
            public string	EmailAddress       { get; set; }
            public string   PropertyNumber     { get; set; }
            public DateTime RentStartDate      { get; set; }
        }
    }
  46. To create a new form, on the main menu, click PROJECT -> Add Windows Form...
  47. Set the name to TenantRegistrationEditor
  48. Click Add
  49. Design the form as follows:
     
    Lambda Properties Management - New Tenant Registration
    Control (Name) Text Modifiers Other Properties
    Label Label   Registration Date    
    DateTimePicker Date Time Picker dtpRegistrationDate   Public  
    Label Label   Processed By   AutoSize: False
    BackColor: Gray
    BorderStyle: FixedSingle
    ForeColor: White
    TextAlign: MiddleLeft
    Label Label   Employee #:    
    TextBox Text Box txtEmployeeNumber   Public  
    TextBox Text Box txtEmployeeName      
    Label Label   Tenant Information   AutoSize: False
    BackColor: Gray
    BorderStyle: FixedSingle
    ForeColor: White
    TextAlign: MiddleLeft
    Label Label   Tenant Code:    
    TextBox Text Box txtTenantCode   Public  
    Label Label   Phone #    
    TextBox Text Box txtPhoneNumber   Public  
    Label Label   First Name:    
    TextBox Text Box txtFirstName   Public  
    Label Label   Last Name:    
    TextBox Text Box txtLastName   Public  
    Label Label   Marital Status:    
    ComboBox Combo Box cbxMaritalStatus   Public Items:
    Other
    Single
    Married
    Widdow
    Divorced
    Separated
    Label Label   # Of Children:    
    TextBox Text Box txtNumberOfChildren   Public  
    Label Label   Email Address:    
    TextBox Text Box txtEmailAddress   Public  
    Label Label   Property Allocation   AutoSize: False
    BackColor: Gray
    BorderStyle: FixedSingle
    ForeColor: White
    TextAlign: MiddleLeft
    Label Label   Property #:    
    TextBox Text Box txtPropertyNumber   Public  
    TextBox Text Box txtPropertyDetails     Multiline: True
    ScrollBars: Vertical
    Label Label   Rent Start Date:    
    DateTimePicker Date Time Picker dtpRentStartDate   Public  
    Label Label   Registration #:    
    TextBox Text Box txtRegistrationNumber   Public  
    Button btnOK OK   DialogResult: OK
    Button btnCancel Cancel   DialogResult: Cancel
    Form
    FormBorderStyle: FixedDialog
    StartPosition: CenterScreen
    AcceptButton: btnOK
    CancelButton: btnCancel
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskBar: False
  50. To create a new form, on the main menu, click PROJECT -> Add Windows Form...
  51. Set the name to TenantsRegistrations
  52. Click Add
  53. Add a list view to the form and create the columns as follows:
     
    (Name) Text Width
    colRegistrationNumber Regist # 55
    colRegistrationDate Regist Date 70
    colRegistrationClerk Registration Clerk 130
    colTenantCode Tenant Code 120
    colFirstName First Name 65
    colLastName Last Name 65
    colMaritalStatus Status  
    colNumberOfChildren # of Children 75
    colPhoneNumber Phone # 80
    colEmailAddress Email Address 150
    colPropertyNumber Property # 65
    colRentStartDate Start Date 160
  54. Click OK
  55. Design the form as follows:
     

    Lambda Properties Management - Employees Records

    Control (Name) Text Other Properties
    ListView List View lvwRegistrations   FullRowSelect: True
    GridLines: True
    View: Details
    Button btnNewRegistration New Registration...  
    Button btnClose Close  
  56. To create a new class, on the main menu, click PROJECT -> Add Class...
  57. Set the Name to RentPayment
  58. Click Add
  59. Change the file as follows:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace LambdaPropertiesManagement1
    {
        [Serializable]
        public class Payment
        {
            public int ReceiptNumber      { get; set; }
            public DateTime PaymentDate   { get; set; }
            public string EmployeeNumber  { get; set; }
            public int RegistrationNumber { get; set; }
            public double PaymentAmount   { get; set; }
            public string Notes	      { get; set; }
        }
    }
  60. To create a new form, on the main menu, click PROJECT -> Add Windows Form...
  61. Set the name to PaymentEditor
  62. Click Add
  63. Design the form as follows:
     
    Lambda Properties Management - Employee Editor
    Control (Name) Text Modifiers Other Properties
    Label Label   Payment Date    
    DateTimePicker Date Time Picker dtpPaymentDate   Public  
    Label Label   Payment Processed By   AutoSize: False
    BackColor: Gray
    BorderStyle: FixedSingle
    ForeColor: White
    TextAlign: MiddleLeft
    Label Label   Employee #:    
    TextBox Text Box txtEmployeeNumber   Public  
    TextBox Text Box txtEmployeeName      
    Label Label   Registration Information   AutoSize: False
    BackColor: Gray
    BorderStyle: FixedSingle
    ForeColor: White
    TextAlign: MiddleLeft
    Label Label   Registration #:    
    TextBox Text Box txtRegistrationNumber   Public  
    Label Label   Property Info:    
    TextBox Text Box txtPropertyInformation   Public  
    Label Label   Payment Information   AutoSize: False
    BackColor: Gray
    BorderStyle: FixedSingle
    ForeColor: White
    TextAlign: MiddleLeft
    Label Label   Amount Paid:    
    TextBox Text Box txtAmountPaid   Public TextAlign: Right
    Label Label   Notes:    
    TextBox Text Box txtNotes   Public Multiline: True
    ScrollBars: Vertical
    Label Label   Receipt #:    
    TextBox Text Box txtReceiptNumber   Public TextAlign: Right
    Button btnOK OK   DialogResult: OK
    Button btnCancel Cancel   DialogResult: Cancel
    Form
    FormBorderStyle: FixedDialog
    Text: Ceil Inn - Employee Editor
    StartPosition: CenterScreen
    AcceptButton: btnOK
    CancelButton: btnCancel
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskBar: False
  64. To create a new form, on the main menu, click PROJECT -> Add Windows Form...
  65. Set the name to RentPayments
  66. Click Add
  67. Add a list view to the form and create the columns as follows:
     
    (Name) Text TextAlign Width
    colReceiptNumber Receipt #   65
    colPaymentDate Payment Date Center 80
    colEmployeeNumber Employee #   75
    colRegistrationNumber Registration #   80
    colPaymentAmount Amount Paid   75
  68. Click OK
  69. Design the form as follows:
     
    Lambda Properties Management - Employees Records
    Control (Name) Text Other Properties
    ListView List View lvwPayments   FullRowSelect: True
    GridLines: True
    View: Details
    Label Label   Processed By:  
    TextBox Text Box txtProcessedBy    
    Label Label   Registation Details:  
    TextBox Text Box txtRegistationDetails   Multiline: True
    ScrollBars: Vertical
    Button btnNewPayment New Payment...  
    Button btnClose Close  
  70. Save all

Starting a Linked List

A linked list is primarily a collection. To support linked lists, the .NET Framework provides the LinkedList generic class defined in the System.Collections.Generic namespace:

public class LinkedList<T> : ICollection<T>, 
            		     IEnumerable<T>,
            		     ICollection, IEnumerable,
            		     ISerializable,
            		     IDeserializationCallback

You can start a linked list be declaring a variable of type LinkedList and initializing it.

 

Adding Nodes to a Linked List

 

Creating a Node

As mentioned already, an item or object of a linked list is also called a node. In the .NET Framework, a node of a linked list is based on the LinkedListNode sealed class. The easiest way to create is to call the AddLast() method of the LinkedList class. Here is an example:

private void btnNewEmployee_Click(object sender, EventArgs e)
{
    EmployeeEditor editor = new EmployeeEditor();
    BinaryFormatter bfEmployees = new BinaryFormatter();
    LinkedList<Employee> employees = new LinkedList<Employee>();
    string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Employees.pml";

    if( File.Exists(strFileName))
    {
        using(FileStream fsEmployees = File.Open(strFileName, FileMode.Open, FileAccess.Read)) 
        {
            employees = (LinkedList<Employee>)bfEmployees.Deserialize(fsEmployees);
        }
    }

    if( editor.ShowDialog() == DialogResult.OK )
    {
        if( string.IsNullOrEmpty(editor.txtEmployeeNumber.Text) )
        {
            MessageBox.Show("You must provide an employee number.",
	        	    "Lambda Properties Management",
        	            MessageBoxButtons.OK, MessageBoxIcon.Information);
            return;
        }
	    
        Employee empl = new Employee();

        empl.EmployeeNumber = editor.txtEmployeeNumber.Text;
        empl.FirstName	    = editor.txtFirstName.Text;
        empl.LastName	    = editor.txtLastName.Text;
        empl.Title	    = editor.txtEmployeeTitle.Text;

        employees.AddLast(empl);

        using(FileStream fsEmployees = File.Open(strFileName, FileMode.Create, FileAccess.Write)) 
        {
            bfEmployees.Serialize(fsEmployees, employees);
        }
    }
}

The nodes of a linked list go from the head to the tail. Probably the easiest way to add a node is to create the last one. This is done by calling the overloaded AddLast() method of the linked list.

ApplicationPractical Learning: Adding a New Node to a Linked List

  1. Display the Employees form and double-click the New Employee button
  2. Change the document as follows:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace LambdaPropertiesManagement1
    {
        public partial class Employees : Form
        {
            public Employees()
            {
                InitializeComponent();
            }
    
            private void ShowEmployees()
            {
            }
    
            private void btnNewEmployee_Click(object sender, EventArgs e)
            {
                EmployeeEditor editor = new EmployeeEditor();
                BinaryFormatter bfEmployees = new BinaryFormatter();
                LinkedList<Employee> employees = new LinkedList<Employee>();
                string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Employees.mpl";
    
                if (File.Exists(strFileName))
                {
                    using (FileStream fsEmployees = File.Open(strFileName, FileMode.Open, FileAccess.Read))
                    {
                        employees = (LinkedList<Employee>)bfEmployees.Deserialize(fsEmployees);
                    }
                }
    
                if (editor.ShowDialog() == DialogResult.OK)
                {
                    if (string.IsNullOrEmpty(editor.txtEmployeeNumber.Text))
                    {
                        MessageBox.Show("You must provide an employee number.",
                                        "Lambda Properties Management",
                                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return;
                    }
    
                    Employee empl = new Employee();
    
                    empl.EmployeeNumber = editor.txtEmployeeNumber.Text;
                    empl.FirstName = editor.txtFirstName.Text;
                    empl.LastName = editor.txtLastName.Text;
                    empl.Title = editor.txtEmployeeTitle.Text;
    
                    LinkedListNode<Employee> employee = new LinkedListNode<Employee>(empl);
                    employees.AddLast(employee);
    
                    using (FileStream fsEmployees = File.Open(strFileName, FileMode.Create, FileAccess.Write))
                    {
                        bfEmployees.Serialize(fsEmployees, employees);
                    }
                }
    
                ShowEmployees();
            }
        }
    }
  3. Save all

Adding the First Node

As opposed to a head, a linked list has a tail, which is considered the first node. To add the first node to a linked list, you can call the AddFirst() method of the LinkedList class.

Inserting a Node Before Another One

Every node of a linked list has a specific reference based on its position. Using the reference of a node, you can add a new one before that one. This operation is carried by the AddBefore() method of the LinkedList class.

Inserting a Node After a Referenced One

Another operation performed on a known node is to create a new node after that one. This operation can be performed using the AddAfter() method of the LinkedList class. It is overloaded by two versions whose syntaxes are:

public void AddAfter(LinkedListNode<T> node, LinkedListNode<T> newNode);
public LinkedListNode<T> AddAfter(LinkedListNode<T> node, T value);

Our application is a database for a house rental company. The properties include apartments, condominiums, townhouses, and single families:

Apartments and Condominiums

Townhouses

Single Family

We will create a listing for the properties. For better organization, we will group the properties by categories. That is, our list of properties will be made of sections: the apartments in one section, the condominiums in a section, the townhouses in their section, and the single families in a section. Since many apartments belong to the same building, when that is the case, we will create a section for a building where the apartments share the same address. Since there are many apartment buildings, the apartments that belong together will be put in the same section. This means that, to group the apartments, we will use their common address.

We will proceed as follows:

  • When the application, there is no list and there is no file for the list of properties. Therefore, when the first property is created, it is simply added to the list. We will call the LinkedList.AddLast() method to create the first node
  • When a property is created, we will check if there is already a file that holds the list of properties
    • If there is no file for the properties, we will call the AddLast() method to create the property and create the new file
    • If there is already a file for the properties, check each property type:
      • If there is not yet a property of the same type as the one that is being added, simply call the AddLast() method and add the new property to the end of the list
      • If there is already at least one property that is the same type as the one being added, add the new property to the end of the section for that category
    • If the property being added is an apartment:
      • If there is at least one apartment in the listing, check its address:
        • If the new apartment has the same address as an apartment record in the file, add the new record after the existing one
        • If the new apartment has a different address, add it after the existing apartment(s)
 
 
 

Exploring the Nodes of a Linked List

 

Iterating Through a Linked List

As you may know already, every collection class in the .NET Framework implements the IEnumerable<> generic interface. This makes it possible to use foreach to iterate through the collection.

ApplicationPractical Learning: Iterating Through a Linked List

  1. Display the Employees form and double-click an unoccupied area of its body
  2. Change the file as follows:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace LambdaPropertiesManagement1
    {
        public partial class Employees : Form
        {
            public Employees()
            {
                InitializeComponent();
            }
    
            private void ShowEmployees()
            {
                BinaryFormatter bfEmployees = new BinaryFormatter();
                LinkedList<Employee> employees = new LinkedList<Employee>();
                string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Employees.mpl";
    
                if (File.Exists(strFileName))
                {
                    using (FileStream fsEmployees = File.Open(strFileName, FileMode.Open, FileAccess.Read))
                    {
                        employees = (LinkedList<Employee>)bfEmployees.Deserialize(fsEmployees);
                        lvwEmployees.Items.Clear();
    
                        foreach (Employee empl in employees)
                        {
                            ListViewItem lviEmployee = new ListViewItem(empl.EmployeeNumber);
    
                            lviEmployee.SubItems.Add(empl.FirstName);
                            lviEmployee.SubItems.Add(empl.LastName);
                            lviEmployee.SubItems.Add(empl.Title);
              
                            lvwEmployees.Items.Add(lviEmployee);
                        }
                    }
                }
            }
    
    	... No Change
    	    	    
            private void Employees_Load(object sender, EventArgs e)
            {
                ShowEmployees();
            }
        }
    }
  3. Return to the Employees form and double-click the Close button
  4. Implement the event as follows:
    private void btnClose_Click(object sender, EventArgs e)
    {
        Close();
    }
  5. Display the Rental Property Editor dialog box and double-click an unoccupied area of its body
  6. Change the Load event as follows:
    private void RentalPropertyEditor_Load(object sender, EventArgs e)
    {
        string strPropertyType = "";
        BinaryFormatter bfProperty = new BinaryFormatter();
        LinkedList<RentalProperty> properties = new LinkedList<RentalProperty>();
        PictureFile = "C:\\Microsoft Visual C# Application Design\\Lambda Properties Management\\000-000.jpg";
        string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Properties.pts";
    
        if (File.Exists(strFileName) == true)
        {
            using (FileStream fsProperties = new FileStream(strFileName,
                                                            FileMode.Open,
                                                            FileAccess.Read))
            {
                properties = (LinkedList<RentalProperty>)bfProperty.Deserialize(fsProperties);
    
                cbxPropertiesTypes.Items.Clear();
    
                foreach (RentalProperty house in properties)
                {
                    if (!cbxPropertiesTypes.Items.Contains(house.PropertyType))
                    {
                        cbxPropertiesTypes.Items.Add(house.PropertyType);
                        strPropertyType = house.PropertyType;
                    }
                }
            }
    
            cbxPropertiesTypes.Text = strPropertyType;
        }
    }
  7. Display the Tenants Registrations form and double-click the New Registration button
  8. Change the document as follows:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.IO;
    using System.Windows.Forms;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace LambdaPropertiesManagement1
    {
        public partial class TenantsRegistrations : Form
        {
            public TenantsRegistrations()
            {
                InitializeComponent();
            }
    
            private void ShowRegistrations()
            {
            }
    
            private void btnNewRegistration_Click(object sender, EventArgs e)
            {
                int iRegistrationNumber = 1000;
                BinaryFormatter bfRegistrations = new BinaryFormatter();
                TenantRegistrationEditor editor = new TenantRegistrationEditor();
                LinkedList<TenantRegistration> registrations = new LinkedList<TenantRegistration>();
                string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Registrations.rgs";
    
                if (File.Exists(strFileName))
                {
                    using (FileStream fsRegistrations = File.Open(strFileName, FileMode.Open, FileAccess.Read))
                    {
                        registrations = (LinkedList<TenantRegistration>)bfRegistrations.Deserialize(fsRegistrations);
    
                        foreach (TenantRegistration regs in registrations)
                        {
                            iRegistrationNumber = regs.RegistrationNumber;
                        }
                    }
                }
    
                editor.txtRegistrationNumber.Text = (iRegistrationNumber + 1).ToString();
    
                if (editor.ShowDialog() == DialogResult.OK)
                {
                    if (string.IsNullOrEmpty(editor.txtRegistrationNumber.Text))
                    {
                        MessageBox.Show("You must provide a registration number.",
    	                            "Lambda Properties Management",
            	                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return;
                    }
    
                    TenantRegistration regist = new TenantRegistration()
                    {
                        RegistrationNumber = int.Parse(editor.txtRegistrationNumber.Text),
                        RegistrationDate   = editor.dtpRegistrationDate.Value,
                        EmployeeNumber     = editor.txtEmployeeNumber.Text,
                        TenantCode         = editor.txtTenantCode.Text,
                        FirstName          = editor.txtFirstName.Text,
                        LastName           = editor.txtLastName.Text,
                        MaritalStatus      = editor.cbxMaritalStatus.Text,
                        NumberOfChildren   = ushort.Parse(editor.txtNumberOfChildren.Text),
                        PhoneNumber        = editor.txtPhoneNumber.Text,
                        EmailAddress       = editor.txtEmailAddress.Text,
                        PropertyNumber     = editor.txtPhoneNumber.Text,
                        RentStartDate      = editor.dtpRentStartDate.Value
                    };
                    LinkedListNode<TenantRegistration> registration = new LinkedListNode<TenantRegistration>(regist);
    
                    registrations.AddLast(registration);
    
                    using (FileStream fsRegistrations = File.Open(strFileName, FileMode.Create, FileAccess.Write))
                    {
                        bfRegistrations.Serialize(fsRegistrations, registrations);
                    }
                }
    
                ShowRegistrations();
            }
        }
    }
  9. Display the Payments form and double-click the New Payment button
  10. Change the document as follows:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.IO;
    using System.Windows.Forms;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace LambdaPropertiesManagement1
    {
        public partial class Payments : Form
        {
            public Payments()
            {
                InitializeComponent();
            }
    
            private void ShowPayments()
            {
            }
    
            private void btnNewPayment_Click(object sender, EventArgs e)
            {
                int iReceiptNumber = 100000;
                PaymentEditor editor = new PaymentEditor();
                BinaryFormatter bfPayments = new BinaryFormatter();
                LinkedList<Payment> payments = new LinkedList<Payment>();
                string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Payments.pmt";
                
                if (File.Exists(strFileName))
                {
                    using (FileStream fsPayments = File.Open(strFileName, FileMode.Open, FileAccess.Read))
                    {
                        payments = (LinkedList<Payment>)bfPayments.Deserialize(fsPayments);
                        
                        foreach (Payment pmt in payments)
                        {
                            iReceiptNumber = pmt.ReceiptNumber;
                        }
                    }
                }
                
                editor.txtReceiptNumber.Text = (iReceiptNumber + 1).ToString();
    
                if (editor.ShowDialog() == DialogResult.OK)
                {
                    if (string.IsNullOrEmpty(editor.txtReceiptNumber.Text))
                    {
                        MessageBox.Show("You must provide a receister number.",
                                        "Lambda Properties Management",
                                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return;
                    }
    
                    if (string.IsNullOrEmpty(editor.txtEmployeeNumber.Text))
                    {
                        MessageBox.Show("You must specify the employee (employee number) who processed the payment.",
                                        "Lambda Properties Management",
                                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return;
                    }
    
                    if (string.IsNullOrEmpty(editor.txtRegistrationNumber.Text))
                    {
                        MessageBox.Show("You must specify the registration (Registration Number) whose payment was made.",
                                        "Lambda Properties Management",
                                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return;
                    }
    
                    if (string.IsNullOrEmpty(editor.txtAmountPaid.Text))
                    {
                        MessageBox.Show("You must specify the amount that was paid.",
                                        "Lambda Properties Management",
                                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return;
                    }
    
                    payments.AddLast(new Payment()
                    { 
                        ReceiptNumber      = int.Parse(editor.txtReceiptNumber.Text),
                        PaymentDate        = editor.dtpPaymentDate.Value,
                        EmployeeNumber     = editor.txtEmployeeNumber.Text,
                        RegistrationNumber = int.Parse(editor.txtRegistrationNumber.Text),
                        PaymentAmount      = double.Parse(editor.txtAmountPaid.Text),
                        Notes              = editor.txtNotes.Text
                    });
    
                    using (FileStream fsPayments = File.Open(strFileName, FileMode.Create, FileAccess.Write))
                    {
                        bfPayments.Serialize(fsPayments, payments);
                    }
                }
            }
        }
    }
  11. Save all

The Value of a Node

Probably the most important aspect of a node is its value. To support it, the LinkedListNode class has a property named Value:

public T Value { get; set; }

Because this is a read-write property, you can use its write-accessory to specify or change its value. On the other hand, you can access the value of a node using this property.

ApplicationPractical Learning: Accessing the Value of a Linked List Node

  1. Display the Rental Properties form and double-click an unoccupied area of its body
  2. Change the document as follows:
    private void ShowRentalProperties()
    {
        BinaryFormatter bfProperty = new BinaryFormatter();
        LinkedList<RentalProperty> properties = new LinkedList<RentalProperty>();
        string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Properties.pts";
    
        if (File.Exists(strFileName) == true)
        {
            using (FileStream fsProperties = new FileStream(strFileName,
                                                                FileMode.Open,
                                                                FileAccess.Read))
            {
                // If some properties were created already,
                // get them and store them in the collection
                properties = (LinkedList<RentalProperty>)bfProperty.Deserialize(fsProperties);
    
                // First, empty the list view
                lvwRentalProperties.Items.Clear();
    
                // Visit each property in the collection and add it to the list view
                foreach (RentalProperty house in properties)
                {
                    LinkedListNode<RentalProperty> propertyNode = new LinkedListNode<RentalProperty>(house);
    
                    ListViewItem lviProperty = new ListViewItem(propertyNode.Value.PropertyNumber);
                    lviProperty.SubItems.Add(propertyNode.Value.PropertyType.ToString());
                    lviProperty.SubItems.Add(propertyNode.Value.Address.ToString());
                    lviProperty.SubItems.Add(propertyNode.Value.UnitNumber.ToString());
                    lviProperty.SubItems.Add(propertyNode.Value.City);
                    lviProperty.SubItems.Add(propertyNode.Value.State.ToString());
                    lviProperty.SubItems.Add(propertyNode.Value.ZIPCode.ToString());
                    lviProperty.SubItems.Add(propertyNode.Value.Stories.ToString());
                    lviProperty.SubItems.Add(propertyNode.Value.Bedrooms.ToString());
                    lviProperty.SubItems.Add(propertyNode.Value.Bathrooms.ToString("F"));
                    lviProperty.SubItems.Add(propertyNode.Value.MonthlyRate.ToString());
                    lviProperty.SubItems.Add(propertyNode.Value.SecurityDeposit.ToString());
                    lviProperty.SubItems.Add(propertyNode.Value.OccupancyStatus);
    
                    lvwRentalProperties.Items.Add(lviProperty);
                }
            }
        }
    }
    
    private void RentalProperties_Load(object sender, EventArgs e)
    {
        ShowRentalProperties();
    }
  3. Return to the Rental Properties form and click the list view
  4. On the Properties window, click the Events button and double-click Leave
  5. Implement the event as follows:
    private void lvwRentalProperties_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
    {
        string strFileName = "C:\\Microsoft Visual C# Application Design\\Lambda Properties Management\\" + e.Item.SubItems[0].Text + ".jpg";
    
        if (File.Exists(strFileName))
            pbxProperty.Image = Image.FromFile(strFileName);
        else
            pbxProperty.Image = Image.FromFile("C:\\Microsoft Visual C# Application Design\\Lambda Properties Management\\000-000.jpg");
    }

Finding a Node

The LinkedList class inherits the Contains method from the ICollection interface. Its syntax is:

public bool Contains(T value);

This method checks whether the linked list contains the (a) node that has the value passed as argument. If that node is found, the method returns true. Otherwise it returns false. To get the actual node that has a value, call the Find() method. Its syntax is:

public LinkedListNode<T> Find(T value);

When this method is called, it starts looking for the value in the linked list. If it finds it, it returns its node. If there is more than one node with that value, the method returns only the first node that has that value. If the list contains more than one node that has the value but you prefer to use the last node, call the FindLast() method.

public LinkedListNode<T> FindLast(T value);

These two methods are ready to work on primitive types. If you are using your own class for the type of node, you should (must) override the Equals() method.

ApplicationPractical Learning: Adding an Item to a Linked List

  1. Return to the Rental Properties form and double-click the New Rental Property button
  2. Change the document as follows:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.IO;
    using System.Windows.Forms;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace LambdaPropertiesManagement1
    {
        public partial class RentalProperties : Form
        {
            public RentalProperties()
            {
                InitializeComponent();
            }
    
            private void ShowRentalProperties()
            {
            }
    
            private void btnNewRentalProperty_Click(object sender, EventArgs e)
            {
                bool propertySameTypeExists = false,
                     propertySameAddressExists = false;
                RentalProperty prop = new RentalProperty();
                BinaryFormatter bfmProperty = new BinaryFormatter();
                RentalProperty propertySameType = new RentalProperty();
                RentalPropertyEditor editor = new RentalPropertyEditor();
                RentalProperty propertySameAddress = new RentalProperty();
                LinkedList<RentalProperty> properties = new LinkedList<RentalProperty>();
                string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Properties.pts";
    
                editor.btnFind.Visible = false;
                editor.txtPropertyNumber.Enabled = true;
    
                if (editor.ShowDialog() == DialogResult.OK)
                {
                    prop.PropertyNumber = editor.txtPropertyNumber.Text;
                    prop.PropertyType = editor.cbxPropertiesTypes.Text;
                    prop.Address = editor.txtAddress.Text;
                    prop.UnitNumber = editor.txtUnitNumber.Text;
                    prop.City = editor.txtCity.Text;
                    prop.State = editor.txtState.Text;
                    prop.ZIPCode = editor.txtZIPCode.Text;
                    prop.Stories = short.Parse(editor.txtStories.Text);
                    prop.Bedrooms = short.Parse(editor.txtBedrooms.Text);
                    prop.Bathrooms = float.Parse(editor.txtBathrooms.Text);
                    prop.MonthlyRate = double.Parse(editor.txtMonthlyRate.Text);
                    prop.SecurityDeposit = double.Parse(editor.txtSecurityDeposit.Text);
                    prop.OccupancyStatus = editor.cbxOccupanciesStatus.Text;
                    
                    if (!editor.PictureFile.Equals(""))
                    {
                        FileInfo flePicture = new FileInfo(editor.PictureFile);
                        flePicture.CopyTo("C:\\Microsoft Visual C# Application Design\\Lambda Properties Management\\" +
                                          editor.txtPropertyNumber.Text + flePicture.Extension, true);
                        prop.PictureFile = "C:\\Microsoft Visual C# Application Design\\Lambda Properties Management\\" +
                                           editor.txtPropertyNumber.Text + flePicture.Extension;
                    }
                    else
                        prop.PictureFile = "C:\\Microsoft Visual C# Application Design\\Lambda Properties Management\\000-000.jpg";
                    
                    if (File.Exists(strFileName) == true)
                    {
                        // If the list of properties exists already,
                        // get it and store it in the Properties collection
                        using (FileStream fsProperties = new FileStream(strFileName,
                                                        FileMode.Open,
                                                    FileAccess.Read))
                        {
                            // Store the list of properties in the collection
                            properties = (LinkedList<RentalProperty>)bfmProperty.Deserialize(fsProperties);
                        }
    
                        // Check each Rental Property record
                        foreach (RentalProperty current in properties)
                        {
                            // Look for an existing Property that has the same Type as the one created by the user
                            // If you find a property with the current Type, ...
                            if (current.PropertyType == prop.PropertyType)
                            {
                                if (current.Address == prop.Address)
                                {
                                    // ... get a reference to that node
                                    propertySameAddress = current;
                                    // Make a note that we have found a property with this type
                                    propertySameAddressExists = true;
                                }
                                else
                                {
                                    propertySameType = current;
                                    propertySameTypeExists = true;
                                }
                            }
                        }
    
                        // If you found a property with this type
                        if (propertySameAddressExists == true)
                        {
                            // ... locate the last property of this type
                            // LinkedListNode<RentalProperty> foundProperty = new LinkedListNode<RentalProperty>(propertySameType);
                            LinkedListNode<RentalProperty> lastPropertyAddress = properties.FindLast(propertySameAddress);
                            // Add/Insert the new property AFTER the LAST in this section (property type)
                            properties.AddAfter(lastPropertyAddress, prop);
                        }
                        else if (propertySameTypeExists == true)
                        {
                            // ... locate the last property of this type
                            // LinkedListNode<RentalProperty> foundProperty = new LinkedListNode<RentalProperty>(propertySameType);
                            LinkedListNode<RentalProperty> lastPropertyType = properties.FindLast(propertySameType);
                            // Add/Insert the new property AFTER the LAST in this section (property type)
                            properties.AddAfter(lastPropertyType, prop);
                        }
                        else
                        {
                            // If there is no property with the current Type,
                            // Add the new property at the end of the list
                            properties.AddLast(prop);
                        }
                    }
                    else
                    {
                        // If no previous Properties file was created,
                        // add the new property as the first in the collection/list
                        properties.AddFirst(prop);
                    }
    
                    // Save the list of properties
                    using (FileStream fsProperties = new FileStream(strFileName,
                                                                    FileMode.Create,
                                                                    FileAccess.Write))
                    {
                        bfmProperty.Serialize(fsProperties, properties);
                    }
                }
    
                // Show the list of properties
                ShowRentalProperties();  
            }
        }
    }

Exploring the Nodes of a Linked List

The LinkedList class doesn't implement the IList interface, which means it doesn't have an Item property, but it implements the IEnumerable interface. This makes it possible to use foreach to get to access each node. The first node of a linked list is represented by a read-only property named First. Its syntax is:

public LinkedListNode<T> First { get; }

The last node is represented by a read-only property of the same name and that, too, is a LinkedListNode object:

public LinkedListNode<T> Last { get; }

The node next to an existing node is represented by a read-only property named Next:

public LinkedListNode<T> Next { get; }

The node previous to an existing one is represented by the read-only Previous property:

public LinkedListNode Previous { get; }

In both cases, you need a node as reference.

ApplicationPractical Learning: Accessing the Individual Nodes of a Linked List

  1. Display the Payments form and double-click an unoccupied area of its body
  2. Change the document as follows:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.IO;
    using System.Windows.Forms;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace LambdaPropertiesManagement1
    {
        public partial class Payments : Form
        {
            public Payments()
            {
                InitializeComponent();
            }
    
            private void ShowPayments()
            {
                ListViewItem lviPayment = null;
                PaymentEditor editor = new PaymentEditor();
                BinaryFormatter bfPayments = new BinaryFormatter();
                LinkedList<Payment> payments = new LinkedList<Payment>();
                string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Payments.pmt";
    
                if (File.Exists(strFileName))
                {
                    using (FileStream fsPayments = File.Open(strFileName, FileMode.Open, FileAccess.Read))
                    {
                        payments = (LinkedList<Payment>)bfPayments.Deserialize(fsPayments);
    
                        lvwPayments.Items.Clear();
    
                        LinkedListNode<Payment> payment = payments.First;
    
                        lviPayment = new ListViewItem(payment.Value.ReceiptNumber.ToString());
    
                        lviPayment.SubItems.Add(payment.Value.PaymentDate.ToShortDateString());
                        lviPayment.SubItems.Add(payment.Value.EmployeeNumber);
                        lviPayment.SubItems.Add(payment.Value.RegistrationNumber.ToString());
                        lviPayment.SubItems.Add(payment.Value.PaymentAmount.ToString());
                        lviPayment.SubItems.Add(payment.Value.Notes);
                        lvwPayments.Items.Add(lviPayment);
    
                        for (int i = 1; i < payments.Count; i++ )
                        {
                            payment = payment.Next;
    
                            lviPayment = new ListViewItem(payment.Value.ReceiptNumber.ToString());
    
                            lviPayment.SubItems.Add(payment.Value.PaymentDate.ToShortDateString());
                            lviPayment.SubItems.Add(payment.Value.EmployeeNumber);
                            lviPayment.SubItems.Add(payment.Value.RegistrationNumber.ToString());
                            lviPayment.SubItems.Add(payment.Value.PaymentAmount.ToString());
                            lviPayment.SubItems.Add(payment.Value.Notes);
                            lvwPayments.Items.Add(lviPayment);
                        }
                    }
                }
            }
    
            private void Payments_Load(object sender, EventArgs e)
            {
                ShowPayments();
            }
        }
    }

Linked Lists and the LINQ

Like all collection classes of the System.Collections.Generic namespace, the LinkedList class has many extension methods that make it possible to use the language integrated query (LINQ) in a linked list collection.

ApplicationPractical Learning: Using LINQ in a Linked List

  1. Display the Payment Editor form and click the Employee # text box
  2. On the Properties window, click the Events button and double-click Leave
  3. Implement the event as follows:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.IO;
    using System.Windows.Forms;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace LambdaPropertiesManagement1
    {
        public partial class PaymentEditor : Form
        {
            public TenantRegistrationEditor()
            {
                InitializeComponent();
            }
    
            private void txtEmployeeNumber_Leave(object sender, EventArgs e)
            {
                BinaryFormatter bfEmployees = new BinaryFormatter();
                LinkedList<Employee> employees = new LinkedList<Employee>();
                string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Employees.mpl";
    
                if (File.Exists(strFileName))
                {
                    using (FileStream fsEmployees = File.Open(strFileName, FileMode.Open, FileAccess.Read))
                    {
                        employees = (LinkedList<Employee>)bfEmployees.Deserialize(fsEmployees);
    
                        IEnumerable<Employee> clerks = from staffMember
                                                       in employees
                                                       where staffMember.EmployeeNumber == txtEmployeeNumber.Text
                                                       select staffMember;
    
                        foreach(var employee in clerks)
                            txtEmployeeName.Text = employee.FirstName + " " + employee.LastName;
                    }
                }
            }
        }
    }
  4. Return to the Payments form and click the Registation # text box
  5. In the Events section of  the Properties window, double-click Leave
  6. Implement the event as follows:
    private void txtRegistrationNumber_Leave(object sender, EventArgs e)
    {
        LinkedList<TenantRegistration> registrations;
        BinaryFormatter bfRegistrations = new BinaryFormatter();
        string strRegistrationsFile = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Registrations.rgs";
    
        if (File.Exists(strRegistrationsFile))
        {
            using (FileStream fsRegistrations = File.Open(strRegistrationsFile, FileMode.Open, FileAccess.Read))
            {
                registrations = (LinkedList<TenantRegistration>)bfRegistrations.Deserialize(fsRegistrations);
    
                var allocations = from alloc
                                  in registrations
                                  select new
                                  {
                                        Registration = string.Concat("Regist #: ", alloc.RegistrationNumber.ToString(),
                                                                     ", Tenant #: ", alloc.TenantCode, ", ", 
                                                                     alloc.FirstName, " ", alloc.LastName, ", ",
                                                                     alloc.MaritalStatus, ", ", alloc.NumberOfChildren,
                                                                     " child(ren)", Environment.NewLine,
                                                                     "Started on ", alloc.RentStartDate.ToLongDateString())
                                  };
    
                foreach (var regist in allocations)
                    txtRegistrationDetails.Text = regist.Registration;
            }
        }
    }
  7. Return to the Payments form and click the list view
  8. In the Events section of the Properties window, double-click ItemSelectedChanged
  9. Implement the event as follows:
    private void lvwPayments_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
    {
        LinkedList<TenantRegistration> registrations;
        BinaryFormatter bfEmployees = new BinaryFormatter();
        BinaryFormatter bfRegistrations = new BinaryFormatter();
        LinkedList<Employee> employees = new LinkedList<Employee>();
        string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Employees.mpl";
        string strRegistrationsFile = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Registrations.rgs";
    
        if (File.Exists(strFileName))
        {
            using (FileStream fsEmployees = File.Open(strFileName, FileMode.Open, FileAccess.Read))
            {
                employees = (LinkedList<Employee>)bfEmployees.Deserialize(fsEmployees);
    
                IEnumerable<Employee> clerks = from staffMember
                                                in employees
                                                where staffMember.EmployeeNumber == e.Item.SubItems[2].Text
                                                select staffMember;
    
                foreach (var employee in clerks)
                    txtEmployeeName.Text = employee.FirstName + " " + employee.LastName;
            }
        }
    
    
        if (File.Exists(strRegistrationsFile))
        {
            using (FileStream fsRegistrations = File.Open(strRegistrationsFile, FileMode.Open, FileAccess.Read))
            {
                registrations = (LinkedList<TenantRegistration>)bfRegistrations.Deserialize(fsRegistrations);
            }
    
            var rentAllocations = from allocation in registrations
                                  where allocation.RegistrationNumber == int.Parse(e.Item.SubItems[3].Text)
                                  select new
                                  {
                                       Registration = string.Concat("Registration Date: ", allocation.RegistrationDate,
                                                                    "Tenant Code: ", allocation.TenantCode, ", ",
                                                                    allocation.FirstName, " ", allocation.LastName, ", ",
                                                                    allocation.MaritalStatus, ", ",
                                                                    allocation.NumberOfChildren, " child(ren), ", Environment.NewLine,
                                                                    "Start Date: ", allocation.RentStartDate.ToLongDateString())
                                  };
    
            foreach (var registration in rentAllocations)
                txtRegistrationDetails.Text = registration.Registration;
        }
    }
  10. Return to the Payments form and double-click the Close button
  11. Change the document as follows:
    private void btnClose_Click(object sender, EventArgs e)
    {
        Close();
    }
  12. Display the Tenant Registration Editor and click the Employee # text box
  13. In the Events section of the Properties window, double-click Leave
  14. Implement the event as follows:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.IO;
    using System.Windows.Forms;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace LambdaPropertiesManagement1
    {
        public partial class TenantRegistrationEditor : Form
        {
            public TenantRegistrationEditor()
            {
                InitializeComponent();
            }
    
            private void txtEmployeeNumber_Leave(object sender, EventArgs e)
            {
                BinaryFormatter bfEmployees = new BinaryFormatter();
                LinkedList<Employee> employees = new LinkedList<Employee>();
                string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Employees.mpl";
    
                if (File.Exists(strFileName))
                {
                    using (FileStream fsEmployees = File.Open(strFileName, FileMode.Open, FileAccess.Read))
                    {
                        employees = (LinkedList<Employee>)bfEmployees.Deserialize(fsEmployees);
    
                        IEnumerable<Employee> clerks = from staffMember
                                                       in employees
                                                       where staffMember.EmployeeNumber == txtEmployeeNumber.Text
                                                       select staffMember;
    
                        foreach(var employee in clerks)
                            txtEmployeeName.Text = employee.FirstName + " " + employee.LastName;
                    }
                }
            }
        }
    }
  15. Return to the Tenant Registration Editor and click the Property # text box
  16. In the Events section of  the Properties window, double-click Leave
  17. Implement the event as follows:
    private void txtPropertyNumber_Leave(object sender, EventArgs e)
    {
        BinaryFormatter bfProperty = new BinaryFormatter();
        LinkedList<RentalProperty> properties = new LinkedList<RentalProperty>();
        string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Properties.pts";
    
        if (File.Exists(strFileName) == true)
        {
            using (FileStream fsProperties = new FileStream(strFileName,
                                                                FileMode.Open,
                                                                FileAccess.Read))
            {
                properties = (LinkedList<RentalProperty>)bfProperty.Deserialize(fsProperties);
    
                var houses = from house
                             in properties
                             where house.PropertyNumber == txtPropertyNumber.Text
                             select new
                             {
                                 Locality = string.Concat(house.City, "(", house.State, ")"),
                                 Beds     = string.Concat(house.Bedrooms, " bedroom(s)"),
                                 Baths    = string.Concat(house.Bathrooms, " bathroom(s)"),
                                 Rent     = string.Concat("Rent = ", house.MonthlyRate.ToString(), "/month"),
                                 Deposit  = string.Concat("Security Deposit = ", house.SecurityDeposit.ToString())
                             };
    
                foreach (var prop in houses)
                    txtPropertyDetails.Text = "Located in " + prop.Locality + Environment.NewLine  +
                                              prop.Beds.ToString() + " , " +
                                              prop.Baths + Environment.NewLine +
                                              prop.Rent + Environment.NewLine +
                                              prop.Deposit;
            }
        }
    }
  18. Display the New Rental Property dialog box and add a Button to the right side of the Property Number text box
  19. Change the button's properties as follows:
    (Name): btnFind
    Text:      Find

    Lambda Properties Management - New Rental Property

  20. Double-click the new Find button and implement its event as follows:
    private void btnFind_Click(object sender, EventArgs e)
    {
        BinaryFormatter bfmProperty = new BinaryFormatter();
        LinkedList<RentalProperty> properties = new LinkedList<RentalProperty>();
        string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Properties.pts";
    
        if (string.IsNullOrEmpty(txtPropertyNumber.Text))
        {
            MessageBox.Show("You must enter a property number.",
                    "Lambda Properties Management",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            return;
        }
    
        if (File.Exists(strFileName) == true)
        {
            using (FileStream fsProperties = new FileStream(strFileName,
                                                    FileMode.Open,
                                                FileAccess.Read))
            {
                properties = (LinkedList<RentalProperty>)bfmProperty.Deserialize(fsProperties);
    
                IEnumerable<RentalProperty> houses = (from house
                                                      in properties
                                                      select house).Where<RentalProperty>(propNumber => propNumber.PropertyNumber == txtPropertyNumber.Text);
    
                foreach (RentalProperty house in houses )
                {
                    cbxPropertiesTypes.Text = house.PropertyType;
                    txtAddress.Text = house.Address;
                    txtUnitNumber.Text = house.UnitNumber;
                    txtCity.Text = house.City;
                    txtState.Text = house.State;
                    txtZIPCode.Text = house.ZIPCode;
                    txtStories.Text = house.Stories.ToString();
                    txtBedrooms.Text = house.Bedrooms.ToString();
                    txtBathrooms.Text = house.Bathrooms.ToString();
                    txtMonthlyRate.Text = house.MonthlyRate.ToString();
                    txtSecurityDeposit.Text = house.SecurityDeposit.ToString();
                    cbxOccupanciesStatus.Text = house.OccupancyStatus;
                }
            }
        }
    }
  21. Display the Tenants Registrations form and double-click an unoccupied area of its body
  22. Change the document as follows:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.IO;
    using System.Windows.Forms;
    using System.Runtime.Serialization.Formatters.Binary;
    
    namespace LambdaPropertiesManagement1
    {
        public partial class TenantsRegistrations : Form
        {
            public TenantsRegistrations()
            {
                InitializeComponent();
            }
    
            private void ShowRegistrations()
            {
                LinkedList<Employee> employees;
                LinkedList<TenantRegistration> registrations;
                BinaryFormatter bfProperty = new BinaryFormatter();
                BinaryFormatter bfEmployees = new BinaryFormatter();
                BinaryFormatter bfRegistrations = new BinaryFormatter();
                TenantRegistrationEditor editor = new TenantRegistrationEditor();
                string strEmployeesFile = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Employees.mpl";
                string strRegistrationsFile = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Registrations.rgs";
    
                if (File.Exists(strRegistrationsFile))
                {
                    using (FileStream fsRegistrations = File.Open(strRegistrationsFile, FileMode.Open, FileAccess.Read))
                    {
                        registrations = (LinkedList<TenantRegistration>)bfRegistrations.Deserialize(fsRegistrations);
                    }
    
                    using (FileStream fsEmployees = File.Open(strEmployeesFile, FileMode.Open, FileAccess.Read))
                    {
                        employees = (LinkedList<Employee>)bfEmployees.Deserialize(fsEmployees);
                    }
    
                    var rentAllocations = from allocation in registrations
                                          join staff in employees on allocation.EmployeeNumber equals staff.EmployeeNumber
                                          select new
                                          {
                                              RegistrationNumber = allocation.RegistrationNumber,
                                              RegistrationDate   = allocation.RentStartDate,
                                              Employee           = string.Concat(staff.EmployeeNumber, ": ", staff.FirstName, " ", staff.LastName),
                                              TenantCode         = allocation.TenantCode,
                                              FirstName          = allocation.FirstName,
                                              LastName           = allocation.LastName,
                                              MaritalStatus      = allocation.MaritalStatus,
                                              NumberOfChildren   = allocation.NumberOfChildren,
                                              PhoneNumber        = allocation.PhoneNumber,
                                              EmailAddress       = allocation.EmailAddress,
                                              House              = allocation.PropertyNumber,
                                              StartDate          = allocation.RentStartDate.ToLongDateString()
                                          };
                    lvwRegistrations.Items.Clear();
    
                    foreach (var registration in rentAllocations)
                    {
                        ListViewItem lviRegistration = new ListViewItem(registration.RegistrationNumber.ToString());
    
                        lviRegistration.SubItems.Add(registration.RegistrationDate.ToShortDateString());
                        lviRegistration.SubItems.Add(registration.Employee);
                        lviRegistration.SubItems.Add(registration.TenantCode);
                        lviRegistration.SubItems.Add(registration.FirstName);
                        lviRegistration.SubItems.Add(registration.LastName);
                        lviRegistration.SubItems.Add(registration.MaritalStatus);
                        lviRegistration.SubItems.Add(registration.NumberOfChildren.ToString());
                        lviRegistration.SubItems.Add(registration.PhoneNumber);
                        lviRegistration.SubItems.Add(registration.EmailAddress);
                        lviRegistration.SubItems.Add(registration.House);
                        lviRegistration.SubItems.Add(registration.StartDate);
    
                        lvwRegistrations.Items.Add(lviRegistration);
                    }
                }
            }
    
            private void TenantsRegistrations_Load(object sender, EventArgs e)
            {
                ShowRegistrations();
            }
        }
    }
  23. Return to the Tenants Registrations form and double-click the Close button
  24. Change the document as follows:
    private void btnClose_Click(object sender, EventArgs e)
    {
        Close();
    }
  25. Save all

Maintenance of Nodes of a Linked List

 

Updating the Nodes of a Linked List

The LinkedList class provides many options to change a node. You can access the Value property of a LinkedListNode and change it. Probably the simplest way consistst of accessing a node from iterating in the collections, and then changing the value of the desired node.

ApplicationPractical Learning: Updating a Node

  1. Return to the Rental Properties form and double-click the Update Rental Property button
  2. Implement the Click event as follows:
    private void btnUpdateRentalProperty_Click(object sender, EventArgs e)
    {
        BinaryFormatter bfmProperty = new BinaryFormatter();
        RentalPropertyEditor editor = new RentalPropertyEditor();
        LinkedList<RentalProperty> properties = new LinkedList<RentalProperty>();
        string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Properties.pts";
    
        editor.btnFind.Visible = true;
    
        if (File.Exists(strFileName) == true)
        {
            using (FileStream fsProperties = new FileStream(strFileName,
                                                            FileMode.Open,
                                                            FileAccess.Read))
            {
                properties = (LinkedList<RentalProperty>)bfmProperty.Deserialize(fsProperties);
            }
    
            if (editor.ShowDialog() == DialogResult.OK)
            {
                foreach (RentalProperty prop in properties)
                {
                    if (prop.PropertyNumber == editor.txtPropertyNumber.Text)
                    {
                        prop.PropertyType    = editor.cbxPropertiesTypes.Text;
                        prop.Address         = editor.txtAddress.Text;
                        prop.UnitNumber      = editor.txtUnitNumber.Text;
                        prop.City            = editor.txtCity.Text;
                        prop.State           = editor.txtState.Text;
                        prop.ZIPCode         = editor.txtZIPCode.Text;
                        prop.Stories         = short.Parse(editor.txtStories.Text);
                        prop.Bedrooms        = short.Parse(editor.txtBedrooms.Text);
                        prop.Bathrooms       = float.Parse(editor.txtBathrooms.Text);
                        prop.MonthlyRate     = double.Parse(editor.txtMonthlyRate.Text);
                        prop.SecurityDeposit = double.Parse(editor.txtSecurityDeposit.Text);
                        prop.OccupancyStatus = editor.cbxOccupanciesStatus.Text;
                        prop.PictureFile     = editor.PictureFile;
                    }
                }
    
                using (FileStream fsProperties = new FileStream(strFileName,
                                                                FileMode.Create,
                                                                FileAccess.Write))
                {
                    bfmProperty.Serialize(fsProperties, properties);
                }
            }
        }
    }

Deleting Nodes from a Linked List

There are various options to delete a node. To delete the first node of a LinkedList collection, call the RemoveFirst() method. Its syntax is:

public void RemoveFirst();

To delete the last node, call the RemoveLast() method whose syntax is:

public void RemoveLast();

To delete a node using its value, call the overloaded Remove() method. The syntaxes of both versions are:

public bool Remove(T value);
public void Remove(LinkedListNode<T> node);

To delete all nodes from a linked list, call the Clear() method. Its syntax is:

public void Clear();

ApplicationPractical Learning: Deleting a Node

  1. Display the Rental Properties form box and double-click the Delete Rental Property button
  2. Implement the Click event as follows:
    private void btnDeleteRentalProperty_Click(object sender, EventArgs e)
    {
        RentalProperty propToDelete = new RentalProperty();
        BinaryFormatter bfProperties = new BinaryFormatter();
        RentalPropertyEditor editor = new RentalPropertyEditor();
        LinkedList<RentalProperty> properties = new LinkedList<RentalProperty>();
        string strFileName = @"C:\Microsoft Visual C# Application Design\Lambda Properties Management\Properties.pts";
    
        if (lvwRentalProperties.SelectedItems.Count == 0)
        {
            MessageBox.Show("You must select the property to delete.",
                            "Lambda Properties Management",
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
            return;
        }
    
        if (File.Exists(strFileName) == true)
        {
            using (FileStream fsProperties = new FileStream(strFileName,
                                                            FileMode.Open,
                                                            FileAccess.Read))
            {
                properties = (LinkedList<RentalProperty>)bfProperties.Deserialize(fsProperties);
    
                foreach (RentalProperty house in properties)
                    if (house.PropertyNumber == lvwRentalProperties.SelectedItems[0].Text)
                        propToDelete = house;
            }
    
            // Present a warning message to the user
            if (MessageBox.Show("Are you sure you want to delete this property?",
                                "Lambda Properties Management",
                                MessageBoxButtons.YesNo,
                                MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
            {
                // If the user clicks yes, delete the property
                if (properties.Remove(propToDelete))
                    MessageBox.Show("The property record has been deleted.",
                                    "Lambda Properties Management",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information);
    
                // Save the list of properties
                using (FileStream stmProperties = new FileStream(strFileName,
                                                            FileMode.Create,
                                                            FileAccess.Write))
                {
                    bfProperties.Serialize(stmProperties, properties);
                }
            }
        }
    
        ShowRentalProperties();
    }
  3. Return to the Rental Properties form and double-click the Close button
  4. Implement the event as follows:
    private void btnClose_Click(object sender, EventArgs e)
    {
        Close();
    }
  5. Press Ctrl + F5 to execute
 
 
  1. Create the employees records as follows:

    Empl # First Name Last Name Title
    40685 Justine Sandt Rent Manager
    73048 Raymond Wilkinson  
    60949 Mark Reason Maintenance Technician
    38408 Marc Knights Rent Associate
    14925 Jane Proctor Human Resources Manager
    93947 Leonard Goulet Owner - General Manager
    28048 Thomas Wilkens Bookeeper
    20448 Nancy Longhorn Rent Associate
    80848 Horace Taylor Maintenance Technician
    61840 Martin Schroeder Rent Associate

  2. Create the following properties:

    Prop # Prop Type Unit # Address City State ZIP Code Beds Baths Monthly Rate Secrt Deposit Ocp Status
    399475 Apartment 101 6802 Gulf Branch Ave Rockville MD 20850 2 2 1150 650 Available
    620048 Apartment 1A 10314 Springster Rd Alexandria VA 22312 1 1 1150 650 Available
    620952 Condominium 802 4606 Canterbury Ave Bethesda MD 20814 1 1 1265 850 Available
    508293 Apartment 102 6802 Gulf Branch Ave Rockville MD 20850 1 1 950 500 Needs Repair
    729397 Apartment 103 6802 Gulf Branch Ave Rockville MD 20850 1 1 925 500 Available
    204058 Single Family   426 Zimmers Rd Silver Spring MD 20901 4 2.5 2650 1000 Available
    928485 Townhouse   688 Larrington St NW Washington DC 20012 3 2.5 1450 850 Available
    884804 Single Family   8602 Jorham Drv Silver Spring MD 20906 5 3.5 2880 1000 Available
    729384 Condominium 804 4606 Canterbury Ave Bethesda MD 20814 2 2 1475 1000 Available
    928364 Apartment 104 6802 Gulf Branch Ave Rockville MD 20850 3 2 1350 850 Available
    355204 Apartment 1B 10314 Springster Rd Alexandria VA 22312 2 1 1375 1000 Available
    297297 Apartment 105 6802 Gulf Branch Ave Rockville MD 20850 2 1 1150 650 Available
    928028 Townhouse 2410 Jerridan Str NW Washington DC 20008 4 3.5 2850 1250 Available
    139749 Apartment 109 6802 Gulf Branch Ave Rockville MD 20850 2 2 1150 650 Available

    Apartments at 6802 Gulf Branch Ave

    Apartments at 6802 Gulf Branch Ave

    Apartments at 10314 Springster Rd

    Apartments at 10314 Springster Rd

    Condominiiums at 4606 Canterbury Ave

    Condominiums at 4606 Canterbury Ave

    Townhouse

    Townhouses

    Single Family 1

    Single Family

    Single Family 2

    Single Family

  3. Create the following registrations:

    Reg ID Registration Date Empl # Tenant Code First Name Last Name Marital Status Children Phone Number Email Address Prop # Rent Start Date
    1001 6/12/2014 38408 29-485-05 Ann Sanders Married 1 (240) 524 -2831 annsanders@emailcity.com 139749 7/1/2014
    1002 6/15/2014 20448 83-400-85 Mahty Shaoul Married 2 202-729-1574 mshaoulman@gmail.com 928364 9/1/2014
    1003 6/22/2014 40685 48-602-73 Frank Ulm Single 0 (301) 882-0704 fulm112244@yaho.com 729397 7/1/2014

  4. Create the following payment records:

    Payment Date Empl # Reg ID Amount Notes
    6/12/2014 38408 1001 650 This is the payment for the security deposit.
    6/20/2014 40685 1003 500 Security Deposit
    7/27/2014 38408 1003 925  
    7/28/2014 38408 1001 1150  
    8/14/2014 20448 1002 850 Payment for security deposit
    8/25/2014 38408 1001 1150  
    8/25/2014 38408 1002 1350  
    8/26/2014 20448 1003 925  
    9/28/2014 20448 1001 1150  
    9/28/2014 40685 1002 1350  
    10/5/2014 38408 1003 925  
    10/8/2014 40685 1010 500 Security Deposit
    10/27/2014 93947 1001 1150  
    10/30/2014 38408 1002 1350  
    10/31/2014 40685 1003 925  
    11/26/2014 38408 1002 1350  
    11/29/2014 93947 1001 1150  
    11/30/2014 38408 1003 925  
    12/28/2014 20448 1001 1150  
    12/28/2014 38408 1004 1100  
    12/28/2014 38408 1005 1150  
    12/30/2014 20448 1003 925  
    12/31/2014 38408 1002 1350  
    1/26/2015 38408 1001 1150  
    1/28/2015 93947 1003 925  
    1/29/2015 93947 1002 1350  
    2/20/2015 20448 1001 1150  
    2/26/2015 38408 1002 1350  
    3/3/2015 40685 1003 925  

  5. Close the forms and return to your programming environment
 

Home Copyright © 2014, FunctionX