|
Built-In Collection Classes |
|
Introduction to List Classes |
|
Overview |
Instead of creating a collection class from scratch or instead of deriving a collection, you can use one of the built-in collection classes of the .NET Framework. To support the creation of any kinds of list, the Microsoft .NET Framework provides the ArrayList and the generic List classes.
The ArrayList class is defined in the System.Collections namespace while the generic List class is part of the System.Collections.Generic namespace. Therefore, in order to use one of these classes in your application, you can first include its namespace in the file that would perform the list-related operations.
The ArrayList class implements the IList, the ICollection, and the IEnumerable interfaces. The List class implements the generic IList<>, the generic ICollection<>, the generic IEnumerable<>, the IList, the ICollection, and the IEnumerable interfaces.
The ArrayList class is founded as follows:
public class ArrayList : IList, ICollection, IEnumerable, ICloneable
The generic List class is founded as follows:
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable
You can use either the ArrayList or the generic List class to create and manage values for a list. Here is an example of declaring an ArrayList variable:
using System;
using System.Collections;
using System.Windows.Forms;
public class Exercise : Form
{
ArrayList lstNames;
public Exercise()
{
InitializeComponent();
}
void InitializeComponent()
{
Load += new EventHandler(StartForm);
}
void StartForm(object sender, EventArgs e)
{
lstNames = new ArrayList();
}
}
public class Program
{
static int Main()
{
System.Windows.Forms.Application.Run(new Exercise());
return 0;
}
}
Besides the ability to create a list, both the ArrayList and the List classes have the built-in mechanism for serialization.
The default constructor allows you to create an empty list before adding values to it. If you already have an ICollection-based list, that is, a list created from a class that implements the ICollection interface, you can initialize your ArrayList list with it. To support this, the ArrayList class is equipped with the following constructor:
public ArrayList(ICollection c);
Here is an example:
void StartForm(object sender, EventArgs e)
{
ComboBox cbx = new ComboBox();
cbx.Items.Add("Paul Bertrand Yamaguchi");
cbx.Items.Add("Helene Mukoko");
cbx.Items.Add("John Hancock");
cbx.Items.Add("Gertrude Monay");
lstNames = new ArrayList(cbx.Items);
}
|
|
![]() |
|||||||||||||||||||||
|
|||||||||||||||||||||
| Form Property | Value | ||||||||||||||||||||
| FormBorderStyle | FixedDialog | ||||||||||||||||||||
| Text | Make Editor | ||||||||||||||||||||
| StartPosition | CenterScreen | ||||||||||||||||||||
| AcceptButton | btnOK | ||||||||||||||||||||
| CancelButton | btnCancel | ||||||||||||||||||||
| MaximizeBox | False | ||||||||||||||||||||
| MinimizeBox | False | ||||||||||||||||||||
| ShowInTaskbar | False | ||||||||||||||||||||
![]() |
|||||||||||||||||||||
|
|||||||||||||||||||||
| Form Property | Value | ||||||||||||||||||||
| FormBorderStyle | FixedDialog | ||||||||||||||||||||
| Text | Model Editor | ||||||||||||||||||||
| StartPosition | CenterScreen | ||||||||||||||||||||
| AcceptButton | btnOK | ||||||||||||||||||||
| CancelButton | btnCancel | ||||||||||||||||||||
| MaximizeBox | False | ||||||||||||||||||||
| MinimizeBox | False | ||||||||||||||||||||
| ShowInTaskbar | False | ||||||||||||||||||||
![]() |
|||||||||||||||||||||
|
|||||||||||||||||||||
| Form Property | Value | ||||||||||||||||||||
| FormBorderStyle | FixedDialog | ||||||||||||||||||||
| Text | Category Editor | ||||||||||||||||||||
| StartPosition | CenterScreen | ||||||||||||||||||||
| AcceptButton | btnOK | ||||||||||||||||||||
| CancelButton | btnCancel | ||||||||||||||||||||
| MaximizeBox | False | ||||||||||||||||||||
| MinimizeBox | False | ||||||||||||||||||||
| ShowInTaskbar | False | ||||||||||||||||||||
![]() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Form Property | Value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FormBorderStyle | FixedDialog | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Text | College Park Auto -Parts: Part Editor | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| StartPosition | CenterScreen | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MaximizeBox | False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MinimizeBox | False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShowInTaskbar | False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
private void btnNewMake_Click(object sender, EventArgs e)
{
var editor = new MakeEditor();
if (editor.ShowDialog() == DialogResult.OK)
{
if (editor.txtMake.Text.Length > 0)
{
var strMake = editor.txtMake.Text;
// Make sure the category is not yet in the list
if (cbxMakes.Items.Contains(strMake))
MessageBox.Show(strMake + " is already in the list");
else
{
// Since this is a new category, add it to the combo box
cbxMakes.Items.Add(strMake);
}
cbxMakes.Text = strMake;
}
}
}
|
private void btnNewModel_Click(object sender, EventArgs e)
{
var editor = new ModelEditor();
if (editor.ShowDialog() == DialogResult.OK)
{
if (editor.txtModel.Text.Length > 0)
{
var strModel = editor.txtModel.Text;
// Make sure the category is not yet in the list
if (cbxModels.Items.Contains(strModel))
MessageBox.Show(strModel + " is already in the list");
else
{
// Since this is a new category, add it to the combo box
cbxModels.Items.Add(strModel);
}
cbxModels.Text = strModel;
}
}
}
|
private void btnNewCategory_Click(object sender, EventArgs e)
{
var editor = new CategoryEditor();
if (editor.ShowDialog() == DialogResult.OK)
{
if (editor.txtCategory.Text.Length > 0)
{
var strCategory = editor.txtCategory.Text;
// Make sure the category is not yet in the list
if (cbxCategories.Items.Contains(strCategory))
MessageBox.Show(strCategory + " is already in the list");
else
{
// Since this is a new category, add it to the combo box
cbxCategories.Items.Add(strCategory);
}
cbxCategories.Text = strCategory;
}
}
}
|

private void lvwAutoParts_DoubleClick(object sender, EventArgs e)
{
var lviAutoPart = lvwAutoParts.SelectedItems[0];
if( (lvwAutoParts.SelectedItems.Count == 0) ||
(lvwAutoParts.SelectedItems.Count > 1) )
return;
txtPartNumber.Text = lviAutoPart.Text;
txtPartName.Text = lviAutoPart.SubItems[1].Text;
txtUnitPrice.Text = lviAutoPart.SubItems[2].Text;
txtQuantity.Text = "1";
txtSubTotal.Text = lviAutoPart.SubItems[2].Text;
txtQuantity.Focus();
}
|
private void txtUnitPrice_Leave(object sender, EventArgs e)
{
var UnitPrice = 0.00D;
var Quantity = 0;
var SubTotal = 0.00D;
try
{
UnitPrice = double.Parse(txtUnitPrice.Text);
}
catch (FormatException)
{
MessageBox.Show("Invalid Unit Price!");
}
try { Quantity = int.Parse(txtQuantity.Text); }
catch (FormatException)
{
MessageBox.Show("Invalid Quandtity!");
}
SubTotal = UnitPrice * Quantity;
txtSubTotal.Text = SubTotal.ToString("F");
}
internal void CalculateOrder()
{
// Calculate the current total order and update the order
var PartsTotal = 0.00D;
var TaxRate = 0.00D;
var TaxAmount = 0.00D;
var OrderTotal = 0.00D;
foreach (ListViewItem lvi in lvwSelectedParts.Items)
{
ListViewItem.ListViewSubItem SubItem = lvi.SubItems[4];
PartsTotal += double.Parse(SubItem.Text);
}
try
{
TaxRate = double.Parse(txtTaxRate.Text) / 100;
}
catch (FormatException)
{
MessageBox.Show("Invalid Tax Rate");
}
TaxAmount = PartsTotal * TaxRate;
OrderTotal = PartsTotal + TaxAmount;
txtPartsTotal.Text = PartsTotal.ToString("F");
txtTaxAmount.Text = TaxAmount.ToString("F");
txtOrderTotal.Text = OrderTotal.ToString("F");
}
|
private void lvwSelectedParts_DoubleClick(object sender, EventArgs e)
{
var lviSelectedPart = lvwSelectedParts.SelectedItems[0];
if( (lvwSelectedParts.SelectedItems.Count == 0) ||
(lvwSelectedParts.SelectedItems.Count > 1) )
return;
txtPartNumber.Text = lviSelectedPart.Text;
txtPartName.Text = lviSelectedPart.SubItems[1].Text;
txtUnitPrice.Text = lviSelectedPart.SubItems[2].Text;
txtQuantity.Text = lviSelectedPart.SubItems[3].Text;
txtSubTotal.Text = lviSelectedPart.SubItems[4].Text;
lvwSelectedParts.Items.Remove(lviSelectedPart);
CalculateOrder();
}
|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CollegeParkAutoParts1
{
[Serializable]
public class PartDescription
{
// These members will be used to define a car part
private long ID;
private int yr;
private string mk;
private string mdl;
private string cat;
private string name;
private double price;
public PartDescription()
{
this.ID = 0;
this.yr = 1960;
this.mk = "";
this.mdl = "";
this.name = "Unknown";
this.price = 0.00;
}
public PartDescription(long code, int year, string make,
string model, string type,
string desc, double UPrice)
{
this.ID = code;
this.yr = year;
this.mk = make;
this.mdl = model;
this.cat = type;
this.name = desc;
this.price = UPrice;
}
public long PartNumber
{
get { return ID; }
set { ID = value; }
}
public int Year
{
get { return yr; }
set { yr = value; }
}
public string Make
{
get { return mk; }
set { mk = value; }
}
public string Model
{
get { return mdl; }
set { mdl = value; }
}
public string Category
{
get { return cat; }
set { cat = value; }
}
public string PartName
{
get { return name; }
set { name = value; }
}
public double UnitPrice
{
get { return (price < 0) ? 0.00 : price; }
set { price = value; }
}
public override string ToString()
{
return this.PartNumber + " " +
this.Year.ToString() + " " +
this.Make + " " +
this.Model + " " +
this.Category + " " +
this.PartName + " " +
this.UnitPrice;
}
}
}
|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CollegeParkAutoParts1
{
[Serializable]
public class PartsOrdered
{
public long PartNumber;
public string PartName;
public double UnitPrice;
public int Quantity;
public double SubTotal;
}
}
|
|
The Capacity of a List |
After declaring an ArrayList or a List variable, it is empty. As objects are added to it, the list grows. The list can grow tremendously as you wish. The number of items of the list is managed through the memory it occupies and this memory grows as needed. The number of items that the memory allocated is currently using is represented by the Capacity property. Here is an example of accessing the ArrayList.Capacity property:
public class Exercise : Form
{
ArrayList lstNames;
public Exercise()
{
InitializeComponent();
}
void InitializeComponent()
{
Load += new EventHandler(StartForm);
}
void StartForm(object sender, EventArgs e)
{
lstNames = new ArrayList();
Text = "List Capacity: " + lstNames.Capacity.ToString();
}
}
This would produce:

The capacity of a list will usually be the least of your concerns. If for some reason, you want to intervene and control the number of items that your list can contain, you can manipulate the Capacity property. For example, you can assign it a constant to set the maximum value that the list can contain. Instead of specifying the capacity after the list has been created, when declaring the list variable, you can specify its maximum capacity. To support this, both the ArrayList and the List classes are equipped with an additional constructor as follows:
public ArrayList(int capacity); public List(int capacity);
Once again, you will hardly have any reason to use the Capacity property: the compiler knows what to do with it.
|
A Read-Only List |
One of the reason for creating a list is to be able to add values to it, edit its values, retrieve a value, or delete values from it. These are the default operations. You can still limit these operations as you judge them unnecessary. For example, you may create a list and then initialize it with the values that you want the list to only have. If you do not want to have the user adding values to it, you can create the list as read-only. To do this, you can call the ArrayList.ReadOnly() method. It is overloaded with two versions as follows:
Public Shared Function ReadOnly(list As ArrayList) As ArrayList public static IList ReadOnly(IList list)
Some operations cannot be performed on a read-only list. To perform such operations, you can first find out whether an ArrayList list is read-only. This is done by checking its IsReadOnly property.
|
Item Addition |
The primary operation performed on a list is to create one or more values. To do this, you have various alternatives. Both the ArrayList and the List classes are equipped with an Add() method. The syntax of the System.Collections.ArrayList.Add() method is:
public virtual int Add(object value);
The syntax of the System.Collections.Generic.List.Add() method is:
public void Add(T value);
The argument of the method is the value to add to the list. If the method succeeds with the addition, it returns the position where the value was added in the list. Here are example for an ArrayList variable:
void StartForm(object sender, EventArgs e)
{
Text = "Employees Records";
lstNames = new ArrayList();
lstNames.Add("Christine Kingston");
lstNames.Add("Hermine Paulson");
lstNames.Add("William Harrison");
lstNames.Add("Ursula Morales");
lstNames.Add("Evan Lancos");
}
If the method fails to add the value and if you are using the ArrayList class, the compiler would throw an error. One of the errors that could result from the ArrayList's failure of this operation would be based on the fact that either a new value cannot be added to the list because the list is read-only, or the list was already full prior to adding the new value. Normally, a list can be full only if you had specified the maximum number of items it can contain using the ArrayList.Capacity property. As mentioned above, the list can be made read-only by passing its variable to the ArrayList.ReadOnly() method.
Instead of adding one values at a time, you can first create a list of values and add that whole list at once. To support this operation, both the ArrayList and the List classes are equipped with a method named AddRange.
The syntax of the ArrayList.AddRange() method is:
public virtual void AddRange(ICollection collection);
The syntax of the List.AddRange() method is:
public void AddRange(IEnumerable<T> collection);
The ArrayList.AddRange() method takes as argument a list created from a class that implements the ICollection interface. Here is an example:
void StartForm(object sender, EventArgs e)
{
Text = "Employees";
ComboBox cbx = new ComboBox();
cbx.Items.Add("Paul Bertrand Yamaguchi");
cbx.Items.Add("Helene Mukoko");
cbx.Items.Add("John Hancock");
cbx.Items.Add("Gertrude Monay");
lstNames = new ArrayList();
lstNames.AddRange(cbx.Items);
}
The List.AddRange() method takes as argument a list created from a class that implements the generic IEnumerable interface.
|
|
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 CollegeParkAutoParts1
{
public partial class NewStoreItem : Form
{
List<PartDescription> lstAutoParts;
. . . No Change
private void btnSubmit_Click(object sender, EventArgs e)
{
FileStream stmAutoParts = null;
BinaryFormatter bfmAutoParts = new BinaryFormatter();
// If this directory doesn't exist, create it
Directory.CreateDirectory(@"C:\College Park Auto Parts");
// This is the file that holds the list of items
string FileName = @"C:\College Park Auto Parts\Parts.prs";
// Create a random number that will be used to identify the item
Random rnd = new Random();
txtPartNumber.Text = rnd.Next(100000, 999999).ToString();
// Make sure the user had selected a make
if (cbxYears.Text.Length == 0)
{
MessageBox.Show("You must specify the year");
cbxYears.Focus();
return;
}
// Make sure the user had selected a make
if (cbxMakes.Text.Length == 0)
{
MessageBox.Show("You must specify the car name");
cbxMakes.Focus();
return;
}
// Make sure the user had selected a model
if (cbxModels.Text.Length == 0)
{
MessageBox.Show("You must specify the model of the car");
cbxModels.Focus();
return;
}
// Make sure the user had selected the part category
if (cbxCategories.Text.Length == 0)
{
MessageBox.Show("You must specify the part's category");
cbxCategories.Focus();
return;
}
// Make sure the user had entered a name/description
if (txtPartName.Text.Length == 0)
{
MessageBox.Show("You must enter the name (or a " +
"short description) for the part");
txtPartName.Focus();
return;
}
// Make sure the user had typed a price for the item
if (txtUnitPrice.Text.Length == 0)
{
MessageBox.Show("You must enter the price of the item");
txtUnitPrice.Focus();
return;
}
// Before saving the new part, find out if there was
// already a file that holds the list of parts
// If that file exists, open it and store its parts
// in our lstParts variable
if (File.Exists(FileName))
{
stmAutoParts = new FileStream(FileName,
FileMode.Open,
FileAccess.Read,
FileShare.Read);
try
{
// Retrieve the list of items from file
lstAutoParts =
(List<PartDescription>)bfmAutoParts.Deserialize(stmAutoParts);
}
finally
{
stmAutoParts.Close();
}
}
// Create the part
PartDescription part = new PartDescription();
part.PartNumber = long.Parse(txtPartNumber.Text);
part.Year = int.Parse(cbxYears.Text);
part.Make = cbxMakes.Text;
part.Model = cbxModels.Text;
part.Category = cbxCategories.Text;
part.PartName = txtPartName.Text;
part.UnitPrice = double.Parse(txtUnitPrice.Text);
// Call the Add method of our collection class to add the part
lstAutoParts.Add(part);
// Save the list
stmAutoParts = new FileStream(FileName,
FileMode.Create,
FileAccess.Write,
FileShare.Write);
try
{
bfmAutoParts.Serialize(stmAutoParts, lstAutoParts);
// After saving the item, reset the form
cbxYears.Text = "";
cbxMakes.Text = "";
cbxModels.Text = "";
cbxCategories.Text = "";
txtPartName.Text = "";
txtUnitPrice.Text = "0.00";
txtPartNumber.Text = rnd.Next(100000, 999999).ToString();
}
finally
{
stmAutoParts.Close();
}
}
}
}
|
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; |
private void btnSaveCustomerOrder_Click(object sender, EventArgs e)
{
BinaryFormatter bfmCustomerOrder = new BinaryFormatter();
// We will store our files in the following folder
string strDirectory = @"C:\College Park Auto Parts\Receipts";
DirectoryInfo dirInfo = new DirectoryInfo(strDirectory);
string strFilename = strDirectory + "\\" + txtSave.Text + ".cap";
List<PartsOrdered> lstOrderedParts = null;
if (lvwSelectedParts.Items.Count == 0)
return;
else
{
lstOrderedParts = new List<PartsOrdered>();
for (int i = 0; i < lvwSelectedParts.Items.Count; i++)
{
PartsOrdered part = new PartsOrdered();
part.PartNumber = long.Parse(lvwSelectedParts.Items[i].Text);
part.PartName = lvwSelectedParts.Items[i].SubItems[1].Text;
part.UnitPrice = double.Parse(lvwSelectedParts.Items[i].SubItems[2].Text);
part.Quantity = int.Parse(lvwSelectedParts.Items[i].SubItems[3].Text);
part.SubTotal = double.Parse(lvwSelectedParts.Items[i].SubItems[4].Text);
lstOrderedParts.Add(part);
}
FileStream stmCustomerOrder = new FileStream(strFilename, FileMode.Create);
try
{
bfmCustomerOrder.Serialize(stmCustomerOrder, lstOrderedParts);
}
finally
{
stmCustomerOrder.Close();
}
}
}
|
|
The Number of Items in the List |
When using a list, at any time, you should be able to know the number of items that the list contains. This information is provided by the ArrayList.Count or the List.Count property.
The Capacity and the Count properties have this in common: the value of each increases as the list grows and the same value decreases if the list shrinks. It is important to know that there are various differences between the capacity of a list and the number of items it contains. Capacity is a read/write property. This means that you can assign a value to the capacity to fix the number of items that the list can contain. You can also retrieve the value of the Capacity. The Count property is read-only because it is used by the compiler to count the current number of values of the list and this counting is performed without your intervention.
|
Item Retrieval |
Once a list is ready, you can perform different types of operations on it. Besides adding items, one of the most regular operations performed on a list consists of locating and retrieving its values. You have various options.
To give you access to each member of their list, both the ArrayList and the List classes are equipped with the default Item property. The Item property is an indexer. The first value of the list has an index of 0. The second has an index of 1, and so on.
To retrieve a single value based on its position, you can apply the square brackets of arrays to the variable. Here is an example:
using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
public class Exercise : Form
{
ArrayList lstNames;
ListBox lbxNames;
public Exercise()
{
InitializeComponent();
}
void InitializeComponent()
{
lbxNames = new ListBox();
lbxNames.Location = new Point(12, 12);
Controls.Add(lbxNames);
Load += new EventHandler(StartForm);
}
void StartForm(object sender, EventArgs e)
{
Text = "Employees";
lstNames = new ArrayList();
lstNames.Add("Christine Kingston");
lstNames.Add("Hermine Paulson");
lstNames.Add("William Harrison");
lstNames.Add("Ursula Morales");
lstNames.Add("Evan Lancos");
for (int i = 0; i < 5; i++)
lbxNames.Items.Add(lstNames[i]);
}
}
public class Program
{
static int Main()
{
System.Windows.Forms.Application.Run(new Exercise());
return 0;
}
}

Another issue to keep in mind is that the ArrayList[] indexer returns an Object value. Therefore, you may have to cast this value to your type of value to get it right.
Besides using the index to access a value from the list, the ArrayList and the List classes implement the IEnumerable.GetEnumerator() method. For this reason, you can use the foreach loop to access each member of the collection. Here is an example:
void StartForm(object sender, EventArgs e)
{
Text = "Employees";
lstNames = new ArrayList();
lstNames.Add("Christine Kingston");
lstNames.Add("Hermine Paulson");
lstNames.Add("William Harrison");
lstNames.Add("Ursula Morales");
lstNames.Add("Evan Lancos");
foreach (string str in lstNames)
lbxNames.Items.Add(str);
}
You can use the Item property to change a value in the list. Because the Item property is used to access an existing value from the list, the value must have been created. If you try setting the value of a non existing item, the compiler would throw an ArgumentOutOfRangeException Exception. Here is an example:
void StartForm(object sender, EventArgs e)
{
Text = "Employees";
lstNames = new ArrayList();
lstNames[0] = "Paul Bertrand Yamaguchi";
}
Notice that at the time the 0 item is accessed, it has not previous been created. This would produce:

A review of the Details section shows:
System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index at System.Collections.ArrayList.set_Item(Int32 index, Object value) at Exercise.StartForm(Object sender, EventArgs e) in E:\Programs\VCSharp\Exercise1\Exercise1\Exercise.cs:line 31
This means that you can use the Item property only to change the value of a previous created item.
|
|
private void cbxMakes_SelectedIndexChanged(object sender, EventArgs e)
{
cbxModels.Text = "";
cbxModels.Items.Clear();
foreach (PartDescription part in lstAutoParts)
if (part.Make == cbxMakes.Text)
if (!cbxModels.Items.Contains(part.Model))
cbxModels.Items.Add(part.Model);
}
|
private void btnAdd_Click(object sender, EventArgs e)
{
if (txtPartNumber.Text.Length == 0)
{
MessageBox.Show("There is no part to be added to the order");
return;
}
foreach (PartDescription part in lstAutoParts)
{
if (part.PartNumber == long.Parse(txtPartNumber.Text))
{
ListViewItem lviSelectedPart =
new ListViewItem(part.PartNumber.ToString());
lviSelectedPart.SubItems.Add(part.PartName);
lviSelectedPart.SubItems.Add(part.UnitPrice.ToString());
lviSelectedPart.SubItems.Add(txtQuantity.Text);
lviSelectedPart.SubItems.Add(txtSubTotal.Text);
lvwSelectedParts.Items.Add(lviSelectedPart);
}
}
CalculateOrder();
}
|
private void btnOpen_Click(object sender, EventArgs e)
{
List<PartsOrdered> lstReceipts = null;
BinaryFormatter bfmReceipts = new BinaryFormatter();
FileStream stmReceipts = null;
string strDirectory = @"C:\College Park Auto Parts\Receipts";
string strFilename = "";
DirectoryInfo dirReceipts = new DirectoryInfo(strDirectory);
FileInfo[] fleReceipts = dirReceipts.GetFiles();
if (txtOpen.Text.Length == 0)
{
MessageBox.Show("You must enter a receipt number\n" +
"There is no receipt number to " +
"open a customer's order");
txtOpen.Focus();
return;
}
if (fleReceipts.Length == 0)
{
MessageBox.Show("There is no customer order to open");
txtOpen.Focus();
return;
}
else
{
lvwAutoParts.Items.Clear();
lvwSelectedParts.Items.Clear();
strFilename = strDirectory + "\\" + txtOpen.Text + ".cap";
if (File.Exists(strFilename))
{
try
{
stmReceipts = new FileStream(strFilename, FileMode.Open);
lstReceipts =
(List<PartsOrdered>)bfmReceipts.Deserialize(stmReceipts);
foreach (PartsOrdered part in lstReceipts)
{
ListViewItem lviReceiptPart =
new ListViewItem(part.PartNumber.ToString());
lviReceiptPart.SubItems.Add(part.PartName);
lviReceiptPart.SubItems.Add(part.UnitPrice.ToString());
lviReceiptPart.SubItems.Add(part.Quantity.ToString());
lviReceiptPart.SubItems.Add(part.SubTotal.ToString());
lvwSelectedParts.Items.Add(lviReceiptPart);
}
}
finally
{
stmReceipts.Close();
}
CalculateOrder();
txtSave.Text = txtOpen.Text;
}
else
MessageBox.Show("There is no customer order with that receipt number");
}
}
|
|
Checking the Existence of an Item |
Instead of the square brackets that allow you to retrieve a value based on its position, you can look for a value based on its complete definition. You have various options. You can first "build" an item and ask the compiler to check whether any item in the list matches your definition. To perform this search, depending on your class, you can call either the ArrayList.Contains() or the List.Contains() method. The syntax of the System.Collections.ArrayList.Contains() method is:
public virtual bool Contains(object value);
The syntax of the System.Collections.Generic.List.Contains() method is:
public bool Contains(T value);
The value to look for is passed as argument to the method. The compiler would look for exactly the value, using its definition, in the list. If any detail of the argument fails to match any value of the list, the method would return false. If all characteristics of the argument correspond to a value of the list, the method returns true. Here is an example:
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.Collections;
namespace Collector1
{
public partial class Form1 : Form
{
ArrayList lstNames;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
lstNames = new ArrayList();
lstNames.Add("Christine Kingston");
lstNames.Add("Hermine Paulson");
lstNames.Add("William Harrison");
lstNames.Add("Ursula Morales");
lstNames.Add("Evan Lancos");
foreach(string str in lstNames)
lbxNames.Items.Add(str);
}
private void btnResult_Click(object sender, EventArgs e)
{
string strFind = txtFind.Text;
if (lstNames.Contains(strFind) == true)
txtResult.Text = "Found";
else
txtResult.Text = "Not Found";
}
}
}
![]() |
![]() |
|
|
private void NewStoreItem_Load(object sender, EventArgs e)
{
// Since all values seem ready, prepare to process the item
lstAutoParts = new List<PartDescription>();
BinaryFormatter bfmAutoParts = new BinaryFormatter();
for (int i = DateTime.Today.Year + 1; i >= 1960; i--)
cbxYears.Items.Add(i.ToString());
// Create a random number that will be used to identify the item
Random rnd = new Random();
txtPartNumber.Text = rnd.Next(100000, 999999).ToString();
// This is the file that holds the list of parts
string FileName = @"C:\College Park Auto Parts\Parts.prs";
if (File.Exists(FileName))
{
FileStream stmAutoParts = new FileStream(FileName,
FileMode.Open,
FileAccess.Read,
FileShare.Read);
try
{
// Retrieve the list of items from file
lstAutoParts =
(List<PartDescription>)
bfmAutoParts.Deserialize(stmAutoParts);
// Display the car manufacturers in the Make combo box
for (int i = 0; i < lstAutoParts.Count; i++)
{
PartDescription part = (PartDescription)lstAutoParts[i];
if (!cbxMakes.Items.Contains(part.Make))
cbxMakes.Items.Add(part.Make);
}
// Display the pats categories in the Category combo box
for (int i = 0; i < lstAutoParts.Count; i++)
{
PartDescription part = (PartDescription)lstAutoParts[i];
if (!cbxCategories.Items.Contains(part.Category))
cbxCategories.Items.Add(part.Category);
}
}
finally
{
stmAutoParts.Close();
}
}
}
|
private void txtPartNumber_Leave(object sender, EventArgs e)
{
// We will allow the user to enter a part number
// In the beginning, we assume that the user
// had entered an invalid number
bool found = false;
// This will represent the part found, if any
PartDescription PartFound = null;
// After the user had entered a part number,
// check the whole list of parts
foreach (PartDescription part in lstAutoParts)
{
// If you find a part that holds the number the user had entered
if( part.PartNumber == long.Parse(txtPartNumber.Text) )
{
// Mark that part
PartFound = part;
// And update the flag that specifies that the part has been found
found = true;
}
// If the part number was not found, check the next
} // If no part has that number, the found flag keeps marked as false
// If a part with that number was found...
if (found == true)
{
// Show the corresponding part name and unit price
txtPartName.Text = PartFound.PartName;
txtUnitPrice.Text = PartFound.UnitPrice.ToString("F");
txtQuantity.Text = "1";
txtSubTotal.Text = PartFound.UnitPrice.ToString("F");
// Give focus to the quantity in case the user was to increase it
txtQuantity.Focus();
}
else
{
// Since no part with that number was found,
// reset the text boxes
txtPartName.Text = "";
txtUnitPrice.Text = "0.00";
txtQuantity.Text = "0";
txtSubTotal.Text = "0.00";
// Let the user know that the part number that
// was entered is not in the list
MessageBox.Show("There is no part with that number");
}
}
|
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 CollegeParkAutoParts1
{
public partial class Central : Form
{
int iFileName;
List<PartDescription> lstAutoParts;
public Central()
{
InitializeComponent();
}
void ShowAutoParts()
{
tvwAutoParts.Nodes.Clear();
TreeNode nodRoot =
tvwAutoParts.Nodes.Add("College Park Auto-Parts",
"College Park Auto-Parts", 0, 1);
// Show the years nodes
for (int years = DateTime.Today.Year + 1; years >= 1960; years--)
nodRoot.Nodes.Add(years.ToString(), years.ToString(), 2, 3);
tvwAutoParts.SelectedNode = nodRoot;
// Expand the root node
tvwAutoParts.ExpandAll();
lstAutoParts = new List<PartDescription>();
BinaryFormatter bfmAutoParts = new BinaryFormatter();
// This is the file that holds the list of auto parts
string FileName = @"C:\College Park Auto Parts\Parts.prs";
if (File.Exists(FileName))
{
FileStream stmAutoParts = new FileStream(FileName,
FileMode.Open,
FileAccess.Read,
FileShare.Read);
try
{
// Retrieve the list of parts from file
lstAutoParts =
(List<PartDescription>)
bfmAutoParts.Deserialize(stmAutoParts);
// Show the makes nodes
foreach (TreeNode nodYear in nodRoot.Nodes)
{
List<string> lstMakes = new List<string>();
foreach (PartDescription part in lstAutoParts)
{
if (nodYear.Text == part.Year.ToString())
{
if (!lstMakes.Contains(part.Make))
lstMakes.Add(part.Make);
}
}
foreach (string strMake in lstMakes)
nodYear.Nodes.Add(strMake, strMake, 4, 5);
}
// Showing the models nodes
foreach (TreeNode nodYear in nodRoot.Nodes)
{
foreach (TreeNode nodMake in nodYear.Nodes)
{
List<string> lstModels = new List<string>();
foreach (PartDescription part in lstAutoParts)
{
if ((nodYear.Text == part.Year.ToString()) &&
(nodMake.Text == part.Make))
{
if (!lstModels.Contains(part.Model))
lstModels.Add(part.Model);
}
}
foreach (string strModel in lstModels)
nodMake.Nodes.Add(strModel, strModel, 6, 7);
}
}
// Showing the categories nodes
foreach (TreeNode nodYear in nodRoot.Nodes)
{
foreach (TreeNode nodMake in nodYear.Nodes)
{
foreach (TreeNode nodModel in nodMake.Nodes)
{
List<string> lstCategories = new List<string>();
foreach (PartDescription part in lstAutoParts)
{
if ((nodYear.Text == part.Year.ToString()) &&
(nodMake.Text == part.Make) &&
(nodModel.Text == part.Model))
{
if (!lstCategories.Contains(part.Category))
lstCategories.Add(part.Category);
}
}
foreach (string strCategory in lstCategories)
nodModel.Nodes.Add(strCategory,
strCategory, 8, 9);
}
}
}
}
finally
{
stmAutoParts.Close();
}
}
}
. . . No Change
private void btnNewAutoPart_Click(object sender, EventArgs e)
{
var editor = new NewStoreItem();
if (editor.ShowDialog() == DialogResult.Cancel)
ShowAutoParts();
}
}
}
|
private void btnNewCustomerOrder_Click(object sender, EventArgs e)
{
// We will store our files in the following folder
string strDirectory = @"C:\College Park Auto Parts\Receipts";
DirectoryInfo dirInfo = Directory.CreateDirectory(strDirectory);
// Get the list of files, if any, from our directory
FileInfo[] fleList = dirInfo.GetFiles();
// If there is no file in the directory,
// then we will use 1000 as the first file name
if (fleList.Length == 0)
{
iFileName = 1000;
}
else // If there was at least one file in the directory
{
// Get a reference to the last file
FileInfo fleLast = fleList[fleList.Length - 1];
// Get the name of the last file without its extension
string fwe = Path.GetFileNameWithoutExtension(fleLast.FullName);
// Increment the name of the file by 1
iFileName = int.Parse(fwe) + 1;
}
txtSave.Text = iFileName.ToString();
lvwAutoParts.Items.Clear();
lvwSelectedParts.Items.Clear();
}
|
private void Central_Load(object sender, EventArgs e)
{
ShowAutoParts();
btnNewCustomerOrder_Click(sender, e);
}
|
private void tvwAutoParts_NodeMouseClick(object sender,
TreeNodeMouseClickEventArgs e)
{
TreeNode nodClicked = e.Node;
if (nodClicked.Level == 4)
lvwAutoParts.Items.Clear();
try
{
foreach (PartDescription part in lstAutoParts)
{
if ((part.Category == nodClicked.Text) &&
(part.Model == nodClicked.Parent.Text) &&
(part.Make == nodClicked.Parent.Parent.Text) &&
(part.Year.ToString() == nodClicked.Parent.Parent.Parent.Text))
{
ListViewItem lviAutoPart =
new ListViewItem(part.PartNumber.ToString());
lviAutoPart.SubItems.Add(part.PartName);
lviAutoPart.SubItems.Add(part.UnitPrice.ToString("F"));
lvwAutoParts.Items.Add(lviAutoPart);
}
}
}
catch (NullReferenceException)
{
}
}
|
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
|
![]() |


|
Searching for an Item |
Another option to look for an item in a list consists of calling the BinarySearch() method of either the ArrayList or the List class. It is overloaded in three versions and one of them uses the following syntax:
public virtual int BinarySearch(object value); public int BinarySearch(T value);
The value to look for is passed argument to the method. Here is an example:
private void btnResult_Click(object sender, EventArgs e)
{
string strFind = txtFind.Text;
if( lstNames.BinarySearch(strFind) > 0 )
txtResult.Text = "Found";
else
txtResult.Text = "Not Found";
}
|
Clearing a List |
To remove all items from a list at once, you can call the Clear() method of either the ArrayList or the List class. Its syntax is:
public virtual void Clear()
|
Deleting an Item |
As opposed to adding a value to a list, you may want to remove one. To perform this operation, you have various options. You can ask the compiler to look for an item in the list and if, or once, the compiler finds it, it would delete the value. To perform this type of deletion, you can call the Remove() method of either the ArrayList or the List class. Its syntax is:
public virtual void Remove(object value); public bool Remove(T value);
This method accepts as argument the value that you want to delete from the list. To perform this operation, the list must not be read-only.
The Remove() method allows you to specify the exact value you want to delete from a list. Another option you have consists of deleting a value based on its position. This is done using the RemoveAt() method whose syntax is:
public virtual void RemoveAt(int index); public void RemoveAt(int index);
With this method, the position of the item is passed as argument. Here is an example:

private void btnSecond_Click(object sender, EventArgs e)
{
lstNames.RemoveAt(1);
lbxNames.Items.Clear();
foreach (string str in lstNames)
lbxNames.Items.Add(str);
}

If the position is not valid because either it is lower or higher than the current Count, the compiler would throw an ArgumentOutOfRangeException exception.
|
Exercises |
|
Musical Instrument Store |
|
College Park Auto Parts |

|
|
||
| Previous | Copyright © 2008-2009 Yevol.com | Next |
|
|
||