XML Serialization - College Park Auto-Parts
XML Serialization - College Park Auto-Parts
Introduction
You can create a fully functional database using one or a combination of the collection classes available in the .NET Framework (or any other library). Those classes provides all the properties and methods you would use to manage the records of the database, including creating new records, looking for/reading/finding, editing/updating, and deleting records. To hold (that is, to save and open) the records of such a database, you can use XML serialization.
Practical Learning: Introducing Data Sets
A Class for Auto-Parts
This is going to be a list-based. Such a list needs to know the type of values it will deal with. For our application, we will use a class that has properties that each represents one detail about an auto-part.
Practical Learning: Creating a Class
namespace CollegeParkAutoParts2 { public class AutoPart { public long PartNumber { get; set; } public int Year { get; set; } public string? Make { get; set; } public string? Model { get; set; } public string? Category { get; set; } public string? PartName { get; set; } public double UnitPrice { get; set; } public string? PictureFile { get; set; } } }
The Vehicles Makes
To identify an auto-part, you use many pieces of information. To start, you must identify the car that uses the auto-part, and a car's identity starts with the manufactuter. In ou AutoPart class, a car manufactuter is represented by the Make property. Our application will need a form to allow the user to provide a vehicle make.
Practical Learning: Introducing Vehicles Makes
Control | (Name) | Text | Additional Properties | |
Label | &Make: | |||
TextBox | txtMake | |||
Button | btnOK | &OK | DialogResult: OK | |
Button | btnCancel | &Cancel | DialogResult: Cancel |
Vehicles Models
While the manufacturer of a vehicle is a business, a company usually makes many vehicles. A particular vehicle is known as a model. We will create a form that a user can use to specify the model of a car.
Practical Learning: Introducing Vehicles Models
Control | (Name) | Text | Additional Properties | |
Label | &Model: | |||
TextBox | txtModel | |||
Button | btnOK | &OK | DialogResult: OK | |
Button | btnCancel | &Cancel | DialogResult: Cancel |
Items Categories
Normally, there are various ways to characterize a car part. We will keep our application simple and use only a category for each part.
Practical Learning: Setting Items Categories
Control | (Name) | Text | Additional Properties | |
Label | C&ategory: | |||
TextBox | txtCategory | |||
Button | btnOK | &OK | DialogResult: OK | |
Button | btnCancel | &Cancel | DialogResult: Cancel |
Creating Records
The primary purpose of the business of our application is to sell auto parts. So it is necessary to create records for those parts. To make this happen, we had already created a table for auto parts. Now we need a graphical object, a form, to manager the records.
Practical Learning: Preparing an Items Inventory
Control | (Name) | Text | Additional Properties | |
Label | &Part #: | |||
TextBox | txtPartNumber | |||
Button | btnSelectPicture | &Select Picture... | ||
Label | &Year: | |||
Combo Box | cbxYears | |||
Picture Box | pbxPartImage | BorderStyle: FixedSingle SizeMode: AutoSize |
||
Label | &Make: | |||
Combo Box | cbxMakes | |||
Button | btnNewMake | New M&ake... | ||
Label | M&odel | |||
Combo Box | cbxModels | |||
Button | btnNewModel | New Mo&del... | ||
Label | Ca&tegory: | |||
Combo Box | cbxCategories | |||
Button | btnNewCategory | New Cat&egory... | ||
Label | Part Na&me: | |||
Text Box | txtPartName | ScrollBars: Vertical Multiline: True |
||
Label | &Unit Price: | |||
Text Box | txtUnitPrice | TextAlign: Right | ||
Label | ____________________ | |||
Button | btnSaveAutoPart | Sa&ve Auto-Part | ||
Button | Close | btnClose | ||
Open File Dialog | ofdPictureFile |
using System.Xml.Serialization; namespace CollegeParkAutoParts { public partial class StoreItemNew : Form { /* This property is used to hold the list of auto-parts of our application. * (We didn't have to use a global variable. We could have used local variables.) */ List<AutoPart> AutoParts { get; set; } = new List<AutoPart>(); public StoreItemNew() { InitializeComponent(); } /* This function is used to reset the form. * It can be called when necessary. */ private void InitializeAutoParts() { // This file is the repository of our database string strFileName = @"C:\College Park Auto-Parts\AutoParts.xml"; // We will use XML serialization to manage the records of our database XmlSerializer xsAutoParts = new XmlSerializer(typeof(List<AutoPart>)); /* Show the years in the top combo box. * We will consider only the cars made in the last 20 years. */ for (int year = DateTime.Today.Year + 1; year >= DateTime.Today.Year - 20; year--) cbxYears.Items.Add(year); // Check whether the file that holds the store inventory was created already if (File.Exists(strFileName)) { Random rndNumber = new(); cbxMakes.Items.Clear(); cbxModels.Items.Clear(); cbxCategories.Items.Clear(); txtPartName.Text = string.Empty; txtUnitPrice.Text = string.Empty; txtPartNumber.Text = rndNumber.Next(100000, 999999).ToString(); // If the inventory file exists, open it using (FileStream fsAutoParts = new FileStream(strFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { // Retrieve the list of items from file AutoParts = (List<AutoPart>)xsAutoParts.Deserialize(fsAutoParts)!; // Display the cars manufacturers in the combo box for (int i = 0; i < AutoParts.Count; i++) { // Make sure the list box doesn't yet have the category being added if (!cbxMakes.Items.Contains(AutoParts[i].Make)) cbxMakes.Items.Add(AutoParts[i].Make); } // Display the categories in the box for (int i = 0; i < AutoParts.Count; i++) { // Make sure the list box doesn't yet have the category being added if (!cbxCategories.Items.Contains(AutoParts[i].Category)) cbxCategories.Items.Add(AutoParts[i].Category); } } } lblPictureFile.Text = @"C:\College Park Auto-Parts\Generic.png"; pbxPartImage.Image = Image.FromFile(@"C:\College Park Auto-Parts\Generic.png"); Width = pbxPartImage.Right + 40; Height = pbxPartImage.Bottom + 75; } private void StoreItemNew_Load(object sender, EventArgs e) { InitializeAutoParts(); } private void btnSelectPicture_Click(object sender, EventArgs e) { if(ofdPictureFile.ShowDialog() == DialogResult.OK) { lblPictureFile.Text = ofdPictureFile.FileName; pbxPartImage.Image = Image.FromFile(ofdPictureFile.FileName); } else pbxPartImage.Image = Image.FromFile(@"C:\College Park Auto-Parts\Generic.png"); Width = pbxPartImage.Right + 40; Height = pbxPartImage.Bottom + 75; } private void cbxMakes_SelectedIndexChanged(object sender, EventArgs e) { cbxModels.Text = ""; cbxModels.Items.Clear(); foreach (AutoPart part in AutoParts) if (part.Make == cbxMakes.Text) if (!cbxModels.Items.Contains(part.Model)) cbxModels.Items.Add(part.Model); } private void btnNewMake_Click(object sender, EventArgs e) { Make editor = new Make(); if (editor.ShowDialog() == DialogResult.OK) { if (editor.txtMake.Text.Length > 0) { string 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.", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); 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) { Model editor = new(); if (editor.ShowDialog() == DialogResult.OK) { if (editor.txtModel.Text.Length > 0) { string 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.", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); 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 Category(); if (editor.ShowDialog() == DialogResult.OK) { if (editor.txtCategory.Text.Length > 0) { string 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.", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); else { // Since this is a new category, add it to the combo box cbxCategories.Items.Add(strCategory); } cbxCategories.Text = strCategory; } } } private void btnSaveAutoPart_Click(object sender, EventArgs e) { // Make sure the user had selected a year if( string.IsNullOrEmpty(cbxYears.Text) ) { MessageBox.Show("You must specify the year.", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } // Make sure the user had selected a make if(string.IsNullOrEmpty(cbxMakes.Text) ) { MessageBox.Show("You must specify the car name.", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } // Make sure the user had selected a model if (string.IsNullOrEmpty(cbxModels.Text) ) { MessageBox.Show("You must specify the model of the car.", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } // Make sure the user had entered a name/description if (string.IsNullOrEmpty(txtPartName.Text) ) { MessageBox.Show("You must enter the name (or a " + "short description) for the part.", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); txtPartName.Focus(); return; } // Make sure the user had typed a price for the item if( string.IsNullOrEmpty(txtUnitPrice.Text) ) { MessageBox.Show("You must enter the price of the item.", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); txtUnitPrice.Focus(); return; } string strFileName = @"C:\College Park Auto-Parts\AutoParts.xml"; XmlSerializer xsAutoParts = new XmlSerializer(typeof(List<AutoPart>)); if (File.Exists(strFileName)) { // If the inventory file exists, open it using (FileStream fsAutoParts = new FileStream(strFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { // Retrieve the list of items from file AutoParts = (List<AutoPart>)xsAutoParts.Deserialize(fsAutoParts)!; } } AutoPart part = new AutoPart(); 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); part.PictureFile = lblPictureFile.Text; // Call the Add method of our collection class to add the part AutoParts.Add(part); TextWriter twAutoParts = new StreamWriter(strFileName); xsAutoParts.Serialize(twAutoParts, AutoParts); twAutoParts.Close(); InitializeAutoParts(); } private void btnClose_Click(object sender, EventArgs e) { Close(); } } }
A database requires maintenance, which consists of locating records, then editing or updaing them. We will use a form to assist the user in taking care of that.
Practical Learning: Editing/Updating a Record
Control | (Name) | Text | |
Button | btnFind | &Find | |
Text Box | txtMake | ||
Text Box | txtModel | ||
Text Box | txtCategory | ||
Button | btnUpdateAutoPart | Up&date Auto-Part |
using System.Xml.Serialization; namespace CollegeParkAutoParts { public partial class StoreItemEditor : Form { List<AutoPart> AutoParts { get; set; } = new List<AutoPart>(); public StoreItemEditor() { InitializeComponent(); } private void InitializeAutoPart() { txtMake.Text = string.Empty; txtModel.Text = string.Empty; txtCategory.Text = string.Empty; txtPartName.Text = string.Empty; txtUnitPrice.Text = string.Empty; txtPartNumber.Text = string.Empty ; lblPictureFile.Text = @"C:\College Park Auto-Parts\Generic.png"; pbxPartImage.Image = Image.FromFile(@"C:\College Park Auto-Parts\Generic.png"); Width = pbxPartImage.Right + 40; Height = pbxPartImage.Bottom + 75; } private void StoreItemEditor_Load(object sender, EventArgs e) { InitializeAutoPart(); } private void btnFind_Click(object sender, EventArgs e) { if( string.IsNullOrEmpty(txtPartNumber.Text)) { MessageBox.Show("You must enter a (valid) number for an auto-part.", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } bool foundAutoPart = false; string strFileName = @"C:\College Park Auto-Parts\AutoParts.xml"; XmlSerializer xsAutoParts = new XmlSerializer(typeof(List<AutoPart>)); if (File.Exists(strFileName)) { using (FileStream fsAutoParts = new(strFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { AutoParts = (List<AutoPart>)xsAutoParts.Deserialize(fsAutoParts)!; for (int i = 0; i < AutoParts.Count; i++) { if (AutoParts[i].PartNumber.Equals(long.Parse(txtPartNumber.Text))) { foundAutoPart = true; txtMake.Text = AutoParts[i].Make; txtModel.Text = AutoParts[i].Model; txtCategory.Text = AutoParts[i].Category; txtPartName.Text = AutoParts[i].PartName; cbxYears.Text = AutoParts[i].Year.ToString(); txtUnitPrice.Text = AutoParts[i].UnitPrice.ToString("F"); pbxPartImage.Image = Image.FromFile(AutoParts[i].PictureFile!); lblPictureFile.Text = AutoParts[i].PictureFile; break; } } } } if(foundAutoPart == false) { MessageBox.Show("There is no auto-part with that number in our records.", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); lblPictureFile.Text = @"C:\College Park Auto-Parts\Generic.png"; pbxPartImage.Image = Image.FromFile(@"C:\College Park Auto-Parts\Generic.png"); } Width = pbxPartImage.Right + 40; Height = pbxPartImage.Bottom + 75; } private void btnSelectPicture_Click(object sender, EventArgs e) { if (ofdPictureFile.ShowDialog() == DialogResult.OK) { lblPictureFile.Text = ofdPictureFile.FileName; pbxPartImage.Image = Image.FromFile(ofdPictureFile.FileName); } else pbxPartImage.Image = Image.FromFile(@"C:\College Park Auto-Parts\Generic.png"); Width = pbxPartImage.Right + 40; Height = pbxPartImage.Bottom + 75; } private void btnUpdateAutoPart_Click(object sender, EventArgs e) { string strFileName = @"C:\College Park Auto-Parts\AutoParts.xml"; XmlSerializer xsAutoParts = new XmlSerializer(typeof(List<AutoPart>)); if (File.Exists(strFileName)) { using (FileStream fsAutoParts = new FileStream(strFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { AutoParts = (List<AutoPart>)xsAutoParts.Deserialize(fsAutoParts)!; } } for (int i = 0; i < AutoParts.Count; i++) { if (AutoParts[i].PartNumber.Equals(long.Parse(txtPartNumber.Text))) { AutoParts[i].Year = Convert.ToInt32(cbxYears.Text); AutoParts[i].Make = txtMake.Text; AutoParts[i].Model = txtModel.Text; AutoParts[i].Category = txtCategory.Text; AutoParts[i].PartName = txtPartName.Text; AutoParts[i].UnitPrice = Convert.ToDouble(txtUnitPrice.Text); AutoParts[i].PictureFile = lblPictureFile.Text; TextWriter twAutoParts = new StreamWriter(strFileName); xsAutoParts.Serialize(twAutoParts, AutoParts); twAutoParts.Close(); break; } } InitializeAutoPart(); } private void btnClose_Click(object sender, EventArgs e) { Close(); } } }
Removing Records
A valuable operation of data management is to remove unwanted records. We will use a form to assist the user with this type of operation.
Practical Learning: Removing Records
Control | (Name) | Text | Additional Properties | |
Text Box | txtYear | TextAlign: Right | ||
Button | btnDeleteAutoPart | Delete Auto-Part |
using System.Xml.Serialization; namespace CollegeParkAutoParts { public partial class StoreItemDelete : Form { List<AutoPart> AutoParts { get; set; } = new List<AutoPart>(); public StoreItemDelete() { InitializeComponent(); } private void InitializeAutoPart() { txtMake.Text = string.Empty; txtModel.Text = string.Empty; txtCategory.Text = string.Empty; txtPartName.Text = string.Empty; txtUnitPrice.Text = string.Empty; txtPartNumber.Text = string.Empty; lblPictureFile.Text = @"C:\College Park Auto-Parts\Generic.png"; pbxPartImage.Image = Image.FromFile(@"C:\College Park Auto-Parts\Generic.png"); Width = pbxPartImage.Right + 40; Height = pbxPartImage.Bottom + 75; } private void StoreItemDelete_Load(object sender, EventArgs e) { InitializeAutoPart(); } private void btnFind_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(txtPartNumber.Text)) { MessageBox.Show("You must enter a (valid) number for an auto-part.", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } bool foundAutoPart = false; XmlSerializer xsAutoParts = new(typeof(List<AutoPart>)); string strFileName = @"C:\College Park Auto-Parts\AutoParts.xml"; if (File.Exists(strFileName)) { using (FileStream fsAutoParts = new(strFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { AutoParts = (List<AutoPart>)xsAutoParts.Deserialize(fsAutoParts)!; for (int i = 0; i < AutoParts.Count; i++) { if (AutoParts[i].PartNumber.Equals(long.Parse(txtPartNumber.Text))) { foundAutoPart = true; txtMake.Text = AutoParts[i].Make; txtModel.Text = AutoParts[i].Model; txtCategory.Text = AutoParts[i].Category; txtPartName.Text = AutoParts[i].PartName; txtYear.Text = AutoParts[i].Year.ToString(); txtUnitPrice.Text = AutoParts[i].UnitPrice.ToString("F"); pbxPartImage.Image = Image.FromFile(AutoParts[i].PictureFile!); lblPictureFile.Text = AutoParts[i].PictureFile; break; } } } } if (foundAutoPart == false) { MessageBox.Show("There is no auto-part with that number in our records.", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); lblPictureFile.Text = @"C:\College Park Auto-Parts\Generic.png"; pbxPartImage.Image = Image.FromFile(@"C:\College Park Auto-Parts\Generic.png"); } Width = pbxPartImage.Right + 40; Height = pbxPartImage.Bottom + 75; } private void btnDeleteAutoPart_Click(object sender, EventArgs e) { XmlSerializer xsAutoParts = new(typeof(List<AutoPart>)); string strFileName = @"C:\College Park Auto-Parts\AutoParts.xml"; if (File.Exists(strFileName)) { using FileStream fsAutoParts = new(strFileName, FileMode.Open, FileAccess.Read, FileShare.Read); AutoParts = (List<AutoPart>)xsAutoParts.Deserialize(fsAutoParts)!; } for (int i = 0; i < AutoParts.Count; i++) { if (AutoParts[i].PartNumber.Equals(long.Parse(txtPartNumber.Text))) { AutoParts.Remove(AutoParts[i]); TextWriter twAutoParts = new StreamWriter(strFileName); xsAutoParts.Serialize(twAutoParts, AutoParts); twAutoParts.Close(); break; } } InitializeAutoPart(); } private void btnClose_Click(object sender, EventArgs e) { Close(); } } }
A Central Point for an Application
You should make your application as user-friendly as possible. For example, you can add a menu or buttons on the first form. The user would then click those button to access the other forms of the application.
Practical Learning: Creating a Central Point for the Application
Control | (Name) | Text | Other Properties | ||
Label | College Park Auto-Parts | Font: Times New Roman, 20.25pt, style=Bold ForeColor: Blue |
|||
Panel | BackColor: Black Height: 2 |
||||
GroupBox | Part Identification | ||||
TreeView | tvwAutoParts | ImageList: AutoPartsImages | |||
GroupBox | Available Parts | ||||
ListView | lvwAutoParts | FullRowSelect: True GridLines: True View: Details |
|||
Columns | (Name) | Text | TextAlign | Width | |
colAvailablePartNumber | Part # | ||||
colAvailablePartName | Part Name/Description | 300 | |||
colAvailableUnitPrice | Unit Price | Right | 80 | ||
GroupBox | Customer Order - Selected Parts | ||||
Label | Part # | ||||
Label | Part Name | ||||
Label | Unit Price | ||||
Label | Qty | ||||
Label | Sub Total | ||||
TextBox | txtPartNumber | ||||
TextBox | txtPartName | ||||
TextBox | txtUnitPrice | TextAlign: Right | |||
TextBox | txtQuantity | TextAlign: Right | |||
TextBox | txtSubTotal | TextAlign: Right | |||
Button | btnAdd | Add/Select | |||
ListView | lvwSelectedParts | FullRowSelect: True GridLines: True View: Details |
|||
Columns | (Name) | Text | TextAlign | Width | |
colSelectedPartNumber | Part # | 45 | |||
colSelectedPartName | Part Name/Description | 274 | |||
colSelectedUnitPrice | Unit Price | Right | 58 | ||
colSelectedQuantity | Qty | Right | 28 | ||
colSelectedSubTotal | Sub-Total | Right | 58 | ||
GroupBox | Order Summary | ||||
Button | btnNewAutoPart | New Au&to Part... | |||
Button | btnUpdateAutoPart | Update Auto Part... | |||
Label | Selected Parts Total: | ||||
TextBox | txtSelectedPartsTotal | 0.00 | TextAlign: Right | ||
Label | Tax Rate: | ||||
TextBox | txtTaxRate | 7.75 | TextAlign: Right | ||
Label | % | ||||
Label | Tax Amount: | ||||
TextBox | txtTaxAmount | TextAlign: Right | |||
Label | Order Total: | ||||
TextBox | txtOrderTotal | 0.00 | TextAlign: Right | ||
Button | btnDeleteAutoPart | Delete Auto-Part ... | |||
Button | btnClose | Close |
using System.Xml.Serialization; namespace CollegeParkAutoParts { public partial class StoreInvetory : Form { /* We will need a list of auto-parts. * For demonstration purpose, we are creating the list as a property * (but a global list is not necessary; we could have used local list variables).*/ public List<AutoPart> AutoParts { get; set; } = new List<AutoPart>(); public StoreInvetory() { InitializeComponent(); } // This function is used to reset the form void InitializeAutoParts() { // When the form must be reset, removes all nodes from the tree view tvwAutoParts.Nodes.Clear(); // Create the root node of the tree view TreeNode nodRoot = tvwAutoParts.Nodes.Add("College Park Auto-Parts", "College Park Auto-Parts", 0, 1); /* Add the cars years to the tree view. * Our application will deal only with the cars in the last 21 years. */ for (int years = DateTime.Today.Year + 1; years >= DateTime.Today.Year - 20; years--) nodRoot.Nodes.Add(years.ToString(), years.ToString(), 2, 3); // Select the root node tvwAutoParts.SelectedNode = nodRoot; // Expand the root node tvwAutoParts.ExpandAll(); // AutoParts = new List<AutoPart>(); // This is the file that holds the list of auto parts string strFileName = @"C:\College Park Auto-Parts\AutoParts.xml"; XmlSerializer xsAutoParts = new(typeof(List<AutoPart>)); if (File.Exists(strFileName)) { // If the inventory file exists, open it using (FileStream fsAutoParts = new FileStream(strFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { // Retrieve the list of items from file AutoParts = (List<AutoPart>)xsAutoParts.Deserialize(fsAutoParts)!; // Show the makes nodes foreach (TreeNode nodYear in nodRoot.Nodes) { List<string> lstMakes = new List<string>(); foreach (AutoPart part in AutoParts) { 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 (AutoPart part in AutoParts) { 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 (AutoPart part in AutoParts) { 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); } } } } } lvwSelectedParts.Items.Clear(); lvwAvailableParts.Items.Clear(); txtPartName.Text = string.Empty; txtQuantity.Text = string.Empty; txtSubTotal.Text = string.Empty; txtUnitPrice.Text = string.Empty; txtTaxAmount.Text = string.Empty; txtOrderTotal.Text = string.Empty; txtPartNumber.Text = string.Empty; txtSelectedPartsTotal.Text = string.Empty; pbxPartImage.Image = Image.FromFile(@"C:\College Park Auto-Parts\Generic.png"); } private void StoreInvetory_Load(object sender, EventArgs e) { InitializeAutoParts(); } private void tvwAutoParts_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { TreeNode nodClicked = e.Node; if (nodClicked.Level == 4) lvwAvailableParts.Items.Clear(); try { foreach (AutoPart part in AutoParts) { 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")); lvwAvailableParts.Items.Add(lviAutoPart); } } } catch (NullReferenceException) { } } private void btnNewAutoPart_Click(object sender, EventArgs e) { StoreItemNew sin = new StoreItemNew(); sin.ShowDialog(); InitializeAutoParts(); } private void lvwAvailableParts_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { bool pictureFound = false; string strFileName = @"C:\College Park Auto-Parts\AutoParts.xml"; XmlSerializer xsAutoParts = new XmlSerializer(typeof(List<AutoPart>)); if (File.Exists(strFileName)) { // If the inventory file exists, open it using (FileStream fsAutoParts = new FileStream(strFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { // Retrieve the list of items from file AutoParts = (List<AutoPart>)xsAutoParts.Deserialize(fsAutoParts)!; foreach (AutoPart part in AutoParts) { if( part.PartNumber == long.Parse(e.Item.SubItems[0].Text)) { pictureFound = true; pbxPartImage.Image = Image.FromFile(part.PictureFile!); break; } } } } if(pictureFound == false) { pbxPartImage.Image = Image.FromFile(@"C:\College Park Auto-Parts\Generic.png"); } Width = pbxPartImage.Right + 40; Height = pbxPartImage.Bottom + 75; } private void lvwAvailableParts_DoubleClick(object sender, EventArgs e) { ListViewItem lviAutoPart = lvwAvailableParts.SelectedItems[0]; if ((lvwAvailableParts.SelectedItems.Count == 0) || (lvwAvailableParts.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) { double subTotal; double unitPrice = 0D; double quantity = 0.00d; try { unitPrice = double.Parse(txtUnitPrice.Text); } catch (FormatException) { MessageBox.Show("Invalid Unit Price!", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); } try { quantity = int.Parse(txtQuantity.Text); } catch (FormatException) { MessageBox.Show("Invalid Quandtity!", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); } subTotal = unitPrice * quantity; txtSubTotal.Text = subTotal.ToString("F"); } internal void CalculateOrder() { // Calculate the current total order and update the order double partsTotal = 0.00D; double taxRate = 0.00D; double taxAmount, orderTotal; if (string.IsNullOrEmpty(txtTaxRate.Text)) txtTaxRate.Text = "7.25"; 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", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); } taxAmount = partsTotal * taxRate; orderTotal = partsTotal + taxAmount; txtSelectedPartsTotal.Text = partsTotal.ToString("F"); txtTaxAmount.Text = taxAmount.ToString("F"); txtOrderTotal.Text = orderTotal.ToString("F"); } private void txtPartNumber_Leave(object sender, EventArgs e) { bool found = false; // After the user had entered a part number, // check the whole list of parts foreach (AutoPart part in AutoParts) { // If you find a part that holds the number the user had entered if (part.PartNumber == long.Parse(txtPartNumber.Text)) { // Show the corresponding part name and unit price txtPartName.Text = part.PartName; txtUnitPrice.Text = part.UnitPrice.ToString("F"); if(string.IsNullOrEmpty(txtQuantity.Text)) txtQuantity.Text = "1"; txtSubTotal.Text = part.UnitPrice.ToString("F"); // Give focus to the quantity in case the user was to increase it txtQuantity.Focus(); // And update the flag that specifies that the part has been found found = true; break; } // If the part number was not found, check the next } // If no part has that number, the found flag is marked as false // If no part with that number was found... if (found == false) { // 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.", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); } } private void btnAdd_Click(object sender, EventArgs e) { if(string.IsNullOrEmpty(txtPartNumber.Text) ) { MessageBox.Show("There is no part to be added to the order.", "College Park Auto-Parts", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } foreach (AutoPart part in AutoParts) { 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 lvwSelectedParts_DoubleClick(object sender, EventArgs e) { ListViewItem 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(); } private void btnUpdateAutoPart_Click(object sender, EventArgs e) { StoreItemEditor sie = new StoreItemEditor(); sie.ShowDialog(); InitializeAutoParts(); } private void btnDeleteAutoPart_Click(object sender, EventArgs e) { StoreItemDelete sid = new StoreItemDelete(); sid.ShowDialog(); InitializeAutoParts(); } private void btnClose_Click(object sender, EventArgs e) { Close(); } } }
Executing and Testing the Application
After creating and application, you can execute it. You can then test it with sample values.
Practical Learning: Executing and Testing the Application
393795 | 2015 | Buick | Regal | Alternators & Generators | DB Electrical Alternator | 218.74 | 928037 |
928374 | 2018 | Chevrolet | Express 3500 | Shocks, Struts & Suspension | Suspension Kit (Front; with 3 Groove Pitman Arm) | 142.44 | 304031 |
730283 | 2020 | Jeep | Wrangler Unlimited Sahara | Oil Filters | Hydraulic Cylinder Timing Belt Tensioner | 14.15 | 730283 |
290741 | 2015 | Ford | F-150 XL 3.5L V6 Flex Regular Cab 2 Full-Size Doors | Shocks, Struts & Suspension | Front Strut and Coil Spring Assembly - Set of 2 | 245.68 | 290741 |
740248 | 2013 | Chevrolet | Equinox | Bearings & Seals | Wheel hub bearing Assembly | 99.95 | 740248 |
283759 | 2012 | Dodge | Charger 3.6L | Starters | DB Electrical SND0787 Starter | 212.58 | 283759 |
799428 | 2012 | Cadillac | XTS | Bearings & Seals | Front/Rear Wheel Hub Bearing Assembly 5 Lugs w/ABS | 79.97 | 799428 |
648203 | 2018 | Honda | CRV | Alternators | Alternator | 202.47 | 593804 |
502853 | 2014 | GMC | Terrain | Bearings & Seals | Wheel Hub Bearing Assembly | 48.85 | 927944 |
520384 | 2020 | Jeep | Wrangler Unlimited Sahara | Drum Brake | Rear Dynamic Friction Company True-Arc Brake Shoes | 42.22 | 520384 |
727394 | 2018 | Toyota | Corolla SE 1.8L L4 Gas | Alternators | DB Electrical 400-40169 Alternator Compatible With/Replacement For 125 Internal Fan Type Decoupler Pulley Type Internal Regulator CW Rotation | 215.84 | 727394 |
927944 | 2017 | Chevrolet | Equinox | Bearings & Seals | Wheel Hub Bearing Assembly | 48.85 | 927944 |
749471 | 2019 | Toyota | Prius | Shocks, Struts & Suspension | 2-Piece Suspension Strut and Coil Spring Kit (593024) | 299.97 | 593024 |
927307 | 2014 | Buick | Regal | Alternators & Generators | DB Electrical Alternator | 218.74 | 928037 |
304031 | 2017 | Chevrolet | Express 2500 | Shocks, Struts & Suspension | Suspension Kit (Front; with 3 Groove Pitman Arm) | 142.44 | 304031 |
497249 | 2013 | GMC | Sierra 1500 | Drum Brake | ACDelco Gold 17960BF1 Bonded Rear Drum Brake Shoe Set | 58.92 | 497249 |
973947 | 2012 | Honda | Accord | Brake Kits | R1 Concepts Front Rear Brakes and Rotors Kit |Front Rear Brake Pads| Brake Rotors and Pads| Ceramic Brake Pads and Rotors | 292.84 | 973947 |
182694 | 2016 | Chevrolet | Impala | Bearings & Seals | Wheel Hub Bearing Assembly | 48.85 | 927944 |
497249 | 2013 | Chevrolet | Silverado 1500 | Drum Brake | ACDelco Gold 17960BF1 Bonded Rear Drum Brake Shoe Set | 58.92 | 497249 |
297149 | 2020 | Jeep | Wrangler | Air Filters | ACDelco Gold A3408C Air Filter | 22.83 | 297149 |
927397 | 2016 | Chevrolet | Impala | Bearings & Seals | Front/Rear Wheel Hub Bearing Assembly 5 Lugs w/ABS | 79.97 | 799428 |
392972 | 2020 | Toyota | Prius AWD-e | Shocks, Struts & Suspension | 2-Piece Suspension Strut and Coil Spring Kit (593024) | 299.97 | 593024 |
928037 | 2017 | Buick | Regal | Alternators & Generators | DB Electrical Alternator | 218.74 | 928037 |
502481 | 2016 | Chevrolet | Equinox | Bearings & Seals | Wheel hub bearing Assembly | 99.95 | 740248 |
593804 | 2019 | Honda | Accord LX 1.5L L4 Gas | Alternator | Alternator | 202.47 | 593804 |
293748 | 2014 | Toyota | Corolla SE 1.8L L4 Gas | Alternators | DB Electrical 400-40169 Alternator Compatible With/Replacement For 125 Internal Fan Type Decoupler Pulley Type Internal Regulator CW Rotation | 215.84 | 727394 |
639704 | 2021 | Kia | Sorento | Brake Kits | Rear Brakes and Rotors Kit |Rear Brake Pads| Brake Rotors and Pads| Optimum OEp Brake Pads and Rotors | 125.15 | 639704 |
829385 | 2020 | Jeep | Wrangler Unlimited Sahara | Drum Brake | Centric Brake Shoe | 22.05 | 829385 |
484695 | 2014 | GMC | Terrain | Bearings & Seals | Front/Rear Wheel Hub Bearing Assembly 5 Lugs w/ABS | 79.97 | 799428 |
807204 | 2016 | Chevrolet | Camaro | Alternators & Generators | DB Electrical Alternator | 218.74 | 928037 |
939283 | 2015 | Chevrolet | Equinox | Bearings & Seals | Wheel Hub Bearing Assembly | 48.85 | 927944 |
738628 | 2021 | Toyota | Prius AWD-e | Shocks, Struts & Suspension | 2-Piece Suspension Strut and Coil Spring Kit (593024) | 299.97 | 593024 |
186950 | 2017 | Honda | CRV | Alternator | Alternator | 202.47 | 593804 |
329573 | 2012 | Chevrolet | Equinox | Bearings & Seals | Front/Rear Wheel Hub Bearing Assembly 5 Lugs w/ABS | 79.97 | 799428 |
594085 | 2015 | Buick | Regal | Bearings & Seals | Front/Rear Wheel Hub Bearing Assembly 5 Lugs w/ABS | 79.97 | 799428 |
928405 | 2018 | Chevrolet | Camaro | Alternators & Generators | DB Electrical Alternator | 218.74 | 928037 |
927937 | 2012 | Ford | Focus SE | Starters | Duralast Starter 19481 | 188.88 | 927937 |
283948 | 2018 | GMC | Savana 3500 | Shocks, Struts & Suspension | Suspension Kit (Front; with 3 Groove Pitman Arm) | 142.44 | 304031 |
495116 | 2020 | Chrysler | Voyager | Brake Kits | Power Stop K7845 Rear Z23 Carbon Fiber Brake Pads with Drilled & Slotted Brake Rotors Kit | 269.75 | 293748 |
180400 | 2012 | Cadillac | CTS FWD | Bearings & Seals | Front/Rear Wheel Hub Bearing Assembly 5 Lugs w/ABS | 79.97 | 799428 |
593024 | 2021 | Toyota | Prius | Shocks, Struts & Suspension | 2-Piece Suspension Strut and Coil Spring Kit (593024) | 299.97 | 593024 |
302839 | 2014 | Chevrolet | Equinox | Bearings & Seals | Wheel Hub Bearing Assembly | 48.85 | 927944 |
649394 | 2020 | Jeep | Wrangler Unlimited Sahara | Brake Kits | Power Stop K7940 Front Z23 Evolution Sport Brake Upgrade Kit | 354.46 | 495116 |
820684 | 2015 | Buick | LaCrosse | Bearings & Seals | Front/Rear Wheel Hub Bearing Assembly 5 Lugs w/ABS | 79.97 | 799428 |
602839 | 2017 | GMC | Savana 2500 | Shocks, Struts & Suspension | Suspension Kit (Front; with 3 Groove Pitman Arm) | 142.44 | 304031 |
|
|||
Home | Copyright © 2005-2023, FunctionX | Wednesday 11 May 2022 | Home |
|