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

  1. In your computer, create a folder named College Park Auto-Parts. If you are using Microsoft Windows, create that folder in your C:\ drive
  2. Save the following image in that folder

    Measures of Center

  3. Start Microsoft Visual Studio
  4. On the Visual Studio (2022) dialog box, click Create a New Project
  5. On the Create a New Project wizard page, in the languages combo box, select C# and, in the list of projects templates, click Windows Forms App
  6. Click Next
  7. In the Configure Your New Project wizard page, change the Project Name to CollegeParkAutoParts2
  8. Accept or change the project Location.
    In the Framework combo box, select the Latest version (.NET 7.0 (Long Term Support)).
    Click Create

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

  1. To create a class, in the Solution Explorer, right-click CollegeParkAutoParts2 -> Add -> Class...
  2. In the middle list of of the Add New Item dialog box, make sure Class is selected.
    Change the file Name to AutoPart
  3. Click Add
  4. Change the document as follows:
    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

  1. To create a dialog box, on the main menu, click Project -> Add Form (Windows Forms)...
  2. Change the Name to Make
  3. Click Add
  4. Design the form as follows:

    College Park Auto-Parts: Makes

    Control (Name) Text Additional Properties
    Label Label   &Make:  
    TextBox Text Box txtMake    
    Button Button btnOK &OK DialogResult: OK
    Button Button btnCancel &Cancel DialogResult: Cancel
  5. Click an unoccupied area of the form and, in the Properties window, change the following characteristics:
    FormBorderStyle: FixedDialog
    StartPosition: CenterScreen
    AcceptButton: btnOK
    CancelButton: btnCancel
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskbar: False

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

  1. To create a dialog box, on the main menu, click Project -> Add Form (Windows Forms)...
  2. Change the Name to Model
  3. Click Add
  4. Design the form as follows:

    College Park Auto-Parts: Models

    Control (Name) Text Additional Properties
    Label Label   &Model:  
    TextBox Text Box txtModel    
    Button Button btnOK &OK DialogResult: OK
    Button Button btnCancel &Cancel DialogResult: Cancel
  5. Click an unoccupied area of the form and, in the Properties window, change the following characteristics:
    FormBorderStyle: FixedDialog
    StartPosition: CenterScreen
    AcceptButton: btnOK
    CancelButton: btnCancel
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskbar: False

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 LearningPractical Learning: Setting Items Categories

  1. To create a dialog box, on the main menu, click Project -> Add Windows Form...
  2. Set the name to Category
  3. Click Add
  4. Design the form as follows:

    College Park Auto-Parts: Makes

    Control (Name) Text Additional Properties
    Label Label   C&ategory:  
    TextBox Text Box txtCategory    
    Button Button btnOK &OK DialogResult: OK
    Button Button btnCancel &Cancel DialogResult: Cancel
  5. Click an unoccupied area of the form and, in the Properties window, change the following characteristics:
    FormBorderStyle: FixedDialog
    StartPosition: CenterScreen
    AcceptButton: btnOK
    CancelButton: btnCancel
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskbar: False

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 LearningPractical Learning: Preparing an Items Inventory

  1. To create a new form, in the Solution Explorer, right-click CollegeParkAutoParts1 -> Add -> Form (Windows Forms)...
  2. Change the Name to StoreItemNew
  3. Click Add
  4. Design the form as follows:

    College Park Auto Parts - New Store Item

    Control (Name) Text Additional Properties
    Label Label   &Part #:  
    TextBox Text Box txtPartNumber    
    Button Button btnSelectPicture &Select Picture...  
    Label Label   &Year:  
    Combo Box Combo Box cbxYears    
    Picture Box Picture Box pbxPartImage   BorderStyle: FixedSingle
    SizeMode: AutoSize
    Label Label   &Make:  
    Combo Box Combo Box cbxMakes    
    Button Button btnNewMake New M&ke...  
    Label Label   M&odel  
    Combo Box Combo Box cbxModels    
    Button Button btnNewModel New Mo&del...  
    Label Label   Ca&tegory:  
    Combo Box Combo Box cbxCategories    
    Button Button btnNewCategory New Cat&egory...  
    Label Label   Part Na&me:  
    Text Box Text Box txtPartName   ScrollBars: Vertical
    Multiline: True
    Label Label   &Unit Price:
    Text Box Text Box txtUnitPrice   TextAlign: Right
    Label Label   ____________________  
    Button Button btnSaveAutoPart Sa&ve Auto-Part  
    Button Button Close btnClose  
    Open File Dialog Open File Dialog ofdPictureFile    
  5. Double-click an unoccupied area of the form to generate its Load event
  6. Return to the form and double-click the &Select Picture... button
  7. Return to the form and double-click the Make combo box to generate its SelectedIndexChanged event
  8. Return to the form and double-click the New M&ake... button
  9. Return to the form and double-click the New Mo&del... button
  10. Return to the form and double-click the New Cat&egory... button
  11. Return to the form and double-click the Sa&ve Auto-Part button
  12. Return to the form and double-click the Close button
  13. Change the document as follows:
    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();
            }
        }
    }

Editing/Updating an Auto-Part

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 LearningPractical Learning: Editing/Updating a Record

  1. To create a form, on the main menu of Microsoft Visual Studio, click Project and click Add Form (Windows Forms...)
  2. Change the file Name to StoreItemEditor
  3. Click Add Resize the form to have the same size as the New Store Item form Display the New Store Item form
  4. Copy everything on it (you can press Ctrl + A and then press Ctrl + C)
  5. Display the Store Item Editor form
  6. Paste everything (you can press Ctrl + V)
  7. Change the design of the form as follows:

    Add New Item

    Control (Name) Text
    Button Button btnFind &Find
    Text Box Text Box txtMake  
    Text Box Text Box txtModel  
    Text Box Label txtCategory  
    Button Button btnUpdateAutoPart Up&date Auto-Part
  8. Double-click an unoccupied area of the form to generate its Load event
  9. Return to the form and double-click the Find button
  10. Return to the form and double-click the &Select Picture... button
  11. Return to the form and double-click the Up&date Auto-Part button
  12. Return to the form and double-click the Close button
  13. Change the document as follows:
    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 of data management is to remove unwanted records. We will use a form to assist the user with this type of operation.

Practical LearningPractical Learning: Removing Records

  1. To create a new form, on the main menu of Microsoft Visual Studio, click Project -> Add Form (Windows Forms...)
  2. Type the file Name as StoreItemDelete
  3. Click Add
  4. Resize the form to have the same size as the Store Item Editor form
  5. Display the Store Item Editor form and copy everything on it (you can press Ctrl + A and then press Ctrl + C)
  6. Display the Store Item Delete form and paste everything in it (you can press Ctrl + V
  7. Chang the design of the form as follows:

    College Park Auto-Parts - Store Item Delete

    Control (Name) Text Additional Properties
    Text Box Text Box txtYear   TextAlign: Right
    Button Button btnDeleteAutoPart Delete Auto-Part  
  8. Double-click an unoccupied area of the form
  9. Return to the form and double-click the Find button
  10. Return to the form and double-click the &Delete Auto-Part button
  11. Return to the form and double-click the Close button
  12. Change the document as follows:
    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 LearningPractical Learning: Creating a Central Point for the Application

  1. In the Solution Explorer, right-click Form1.cs and click Rename
  2. Type StoreInventory (to have StoreInventory.cs) and press Enter three times to accept the name and display the form
  3. From the Components section of the Toolbox, click ImageList and click the form
  4. In the Properties window, click (Name) and type AutoPartsImages
  5. Click the ellipsis button of the Images field
  6. In the Image Collection Editor, click Add
  7. Locate the folder that contains the resources for these lessons and display it in the Look In combo box
  8. Select the following icons: Sign1, Sign2, Cliper1, Cliper2, Rulers1, Rulers2, Graph1, Graph2, Tool1, and Tool2
  9. Click Open

    Image Collection Editor

  10. Click OK
  11. Click OK
  12. Design the form as follows:

    College Park Auto Parts - Form Design

    Control (Name) Text Other Properties
    Label Label   College Park Auto-Parts Font: Times New Roman, 20.25pt, style=Bold
    ForeColor: Blue
    Panel Panel     BackColor: Black
    Height: 2
    GroupBox Group Box   Part Identification  
    TreeView Tree View tvwAutoParts   ImageList: AutoPartsImages
    GroupBox Group Box   Available Parts  
    ListView List View 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 Group Box   Customer Order - Selected Parts  
    Label Label   Part #  
    Label Label   Part Name  
    Label Label   Unit Price  
    Label Label   Qty  
    Label Label   Sub Total  
    TextBox Text Box txtPartNumber    
    TextBox Text Box txtPartName    
    TextBox Text Box txtUnitPrice   TextAlign: Right
    TextBox Text Box txtQuantity   TextAlign: Right
    TextBox Text Box txtSubTotal   TextAlign: Right
    Button Button btnAdd Add/Select  
    ListView List View 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 Group Box Order Summary    
    Button Button btnNewAutoPart New Au&to Part...  
    Button Button btnUpdateAutoPart Update Auto Part...  
    Label Label   Selected Parts Total:  
    TextBox Text Box txtSelectedPartsTotal 0.00 TextAlign: Right
    Label Label Tax Rate:    
    TextBox Text Box txtTaxRate 7.75 TextAlign: Right
    Label Label   %  
    Label Label   Tax Amount:  
    TextBox Text Box txtTaxAmount   TextAlign: Right
    Label Label   Order Total:  
    TextBox Text Box txtOrderTotal 0.00 TextAlign: Right
    Button Button btnDeleteAutoPart Delete Auto-Part ...  
    Button Button btnClose Close  
  13. Double-click an unoccupied area of the form to generate its load event
  14. Return to the form and, in the Properties window, click the Events button Events
  15. On the form, click the Part Identification tree view
  16. In the Events section of the Properties window, double-click NodeMouseClick
  17. Return to the form and double-click the New Au&to Part button
  18. On the form, click the Available Parts list view to select it and, in the Events section Properties window, double-click ItemSelectionChanged
  19. Return to the form and make sure the Available Parts list view is still selected.
    In the Events section of the Properties, double-click DoubleClick
  20. Return to the form and click the Part # text box to select it
  21. In the Events section of the Properties window, double-click Leave
  22. Return to the form and click the Unit Price text box to select it
  23. In the Events section of the Properties window, double-click Leave
  24. Return to the form and click the Qty text box to select it
  25. In the Events section of the Properties window, click the arrow of the Leave combo box and select txtUnitPrice_Leave
  26. Return to the form and double-click the Add/Select
  27. Return to the form and click the Selected Parts list view to select it
  28. In the Events section of the Properties window, double-click DoubleClick
  29. Return to the form and double-click the Update Auto-Part button
  30. Return to the form and double-click the Delete Auto-Part button
  31. Return to the form and double-click the Close button
  32. Change the document as follows:
    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 LearningPractical Learning: Executing and Testing the Application

  1. To execute the application, on the main menu, click Debug -> Start Without Debugging:

  2. Click the New Auto Part button

  3. Click the New Make button
  4. Click Cancel
  5. Create some auto parts as follows:
    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 & SuspensionFront Strut and Coil Spring Assembly - Set of 2 245.68 290741
    740248 2013 Chevrolet EquinoxBearings & 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 TerrainBearings & SealsWheel Hub Bearing Assembly48.85 927944
    520384 2020 Jeep Wrangler Unlimited SaharaDrum BrakeRear 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 BrakeACDelco 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 & SealsWheel 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 ImpalaBearings & Seals Front/Rear Wheel Hub Bearing Assembly 5 Lugs w/ABS 79.97 799428
    392972 2020 ToyotaPrius AWD-eShocks, Struts & Suspension2-Piece Suspension Strut and Coil Spring Kit (593024)299.97593024
    928037 2017 BuickRegalAlternators & GeneratorsDB Electrical Alternator218.74928037
    502481 2016 ChevroletEquinoxBearings & SealsWheel hub bearing Assembly99.95740248
    593804 2019HondaAccord LX 1.5L L4 GasAlternatorAlternator202.47593804
    293748 2014ToyotaCorolla SE 1.8L L4 GasAlternatorsDB Electrical 400-40169 Alternator Compatible With/Replacement For 125 Internal Fan Type Decoupler Pulley Type Internal Regulator CW Rotation215.84727394
    639704 2021KiaSorentoBrake KitsRear Brakes and Rotors Kit |Rear Brake Pads| Brake Rotors and Pads| Optimum OEp Brake Pads and Rotors125.15639704
    829385 2020JeepWrangler Unlimited SaharaDrum BrakeCentric Brake Shoe22.05829385
    484695 2014GMCTerrainBearings & SealsFront/Rear Wheel Hub Bearing Assembly 5 Lugs w/ABS79.97799428
    807204 2016ChevroletCamaroAlternators & GeneratorsDB Electrical Alternator218.74928037
    939283 2015ChevroletEquinoxBearings & SealsWheel Hub Bearing Assembly48.85927944
    738628 2021ToyotaPrius AWD-eShocks, Struts & Suspension2-Piece Suspension Strut and Coil Spring Kit (593024)299.97593024
    186950 2017HondaCRVAlternatorAlternator202.47593804
    329573 2012ChevroletEquinoxBearings & SealsFront/Rear Wheel Hub Bearing Assembly 5 Lugs w/ABS79.97799428
    594085 2015BuickRegalBearings & SealsFront/Rear Wheel Hub Bearing Assembly 5 Lugs w/ABS79.97799428
    928405 2018ChevroletCamaroAlternators & GeneratorsDB Electrical Alternator218.74928037
    927937 2012FordFocus SEStartersDuralast Starter 19481188.88927937
    283948 2018GMCSavana 3500Shocks, Struts & SuspensionSuspension Kit (Front; with 3 Groove Pitman Arm)142.44304031
    495116 2020ChryslerVoyagerBrake KitsPower Stop K7845 Rear Z23 Carbon Fiber Brake Pads with Drilled & Slotted Brake Rotors Kit269.75293748
    180400 2012CadillacCTS FWDBearings & SealsFront/Rear Wheel Hub Bearing Assembly 5 Lugs w/ABS79.97799428
    593024 2021ToyotaPriusShocks, Struts & Suspension2-Piece Suspension Strut and Coil Spring Kit (593024)299.97593024
    302839 2014ChevroletEquinoxBearings & SealsWheel Hub Bearing Assembly48.85927944
    649394 2020JeepWrangler Unlimited SaharaBrake KitsPower Stop K7940 Front Z23 Evolution Sport Brake Upgrade Kit 354.46495116
    820684 2015BuickLaCrosseBearings & SealsFront/Rear Wheel Hub Bearing Assembly 5 Lugs w/ABS79.97799428
    602839 2017GMCSavana 2500Shocks, Struts & SuspensionSuspension Kit (Front; with 3 Groove Pitman Arm)142.44304031
  6. Close the forms and return to your programming environment
  7. Close your programming environment

Home Copyright © 2005-2023, FunctionX Wednesday 11 May 2022 Home