The .NET Framework's Linked List |
|
|
A linked list is a collection with the following rules:
|
- Each item in the list is called a node (this is not an actual rule
but a habit or a suggestion)
- If the list is empty, it may have one item referred to as null
- If the list was just empty, when a new node is added, that node
becomes the first and last item
- If the list has only one node, that node represents the first and
the last item
- If the list contains at least one node, whenever a new node is
added, that new node is positioned as the last in the list. This is
because the new node is added next to the existing node
- If the list contains more than one node, each item holds a
reference to the object next to it
In reality, there are various types of linked lists. A
singly linked list is a one-way directional list where each item points
(only) to the item next to it (in a somewhat right direction). The
description we just gave is conform to a singly linked list. Another type
is the doubly linked list:
- Each item in the list is called a node (again, this is not a real
rule)
- If the list is empty, it may have one item referred to as null or
two items referred to as nulls
- If a new node is added to an empty list, that node is added as the
first in the collection
- If the list contains one node, that node has two references to
itself: one reference as the next and the other reference as its
previous
- If the list contains two nodes:
- One node is the first. That first node holds a reference to
the other node as its next
- The other node is the last. That last node holds a reference
to the first node as its previous item
- If the list contains more than two nodes:
- The first node holds a reference to the next node (in the
right direction)
- The last node holds a reference to the node previous to it (in
the left direction)
- Each node holds two references: one reference to the previous
node and one reference to the next node
The last type of linked list is called a circular
linked list. This list is primarily created as either a singly linked list
or a doubly linked list:
- In a circular singly linked list, the list primarily follows the
rules of a singly linked list. then:
- If the list has two nodes, the first node holds a reference to
the other node as its next and its previous node
- If the list has more than one node:
- The first node holds a reference to the last node as its
previous object
- The last node holds a reference to first node as its next
- In a doubly linked list, the list includes the rules of the doubly
linked list and combines with those of the circular singly linked
list:
- The first node has a reference to the last node as its
previous node
- The last node has a reference to the first node as its next
node
- Each node has two references: its previous and its next nodes
Topic
Applied: Introducing Linked Lists
|
|
- Start Microsoft Visual Studio
- To create a new application, on the main menu, click FILE -> New
Project...
- In the middle list, make sure Windows Forms Application is
selected and change the Name to AltairRealtors1
- Click OK
- When asked whether you want to save the current solution, click
Yes
- To create a new class, on the main menu, click PROJECT -> Add
Class...
- Set the Name to RealEstateProperty
- Click Add
- Change the file as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AltairRealtors1
{
[Serializable]
public class RealEstateProperty
{
public string PropertyNumber { get; set; }
public string PropertyType { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZIPCode { get; set; }
public short Stories { get; set; }
public int YearBuilt { get; set; }
public short Bedrooms { get; set; }
public float Bathrooms { get; set; }
public string Condition { get; set; }
public string SaleStatus { get; set; }
public double MarketValue { get; set; }
public string PictureFile { get; set; }
// To determine that two properties are the same,
// we will test only the property number.
// We assume that if two properties have the same number,
// then it is the same property
public override bool Equals(object obj)
{
RealEstateProperty rep = (RealEstateProperty)obj;
if (rep.PropertyNumber == PropertyNumber)
return true;
else
return false;
}
// To avoid a compiler warning
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}
- In the Solution Explorer, right-click Form1.cs and click Rename
- Type AltairRealtors.cs and press Enter twice
- Display the form and, from the Toolbox, add a list view to the
form
- Right-click the list view on the form and click Edit Columns...
- Create the columns as follows:
(Name) |
Text |
TextAlign |
Width |
colPropertyNumber |
Property # |
|
65 |
colCity |
City |
|
75 |
colStories |
Stories |
Right |
45 |
colYearBuilt |
Year |
Right |
40 |
colBedrooms |
Beds |
Right |
38 |
colBathrooms |
Baths |
Right |
40 |
colCondition |
Condition |
|
80 |
colSaleStatus |
Status |
|
70 |
colMarketValue |
Value |
Right |
75 |
- Click OK
- Design the form as follows:
|
Control |
(Name) |
Anchor |
BorderStyle |
SizeMode |
Text |
ListView |
|
lvwProperties |
Top, Bottom, Left, Right |
|
|
|
Button |
|
btnNewProperty |
Bottom, Left |
|
|
New Real Estate Property... |
PictureBox |
|
pbxPicture |
Bottom, Right |
FixedSingle |
Zoom |
|
Button |
|
btnClose |
Bottom, Right |
|
|
Close |
|
Form |
Text: |
Altair Realtors - Properties Listing |
StartPosition: |
CenterScreen |
- Right-click the form and click Edit Groups...
- Create the groups as follows:
Header |
Name |
Condominium |
lvgCondominium |
Townhouse |
lvgTownhouse |
Single Family |
lvgSingleFamily |
- Click OK
Although you can create a linked list collection class
from scratch, to assist you, the .NET Framework provides a class named
LinkedList and that is a member of the
System.Collections.Generic namespace. LinkedList
is a generic collection class with three constructors. The default
constructor allows you to create an empty linked list. Here is an example
of using it:
using System;
using System.Windows.Forms;
using System.Collections.Generic;
public class LinkedListExample : Form
{
Button btnLinkedList;
public LinkedListExample()
{
InitializeComponent();
}
private void InitializeComponent()
{
btnLinkedList = new Button();
btnLinkedList.Location = new System.Drawing.Point(12, 12);
btnLinkedList.Text = "Linked List";
btnLinkedList.Click += new EventHandler(btnLinkedListClicked);
Controls.Add(btnLinkedList);
Text = "Linked List Example";
StartPosition = FormStartPosition.CenterScreen;
}
private void btnLinkedListClicked(object sender, EventArgs e)
{
LinkedList<double> numbers = new LinkedList<double>();
}
}
public class Exercise
{
public static int Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new LinkedListExample());
return 0;
}
}
Another constructor allows you to create a linked
using an existing list. Its syntax is:
public LinkedList(IEnumerable<T> collection);
The argument can be a variable from any class that
implements the IEnumerable<T> interface. Here is an
example of using this second constructor:
private void btnLinkedListClicked(object sender, EventArgs e)
{
List<double> values = new List<double>();
values.Add(84.597);
values.Add(6.47);
values.Add(2747.06);
values.Add(282.924);
LinkedList<double> numbers = new LinkedList<double>(values);
}
Fundamental Operations on a Linked List
|
|
Introduction to a Node as an Object
|
|
As mentioned already, it is a tradition to call an
item of a linked list a node. To define a node as a true object, the .NET
Framework provides the LinkedListNode sealed class:
public sealed class LinkedListNode<T>
This class has only properties, no methods.
The Number of Nodes of a List
|
|
The LinkedList class starts as
follows:
public class LinkedList<T> : ICollection<T>,
IEnumerable<T>,
ICollection, IEnumerable,
ISerializable,
IDeserializationCallback
As you can see, the LinkedList class
implements the ICollection interface. This gives it a
Count property that produces the number of nodes. Here is
an example of accessing it:
private void btnLinkedListClicked(object sender, EventArgs e)
{
List<double> values = new List<double>();
values.Add(84.597);
values.Add(6.47);
values.Add(2747.06);
values.Add(282.924);
LinkedList<double> numbers = new LinkedList<double>(values);
MessageBox.Show("There are " + numbers.Count.ToString() + " numbers in the list",
"Linked List",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
The primary operation to perform on a linked list is
to add a new node to it. To support it, the LinkedList
class is equipped with various methods. One of them is named AddLast
that is overloaded in two versions. One of them uses the following syntax:
public LinkedListNode<T> AddLast(T value);
This method expects the new value as argument. Here is
an example of calling it:
using System;
using System.Windows.Forms;
using System.Collections.Generic;
public class LinkedListExample : Form
{
Button btnLinkedList;
public LinkedListExample()
{
InitializeComponent();
}
private void InitializeComponent()
{
btnLinkedList = new Button();
btnLinkedList.Location = new System.Drawing.Point(12, 12);
btnLinkedList.Text = "Linked List";
btnLinkedList.Click += new EventHandler(btnLinkedListClicked);
Controls.Add(btnLinkedList);
Text = "Linked List Example";
StartPosition = FormStartPosition.CenterScreen;
}
private void btnLinkedListClicked(object sender, EventArgs e)
{
LinkedList<double> numbers = new LinkedList<double>();
numbers.AddLast(148.24);
}
}
public class Exercise
{
public static int Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new LinkedListExample());
return 0;
}
}
Another version of this method is:
public void AddLast(LinkedListNode<T> node);
This version expects a LinkedListNode
object as argument. Here is an example of calling it:
private void btnLinkedListClicked(object sender, EventArgs e)
{
LinkedList<double> numbers = new LinkedList<double>();
LinkedListNode<double> number = new LinkedListNode<double>(148.24);
numbers.AddLast(number);
}
In the same way, you can use this method to add new
items. Here are examples:
private void btnLinkedListClicked(object sender, EventArgs e)
{
LinkedList<double> numbers = new LinkedList<double>();
LinkedListNode<double> number = new LinkedListNode<double>(148.24);
numbers.AddFirst(number);
number = new LinkedListNode<double>(35.75);
numbers.AddLast(number);
number = new LinkedListNode<double>(2222.06);
numbers.AddLast(number);
number = new LinkedListNode<double>(4.19);
numbers.AddLast(number);
number = new LinkedListNode<double>(66.18);
numbers.AddLast(number);
}
Because the LinkedList implements the
ICollection interface, it inherits the Contains
method. As a reminder, 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. Here is an
example of calling it:
private void btnLinkedListClicked(object sender, EventArgs e)
{
List<double> values = new List<double>();
values.Add(84.597);
values.Add(6.47);
values.Add(2747.06);
values.Add(282.924);
LinkedList<double> numbers = new LinkedList<double>(values);
LinkedListNode<double> number = new LinkedListNode<double>(148.24);
numbers.AddFirst(number);
number = new LinkedListNode<double>(35.75);
numbers.AddFirst(number);
number = new LinkedListNode<double>(2222.06);
numbers.AddFirst(number);
number = new LinkedListNode<double>(4.19);
numbers.AddFirst(number);
number = new LinkedListNode<double>(66.18);
numbers.AddFirst(number);
if( numbers.Contains(2222.06) == true )
MessageBox.Show("The list contains 2222.06.",
"Linked List",
MessageBoxButtons.OK, MessageBoxIcon.Information);
else
MessageBox.Show("There is no such a number in the list.",
"Linked List",
MessageBoxButtons.OK, MessageBoxIcon.Information);
This method works only if the type of the node is able
to perform the comparison for equality. If you are using values of
primitive types (int, char,
double, DateTime, etc) or string,
the method would work fine. If you are using your own class, make sure you
override the Equals() method.
While the Contains() method is used
to look for a value in a linked list, it only lets you know whether the
value was found. If you want to get the actual node that has that value,
you can 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. Here is an example of calling this method:
private void btnLinkedListClicked(object sender, EventArgs e)
{
List<double> values = new List<double>();
values.Add(84.597);
values.Add(6.47);
values.Add(2747.06);
values.Add(282.924);
LinkedList<double> numbers = new LinkedList<double>(values);
LinkedListNode<double> number = new LinkedListNode<double>(148.24);
numbers.AddFirst(number);
number = new LinkedListNode<double>(35.75);
numbers.AddFirst(number);
number = new LinkedListNode<double>(2222.06);
numbers.AddFirst(number);
numbers.AddFirst(2747.06);
number = new LinkedListNode<double>(4.19);
numbers.AddFirst(number);
number = new LinkedListNode<double>(66.18);
numbers.AddFirst(number);
if( numbers.Find(2747.06) != null )
MessageBox.Show("2747.06 was found in the list.",
"Linked List",
MessageBoxButtons.OK, MessageBoxIcon.Information);
else
MessageBox.Show("2747.06 is nowhere in the list.",
"Linked List",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
If the list contains more than one node that has the
value but you prefer to use the last node, you can call the
FindLast() method.
public LinkedListNode<T> FindLast(T value);
Once again, remember that 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.
As you can see, the LinkedList class
doesn't implement the IList interface, which means it
doesn't have an Item property. As we have seen with the
AddLast() method and as we will see in the next sections,
each method used to add a node is provided in two versions. One of the
versions returns a LinkedListNode object. This means
that, when performing an addition operation, you can get the returned
value and do what you want with it.
The class implements the IEnumerable
interface. This makes it possible to use foreach to get
to access each node. This can be done as follows:
private void btnLinkedListClicked(object sender, EventArgs e)
{
LinkedList<double> numbers = new LinkedList<double>();
LinkedListNode<double> number = new LinkedListNode<double>(148.24);
numbers.AddFirst(number);
foreach (double nbr in numbers)
MessageBox.Show(nbr.ToString());
}
Topic
Applied: Getting Each Node of a Linked List
|
|
- Double-click an unoccupied area of the Altair Realtors form
- 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.IO;
using System.Windows.Forms;
using System.Runtime.Serialization.Formatters.Binary;
namespace AltairRealtors1
{
public partial class AltairRealtors : Form
{
ListViewItem lviSelected;
LinkedList<RealEstateProperty> properties;
public AltairRealtors()
{
InitializeComponent();
}
private void ShowProperties()
{
BinaryFormatter bfmProperty = new BinaryFormatter();
string strFileName = "C:\\Microsoft Visual C# Application Design\\Altair Realtors\\properties.ars";
// Make sure the file exists
if (File.Exists(strFileName) == true)
{
// if so, create a file stream
using (FileStream stmProperties = new FileStream(strFileName,
FileMode.Open,
FileAccess.Read))
{
// If some properties were created already,
// get them and store them in the collection
properties = (LinkedList<RealEstateProperty>)bfmProperty.Deserialize(stmProperties);
// First, empty the list view
lvwProperties.Items.Clear();
ListViewItem lviProperty = null;
// Visit each property in the collection and add it to the list view
foreach (RealEstateProperty house in properties)
{
if (house.PropertyType.Equals("Condominium"))
lviProperty = new ListViewItem(house.PropertyNumber, lvwProperties.Groups[0]);
else if (house.PropertyType.Equals("Townhouse"))
lviProperty = new ListViewItem(house.PropertyNumber, lvwProperties.Groups[1]);
else // if (house.PropertyType.Equals("Single Family"))
lviProperty = new ListViewItem(house.PropertyNumber, lvwProperties.Groups[2]);
lviProperty.SubItems.Add(house.City);
lviProperty.SubItems.Add(house.Stories.ToString());
lviProperty.SubItems.Add(house.YearBuilt.ToString());
lviProperty.SubItems.Add(house.Bedrooms.ToString());
lviProperty.SubItems.Add(house.Bathrooms.ToString("F"));
lviProperty.SubItems.Add(house.Condition);
lviProperty.SubItems.Add(house.SaleStatus);
lviProperty.SubItems.Add(house.MarketValue.ToString());
lvwProperties.Items.Add(lviProperty);
}
} // Close the file stream
}
}
private void AltairRealtors_Load(object sender, EventArgs e)
{
Directory.CreateDirectory("C:\\Microsoft Visual C# Application Design\\Altair Realtors");
properties = new LinkedList<RealEstateProperty>();
ShowProperties();
lviSelected = new ListViewItem();
}
}
}
Navigating Among the Nodes
|
|
The First and the Last Nodes
|
|
As mentioned already, a linked list has a first and a
last nodes (some people or documentations call them the head and the
tail). To identify the first node, the LinkedList class
is equippped with 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; }
Here are examples of accessing these properties:
private void btnLinkedListClicked(object sender, EventArgs e)
{
LinkedList<double> numbers = new LinkedList<double>();
LinkedListNode<double> number = new LinkedListNode<double>(148.24);
numbers.AddFirst(number);
number = new LinkedListNode<double>(35.75);
numbers.AddFirst(number);
number = new LinkedListNode<double>(2222.06);
numbers.AddFirst(number);
number = new LinkedListNode<double>(4.19);
numbers.AddFirst(number);
number = new LinkedListNode<double>(66.18);
numbers.AddFirst(number);
MessageBox.Show("The value of the first node is " + numbers.First.Value);
MessageBox.Show("The value of the last node is " + numbers.Last.Value);
}
The Next and Previous Nodes
|
|
To access a node that is next to an existing node, you
must first know what node is used as reference. To let you access the next
node, the LinkedListNode class is equipped with a
read-only property named Next:
public LinkedListNode<T> Next { get; }
To let you access the node previous to an existing
one, the LinkedListNode class is equipped with the
read-only Previous property:
public LinkedListNode Previous { get; }
Remember that in both cases, you need a node as
reference.
When dealing with a linked list, you have many options
on how to add a new node. As mentioned already, a linked list has a first
node, a last node, and one or more nodes between them. All nodes have and
use some references with regards to the node(s) close to them. Based on
this, when adding a new node, you have to specify whether you want it as
the first node, the last node, the node before a certain node, or the node
after a certain one. The LinkedList class easily supports
all these operations with very little effort on your part.
We saw that you could call the AddFirst()
method to add a new node. In reality, there is no such a thing as simply
adding a new node to a linked list. When a linked list has just been
created and it is empty, it holds a reference to a null node. There is
nothing you can do with that node and you don't need to do anything with
it. To start adding nodes, you have the option of setting it as the first
or the last item. This would not make any difference because there is no
other node in the list.
After adding a node, it becomes a reference that new
nodes can use. If you call the AddFirst() method, the new
node would be added before any existing node in the collection.
Topic
Applied: Adding a Node to a Linked List
|
|
- To create a new form, on the main menu, click PROJECT -> Add
Windows Form...
- Set the Name to PropertyEditor
- Click Add
- In the Dialogs section of the Toolbox, click OpenFileDialog
- Click the form
- In the Properties window, change its characteristics as follows:
(Name): dlgPicture
DefaultExt: jpg
Filter:
JPEG Files (*.jpg,*.jpeg)|*.jpg
Title: Select House
Picture
- Design the form as follows:
|
Control |
(Name) |
DropDownStyle |
Text |
Items |
Modifiers |
Other Properties |
Label |
|
|
|
Property Type: |
|
|
|
ComboBox |
|
cbxPropertyTypes |
DropDownList |
|
Unknown Townhouse Single Family
Condominium |
Public |
|
Label |
|
|
|
Property #: |
|
|
|
TextBox |
|
txtPropertyNumber |
|
|
|
Public |
|
Label |
|
|
|
Address: |
|
|
|
TextBox |
|
txtAddress |
|
|
|
Public |
|
Label |
|
|
|
City: |
|
|
|
TextBox |
|
txtCity |
|
|
|
Public |
|
Label |
|
|
|
State: |
|
|
|
ComboBox |
|
cbxStates |
DropDownList |
|
AL, AK, AZ, AR, CA, CO, CT, DE, DC, FL, GA, HI,
ID, IL, IN, IA, KS, KY, LA, ME, MD, MA, MI, MN, MS,
MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, OH, OK, OR,
PA, RI, SC, SD, TN, TX, UT, VT, VA, WA, WV, WI, WY |
Public |
|
Label |
|
|
|
ZIP Code: |
|
|
|
TextBox |
|
txtZIPCode |
|
|
|
Public |
|
Label |
|
|
|
Stories: |
|
|
|
TextBox |
|
txtStories |
|
|
|
Public |
|
Label |
|
|
|
Year Built: |
|
|
|
TextBox |
|
txtYearBuilt |
|
|
|
Public |
|
Label |
|
|
|
Condition: |
|
|
|
ComboBox |
|
cbxConditions |
DropDownList |
|
Excellent Good Shape Needs Fixing |
Public |
|
Label |
|
|
|
Bedrooms: |
|
|
|
TextBox |
|
txtBedrooms |
|
0 |
|
Public |
|
Label |
|
|
|
Bathrooms: |
|
|
|
TextBox |
|
txtBathrooms |
|
0.00 |
|
Public |
|
Label |
|
|
|
Market Value: |
|
|
|
TextBox |
|
txtMarketValue |
|
0.00 |
|
Public |
|
Label |
|
|
|
Sale Status: |
|
|
|
ComboBox |
|
cbxSaleStatus |
DropDownList |
|
Sold Available Unspecified |
Public |
|
Button |
|
btnPicture |
|
Picture... |
|
|
|
PictureBox |
|
pbxProperty |
|
|
|
|
BorderStyle: FixedSingle SizeMode: Zoom |
Button |
|
btnOK |
|
OK |
|
|
DialogResult: OK |
Button |
|
btnCancel |
|
Cancel |
|
|
DialogResult: Cancel |
|
Form |
FormBorderStyle: |
FixedDialog |
Text: |
Altair Realtors - Property Editor |
StartPosition: |
CenterScreen |
AcceptButton: |
btnOK |
CancelButton: |
btnCancel |
MaximizeBox: |
False |
MinimizeBox: |
False |
ShowInTaskBar: |
False |
- Double-click an unoccupied area of the form
- Return to the form and double-click the Picture button
- 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;
namespace AltairRealtors1
{
public partial class PropertyEditor : Form
{
public bool pictureChanged;
public string pictureFile;
public PropertyEditor()
{
InitializeComponent();
}
private void PropertyEditor_Load(object sender, EventArgs e)
{
pictureChanged = false;
pictureFile = "C:\\Microsoft Visual C# Application Design\\Altair Realtors\\000-000.jpg";
}
private void btnPicture_Click(object sender, EventArgs e)
{
if (dlgPicture.ShowDialog() == DialogResult.OK)
{
pbxProperty.Image = Image.FromFile(dlgPicture.FileName);
pictureFile = dlgPicture.FileName;
pictureChanged = true;
}
}
}
}
- Display the Altair Realtors form and, on the form, double-click
the New Real Estale Property button
- Implement its event as follows:
private void btnNewProperty_Click(object sender, EventArgs e)
{
PropertyEditor editor = new PropertyEditor();
BinaryFormatter bfmProperty = new BinaryFormatter();
Random rndNumber = new Random(DateTime.Now.Millisecond);
int number1 = rndNumber.Next(100, 999);
int number2 = rndNumber.Next(100, 999);
string propNumber = number1 + "-" + number2;
editor.txtPropertyNumber.Text = propNumber;
// Get a reference to the file that holds the properties
string strFileName = "C:\\Microsoft Visual C# Application Design\\Altair Realtors\\properties.ars";
// First check if the file was previously created
if (File.Exists(strFileName) == true)
{
// If the list of properties exists already,
// get it and store it in a file stream
using (FileStream stmProperties = new FileStream(strFileName,
FileMode.Open,
FileAccess.Read))
{
// Store the list of properties in the collection
properties = (LinkedList<RealEstateProperty>)bfmProperty.Deserialize(stmProperties);
} // Close the file stream
}
if (editor.ShowDialog() == DialogResult.OK)
{
RealEstateProperty prop = new RealEstateProperty();
prop.PropertyNumber = editor.txtPropertyNumber.Text;
prop.PropertyType = editor.cbxPropertyTypes.Text;
prop.Address = editor.txtAddress.Text;
prop.City = editor.txtCity.Text;
prop.State = editor.cbxStates.Text;
prop.ZIPCode = editor.txtZIPCode.Text;
prop.Stories = short.Parse(editor.txtStories.Text);
prop.YearBuilt = int.Parse(editor.txtYearBuilt.Text);
prop.Bedrooms = short.Parse(editor.txtBedrooms.Text);
prop.Bathrooms = float.Parse(editor.txtBathrooms.Text);
prop.Condition = editor.cbxConditions.Text;
prop.SaleStatus = editor.cbxSaleStatus.Text;
prop.MarketValue = double.Parse(editor.txtMarketValue.Text);
if (!editor.pictureFile.Equals(""))
{
FileInfo flePicture = new FileInfo(editor.pictureFile);
flePicture.CopyTo("C:\\Microsoft Visual C# Application Design\\Altair Realtors\\" +
editor.txtPropertyNumber.Text + flePicture.Extension, true);
prop.PictureFile = "C:\\Microsoft Visual C# Application Design\\Altair Realtors\\" +
editor.txtPropertyNumber.Text + flePicture.Extension;
}
else
prop.PictureFile = "C:\\Microsoft Visual C# Application Design\\Altair Realtors\\000-000.jpg";
// Add the property in the collection
properties.AddFirst(prop);
// Create a file stream to hold the list of properties
using (FileStream stmProperties = new FileStream(strFileName,
FileMode.Create,
FileAccess.Write))
{
// Serialize the list of properties
bfmProperty.Serialize(stmProperties, properties);
} // Close the file stream
// Show the list of properties
ShowProperties();
}
}
- Return to the Altair Realtors form and click the list view
- In the Properties window, click Events and double-click
ItemSelectionChanged
- Implement the event as follows:
private void lvwProperties_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
RealEstateProperty currentProperty = new RealEstateProperty();
string strFileName = "C:\\Microsoft Visual C# Application Design\\Altair Realtors\\" + 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\\Altair Realtors\\000-000.jpg");
}
- Press Ctrl + F5 to execute
- Click the New Real Estate Property button and create a property as
follows:
Property Type |
Address |
City |
State |
ZIP Code |
Stories |
Year Built |
Condition |
Bedrooms |
Bathrooms |
Market Value |
Status |
Single Family |
4288 Lucow Drive |
Rockville |
MD |
20856 |
2 |
1988 |
Excellent |
3 |
2.5 |
665580 |
Available |
- Click OK
- Copy the following picture and paste (or save) it in the Altair
Realtors folder (or the folder that contains the file for the houses
of this project):
- Create the following properties
Property Type |
Address |
City |
State |
ZIP Code |
Stories |
Year Built |
Condition |
Bedrooms |
Bathrooms |
Market Value |
Status |
Townhouse |
719 Beanson Road |
Arlington |
VA |
22201 |
4 |
1995 |
Good Shape |
4 |
3.5 |
580795 |
Sold |
Condominium |
6662 16th Street NW |
Washington |
DC |
20012 |
6 |
1984 |
Good Shape |
1 |
1 |
325775 |
Available |
- Close the form and return to your programming environment
- On the Altair Realtors form, click the list view
- In the Events section of the Properties window, double-click
DoubleClick
- Implement its event as follows:
private void lvwProperties_DoubleClick(object sender, EventArgs e)
{
PropertyEditor editor = new PropertyEditor();
RealEstateProperty house = new RealEstateProperty();
BinaryFormatter bfmProperties = new BinaryFormatter();
string strFileName = "C:\\Microsoft Visual C# Application Design\\Altair Realtors\\properties.ars";
if ((lvwProperties.SelectedItems.Count == 0) || (lvwProperties.SelectedItems.Count > 1))
return;
using (FileStream stmProperties = new FileStream(strFileName,
FileMode.Open,
FileAccess.Read))
{
properties = (LinkedList<RealEstateProperty>)bfmProperties.Deserialize(stmProperties);
}
// Get the property that the user double-clicked
ListViewItem lviProperty = lvwProperties.SelectedItems[0];
foreach (RealEstateProperty prop in properties)
if (prop.PropertyNumber == lviProperty.Text)
house = prop;
// Prepare to fill the editor with the values of the property the user double-clicked
editor.txtPropertyNumber.Text = house.PropertyNumber;
editor.cbxPropertyTypes.Text = house.PropertyType;
editor.txtAddress.Text = house.Address;
editor.txtCity.Text = house.City;
editor.cbxStates.Text = house.State;
editor.txtZIPCode.Text = house.ZIPCode;
editor.txtStories.Text = house.Stories.ToString();
editor.txtYearBuilt.Text = house.YearBuilt.ToString();
editor.txtBedrooms.Text = house.Bedrooms.ToString();
editor.txtBathrooms.Text = house.Bathrooms.ToString("F");
editor.cbxConditions.Text = house.Condition;
editor.cbxSaleStatus.Text = house.SaleStatus;
editor.txtMarketValue.Text = house.MarketValue.ToString("F");
string strPictureFile = "C:\\Microsoft Visual C# Application Design\\Altair Realtors\\" + house.PropertyNumber + ".jpg";
if (File.Exists(strPictureFile))
editor.pbxProperty.Image = Image.FromFile(strPictureFile);
else
editor.pbxProperty.Image = Image.FromFile("C:\\Microsoft Visual C# Application Design\\Altair Realtors\\000-000.jpg");
// Disable the property number so the user cannot change it
editor.txtPropertyNumber.Enabled = false;
editor.ShowDialog();
// Show the list of properties
ShowProperties();
}
- Press Ctrl + F5 to execute the application
- Double-click one of the records in the list view
- Close the forms and return to your programming environment
By contrast, you can call a method named
AddLast. It is overloaded with versions whose syntaxes are:
public LinkedListNode<T> AddLast(T value);
public void AddLast(LinkedListNode<T> node);
When you call this method, the value or node you pass
will be added as the last item in the list. Here is an example:
using System;
using System.Windows.Forms;
using System.Collections.Generic;
public class LinkedListExample : Form
{
Button btnLinkedList;
ListBox lbxLinkedList;
public LinkedListExample()
{
InitializeComponent();
}
private void InitializeComponent()
{
btnLinkedList = new Button();
btnLinkedList.Location = new System.Drawing.Point(12, 12);
btnLinkedList.Text = "Linked List";
btnLinkedList.Click += new EventHandler(btnLinkedListClicked);
lbxLinkedList = new ListBox();
lbxLinkedList.Location = new System.Drawing.Point(12, 40);
lbxLinkedList.Height = 140;
Controls.Add(btnLinkedList);
Controls.Add(lbxLinkedList);
Text = "Linked List";
StartPosition = FormStartPosition.CenterScreen;
}
private void btnLinkedListClicked(object sender, EventArgs e)
{
List<double> values = new List<double>();
values.Add(84.597);
values.Add(6.47);
values.Add(2747.06);
values.Add(282.924);
LinkedList<double> numbers = new LinkedList<double>(values);
LinkedListNode<double> number = new LinkedListNode<double>(148.24);
numbers.AddFirst(number);
number = new LinkedListNode<double>(35.75);
numbers.AddFirst(number);
numbers.AddLast(2747.06);
number = new LinkedListNode<double>(2222.06);
numbers.AddFirst(number);
number = new LinkedListNode<double>(4.19);
numbers.AddFirst(number);
number = new LinkedListNode<double>(66.18);
numbers.AddFirst(number);
foreach (double dbl in numbers)
lbxLinkedList.Items.Add(dbl);
}
}
public class Exercise
{
public static int Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new LinkedListExample());
return 0;
}
}