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.
Practical
Learning: Iterating Through a Linked List
|
|
- Display the Employees form and double-click an unoccupied area of
its body
- 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();
}
}
}
- Return to the Employees form and double-click the Close button
- Implement the event as follows:
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
- Display the Rental Property Editor dialog box and double-click an
unoccupied area of its body
- 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;
}
}
- Display the Tenants Registrations form and double-click the New
Registration button
- 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();
}
}
}
- Display the Payments form and double-click the New Payment button
- 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);
}
}
}
}
}
- Save all
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.
Practical
Learning: Accessing the Value of a Linked List Node
|
|
- Display the Rental Properties form and double-click an unoccupied
area of its body
- 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();
}
- Return to the Rental Properties form and click the list view
- On the Properties window, click the Events button and double-click
Leave
- 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");
}
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.
Practical
Learning: Adding an Item to a Linked List
|
|
- Return to the Rental Properties form and double-click the New Rental
Property button
- 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.
Practical
Learning: Accessing the Individual Nodes of a Linked List
|
|
- Display the Payments form and double-click an unoccupied area of its
body
- 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.
Practical
Learning: Using LINQ in a Linked List
|
|
- Display the Payment Editor form and click the Employee # text box
- On the Properties window, click the Events button and double-click
Leave
- 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;
}
}
}
}
}
- Return to the Payments form and click the Registation # text box
- In the Events section of the Properties window, double-click Leave
- 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;
}
}
}
- Return to the Payments form and click the list view
- In the Events section of the Properties window, double-click
ItemSelectedChanged
- 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;
}
}
- Return to the Payments form and double-click the Close button
- Change the document as follows:
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
- Display the Tenant Registration Editor and click the Employee # text
box
- In the Events section of the Properties window, double-click Leave
- 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;
}
}
}
}
}
- Return to the Tenant Registration Editor and click the Property #
text box
- In the Events section of the Properties window, double-click Leave
- 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;
}
}
}
- Display the New Rental Property dialog box and add a Button to the
right side of the Property Number text box
- Change the button's properties as follows:
(Name): btnFind
Text: Find
- 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;
}
}
}
}
- Display the Tenants Registrations form and double-click an
unoccupied area of its body
- 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();
}
}
}
- Return to the Tenants Registrations form and double-click the Close
button
- Change the document as follows:
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
- 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.
Practical
Learning: Updating a Node
|
|
- Return to the Rental Properties form and double-click the Update
Rental Property button
- 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();
Practical
Learning: Deleting a Node
|
|
- Display the Rental Properties form box and double-click the Delete
Rental Property button
- 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();
}
- Return to the Rental Properties form and double-click the Close
button
- Implement the event as follows:
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
- Press Ctrl + F5 to execute
|
|