Home

XML-Based Applications:
College Park Auto-Parts

 
 

Inventory Creation

The inventory of our store is created by adding store items to an XML file. To do this, once again, we take advantage of the XmlDocument, the XmlNode, and its derived classes. This inventory is created using the New Part form.

We need to apply some rules in order to create a store item. Early rules can make the application easier to use and maintain. For example, we must create an item only if it can be clearly identified. This makes it easy to locate it when processing an order. We explain through the comments in the code.

 

Practical Learning Practical Learning: Creating the Inventory

  1. Display the New Model form and double-click the New Make button
  2. Change the Click event of the btnNewMake button as follows:
     
    System::Void btnNewMake_Click(System::Object *  sender, System::EventArgs *  e)
    {
    	 // The new car make will come from the New Make dialog box
    	 NewMake *frmMake = new NewMake;
    
    	 // Display the New Make dialog box and find out if the user clicked OK
    	 if( frmMake->ShowDialog() == DialogResult::OK )
    	 {
    		 String *strNewMake = frmMake->txtNewMake->Text;
    
    		 // If the user didn't create a new Make, don't do anything
    		 if( strNewMake->Equals(S"") )
    			 return;
    
    		 // Before adding the new make, check that it doesn't exist already
    		 if( this->cboMakes->FindStringExact(strNewMake) > 0 )
    			 return;
    
    		 // Now you can add it
    		 this->cboMakes->Items->Add(strNewMake);
    		 // The user likely wants this new item selected
    		 this->cboMakes->Text = strNewMake;
    
    		 // Open the Cars.xml file
    		 XmlDocument *docXMLFile = new XmlDocument;
    		 docXMLFile->Load(S"Cars.xml");
    
    		 // Get the root node so we can explore its children
    		 XmlNode *nodRoot = docXMLFile->DocumentElement;
    		 
    		 // If the car is not in the list already, create its Make node
    	XmlNode *nodNewMake  = docXMLFile->CreateNode(XmlNodeType::Element, S"Make", S"");
    		 // Create an attribute for the node
    	 dynamic_cast<XmlElement *>(nodNewMake)->SetAttribute(S"MakeName", strNewMake);
    		 
    		 // Add the new node to the XML file
    		 docXMLFile->DocumentElement->AppendChild(nodNewMake);
    		 
    		 // Save the file
    		 docXMLFile->Save(S"Cars.xml");
    	}
    }
  3. Display the New Part form and double-click the New Make button
  4. Change the Click event of the btnNewMake button as follows:
     
    System::Void btnNewMake_Click(System::Object *  sender, System::EventArgs *  e)
    {
    	 // The new car make will come from the New Make dialog box
    	 NewMake *frmMake = new NewMake;
    
    	 // Display the New Make dialog box and find out if the user clicked OK
    	 if( frmMake->ShowDialog() == DialogResult::OK )
    	 {
    		 String *strNewMake = frmMake->txtNewMake->Text;
    
    		 // If the user didn't create a new Make, don't do anything
    		 if( strNewMake->Equals(S"") )
    			 return;
    
    		 // Before adding the new make, check that it doesn't exist already
    		 if( this->cboMakes->FindStringExact(strNewMake) > 0 )
    			 return;
    
    		 // Now you can add it
    		 this->cboMakes->Items->Add(strNewMake);
    		 // The user likely wants this new item selected
    		 this->cboMakes->Text = strNewMake;
    
    		 // Open the Cars.xml file
    		 XmlDocument *docXMLFile = new XmlDocument;
    		 docXMLFile->Load(S"Cars.xml");
    
    		 // Get the root node so we can explore its children
    		 XmlNode *nodRoot = docXMLFile->DocumentElement;
    		 
    		 // If the car is not in the list already, create its Make node
    	XmlNode *nodNewMake  = docXMLFile->CreateNode(XmlNodeType::Element, S"Make", S"");
    		 // Create an attribute for the node
    	 dynamic_cast<XmlElement *>(nodNewMake)->SetAttribute(S"MakeName", strNewMake);
    		 
    		 // Add the new node to the XML file
    		 docXMLFile->DocumentElement->AppendChild(nodNewMake);
    		 
    		 // Save the file
    		 docXMLFile->Save(S"Cars.xml");
    	}
    }
  5. Display the New Part form again and double-click the New Model button
  6. Implement its Click event as follows:
     
    System::Void btnNewModel_Click(System::Object *  sender, System::EventArgs *  e)
    {
    	 // The new car model will come from the New Model dialog box
    	 NewModel *frmModel = new NewModel;
    
    	 // Display the New Model dialog box and find out if the user clicked OK
    	 if( frmModel->ShowDialog() == DialogResult::OK )
    	 {
    		 // Retrieve the values that the user specified
    		 String *strMake     = frmModel->cboMakes->Text;
    		 String *strNewModel = frmModel->txtNewModel->Text;
    
    		 // If the user didn't select a Make, don't do anything
    		 if( strMake->Equals(S"") )
    			 return;
    		 // If the New Model string is empty, don't do anything
    		 if( strNewModel->Equals(S"") )
    			 return;
    
    		 // Open the Cars.xml file
    		 XmlDocument *docXMLFile = new XmlDocument;
    		 docXMLFile->Load(S"Cars.xml");
    
    		 // Get the root node so we can explore its children
    		 XmlNode *nodRoot     = docXMLFile->DocumentElement;
    		 
    		 // Create a list of all Make nodes
    		 XmlNodeList *lstMakes = docXMLFile->GetElementsByTagName(S"Make");
    
    		 // Visit each Make
    		 for(int i = 0; i < lstMakes->Count; i++)
    		 {
    			 // Get a reference to the current node
    			 XmlNode *curMake = lstMakes->ItemOf[i];
    
    			 // If, or when you find the Make
    		if( curMake->Attributes->ItemOf[S"MakeName"]->InnerText->Equals(strMake) )
    			 {
    				 // Since we found the Make, find out if the model exists
    				 XmlNodeList *lstCurrentModels = curMake->ChildNodes;
    
    				 // Check each model if the list already contains the model
    				 for(int j = 0; j < lstCurrentModels->Count; j++)
    				 {
    				 if( lstCurrentModels->ItemOf[j]->InnerText->Equals(strNewModel) )
    					 {
    				MessageBox::Show(S"That model exists already in the database");
    						 return;
    					 }
    				 }
    
    				 // create a child node to it
    	    XmlNode *nodModel = docXMLFile->CreateNode(XmlNodeType::Element, S"Model", S"");
    			 // Create its value using the string from the New Make dialog box
    				 nodModel->InnerText = strNewModel;
    				 // Add the new element at the end of the file
    				 curMake->AppendChild(nodModel);
    
    				 // Save the file
    				 docXMLFile->Save(S"Cars.xml");
    				 break;
    			 }
    		 }
    	}
    }
  7. Display the New Part form again and double-click the Make combo box
  8. Implement its SelectedIndexChanged event as follows:
     
    System::Void cboMakes_SelectedIndexChanged(System::Object *  sender, System::EventArgs *  e)
    {
    	 // Empty the Models combo box
    	 this->cboModels->Items->Clear();
    
    	 // Find out if the user had selected a Make
    	 String *strSelectedMake = this->cboMakes->Text;
    	 // Open the Cars.xml file
    	 XmlDocument *docXML = new XmlDocument();
    	 docXML->Load(S"Cars.xml");
    
    	 // Get a reference to the root node
    	 XmlElement *nodRoot = docXML->DocumentElement;
    	 // Locate all nodes whose name is Make
    	 XmlNodeList *nodMakes = nodRoot->GetElementsByTagName(S"Make");
    	 // Look for the Make that is the same the user selected
        	for(int i = 0; i < nodMakes->Count; i++)
    	{
    	    // Retrieve the value of each Make node and put
    String *strMakeName = nodMakes->ItemOf[i]->Attributes->ItemOf[S"MakeName"]->InnerText;
    	    // If you find it...
    	    if( strMakeName->Equals(strSelectedMake) )
    	   {
    		// If you find it, make a list of its models...
    		XmlNodeList *nodAvailableModels = nodMakes->ItemOf[i]->ChildNodes;
    		// ... then add each of its models to the Model combo box
    		for(int j = 0; j < nodAvailableModels->Count; j++)
    		this->cboModels->Items->Add(nodAvailableModels->ItemOf[j]->InnerText);
    	  }
    	}
    }
  9. Display the New Part form again and double-click the New Category button
  10. Change its Click event as follows:
     
    System::Void btnNewCategory_Click(System::Object *  sender, System::EventArgs *  e)
    {
    	 // Get a reference to the New Part Category form
    	 NewPartCategory *frmCategory = new NewPartCategory;
    
    	 // Display the New Part Category dialog box and find out if the user clicked OK
    	 if( frmCategory->ShowDialog() == DialogResult::OK )
    	 {
    		 String *strCategory = frmCategory->txtNewCategory->Text;
    
    		 // If the user didn't create a new category, don't do anything
    		 if( strCategory->Equals(S"") )
    			 return;
    
    		 // Before adding the new category, check that it doesn't exist already
    		 if( this->cboPartCategories->FindStringExact(strCategory) > 0 )
    			 return;
    
    		 // Now you can add it
    		 this->cboPartCategories->Items->Add(strCategory);
    		 // The user likely wants this new item selected
    		 this->cboPartCategories->Text = strCategory;
    
    		 // Open the PartCategories.xml file
    		 XmlDocument *docXMLFile = new XmlDocument;
    		 docXMLFile->Load(S"PartCategories.xml");
    
    		 // Get the root node so we can explore its children
    		 XmlNode *nodRoot = docXMLFile->DocumentElement;
    		 
    		 // If the new part is not in the list already, create its node
    XmlNode *nodNewCategory  = docXMLFile->CreateNode(XmlNodeType::Element, S"PartCategory", S"");
    		 // Create text for the node
    		 nodNewCategory->InnerText = strCategory;
    		 
    		 // Add the new node to the XML file
    		 docXMLFile->DocumentElement->AppendChild(nodNewCategory);
    		 
    		 // Save the file
    		 docXMLFile->Save(S"PartCategories.xml");
    	}
    }
  11. Return to the New Part form and double-click the Part Name text box
  12. Implement its TextChanged event as follows:
     
    System::Void txtPartName_TextChanged(System::Object *  sender, System::EventArgs *  e)
    {
    	 // If there is no part name, no need to add the item to the XML file
    	 if( this->txtPartName->Text->Equals(S"") )
    		 this->btnAddPart->Enabled = false;
    	 else
    		 this->btnAddPart->Enabled = true;
    }
  13. Return to the New Part form and double-click the Unit Price text box
  14. Implement its TextChanged event as follows:
     
    System::Void txtUnitPrice_TextChanged(System::Object *  sender, System::EventArgs *  e)
    {
    	 // If the price is not specified, don't add the item to the XML file
    	 if( this->txtUnitPrice->Text->Equals(S"") )
    		 this->btnAddPart->Enabled = false;
    	 else
    		 this->btnAddPart->Enabled = true;
    }
  15. Return to the New Part form and double-click the Part # text box
  16. Implement its TextChanged event as follows:
     
    System::Void txtPartNumber_TextChanged(System::Object *  sender, System::EventArgs *  e)
    {
    	 // Make sure that there is a Part Number for this item
    	 // Otherwise, don't add the part to the XML file
    		 if( this->txtPartNumber->Text->Equals(S"") )
    			 this->btnAddPart->Enabled = false;
    		 else
    			 this->btnAddPart->Enabled = true;
    }
  17. Return to the New Part form and double-click the Add Part button
  18. Implement its Click event as follows:
     
    System::Void btnAddPart_Click(System::Object *  sender, System::EventArgs *  e)
    {
    	 // Open the Parts.xml file
    	 XmlDocument *docXML = new XmlDocument();
    	 docXML->Load(S"Parts.xml");
    
    	 // Before adding the new part, make sure all components are ready
    	 // Otherwise, don't add it
    	 if( this->cboYears->SelectedIndex < 0 )
    	 {
    		 MessageBox::Show(S"You must specify the year. "
    				  S"This will help to locate the part");
    		 this->cboYears->Focus();
    		 return;
    	 }
    	 if( this->cboMakes->SelectedIndex < 0 )
    	 {
    		 MessageBox::Show(S"Please select the car make for this part.");
    		 this->cboMakes->Focus();
    		 return;
    	 }
    	 if( this->cboModels->SelectedIndex < 0 )
    	 {
    		 MessageBox::Show(S"The car model is required. "
    				S"It helps to know the specific car this part is made for.");
    		 this->cboModels->Focus();
    		 return;
    	 }
    	 if( this->txtPartName->Text->Equals(S"") )
    	 {
    		MessageBox::Show(S"You must specify the part name or a (very) short description.");
    		 this->txtPartName->Focus();
    		 return;
    	 }
    	 if( this->txtUnitPrice->Text->Equals(S"") )
    	 {
    		 MessageBox::Show(S"You must enter the price of each unit of this part.");
    		 this->txtUnitPrice->Focus();
    		 return;
    	 }
    	 if( this->txtPartNumber->Text->Equals(S"") )
    	 {
    		 MessageBox::Show(S"Every item of this database must have a number. "
    				  S"The number is just a combination of letters and digits."
    				  S"Please make up a number and enter it in the Part # box.");
    		 this->txtPartNumber->Focus();
    		 return;
    	 }
    
    	 // The part seems to be ready
    	 // Get a reference to the root node
    	 XmlElement *nodNewPart = docXML->CreateElement(S"Part");
    	 // Create a new part as a child of the root (this is a simple node addition)
    	 String *strNewPart = String::Concat(S"<PartNumber>",
    					 this->txtPartNumber->Text, S"</PartNumber>",
    					S"<CarYear>", this->cboYears->Text, S"</CarYear>",
    					 S"<Make>", this->cboMakes->Text, S"</Make>",
    					 S"<Model>", this->cboModels->Text, S"</Model>",
    					 S"<PartName Category=\"",
    					 this->cboPartCategories->Text,S"\">",
    					 this->txtPartName->Text, S"</PartName>",
    					 S"<UnitPrice>", this->txtUnitPrice->Text,
    					S"</UnitPrice>");
    	 nodNewPart->InnerXml = strNewPart;
    	 docXML->DocumentElement->AppendChild(nodNewPart);
    	 docXML->Save(S"Parts.xml");
    
    	 // Reset the form in case the user wants to add another part
    	 this->cboYears->SelectedIndex = -1;
    	 this->cboMakes->SelectedIndex = -1;
    	 this->cboModels->SelectedIndex = -1;
    	 this->cboPartCategories->Text = S"Miscellaneous";
    	 this->txtPartName->Text = S"";
    	 this->txtUnitPrice->Text = S"";
    	 
    	 // We will generate a random number for the item
    	 // To start, we will use the miliseconds as a seed
    	 DateTime tmeNow = DateTime::Now;
    	 int ms = tmeNow.Millisecond;
    
    	 // Now we can generate a random number between 100000 and 999999
    	 Random *rndNumber = new Random(ms);
    
    	 // Generate three random characters
    	 Char firstCharacter  = static_cast<Char>(rndNumber->Next(65, 90));
    	 Char secondCharacter = static_cast<Char>(rndNumber->Next(65, 90));
    	 Char thirdCharacter  = static_cast<Char>(rndNumber->Next(65, 90));
    	 // Generate a random number made of 4 digits
    	 int numberPart = rndNumber->Next(1000, 9999);
    	 
    	 // Exclude the digits 1 and 0 because they create confusion
    	 if( firstCharacter == 'I' || firstCharacter == 'O' )
    		 firstCharacter = 'A';
    	 if( secondCharacter == 'I' || secondCharacter == 'O' )
    		 secondCharacter = 'A';
    	 if( thirdCharacter == 'I' || thirdCharacter == 'O' )
    		 thirdCharacter = 'A';
    	 // Generate a random number between 1 and 3
    	 int rndCombination = rndNumber->Next(1, 4);
    	 String *strPartNumber = 0;
    
    	 // Create a part number using some algorithm
    	 if( rndCombination == 1 )
    		 strPartNumber = String::Concat(firstCharacter.ToString(),
    						secondCharacter.ToString(), 
    						numberPart.ToString(),
    						thirdCharacter.ToString());
    	 else if( rndCombination == 2 )
    		 strPartNumber = String::Concat(firstCharacter.ToString(),
    						numberPart.ToString(), 
    						secondCharacter.ToString(),
    						thirdCharacter.ToString());
    	 else if( rndCombination == 3 )
    		 strPartNumber = String::Concat(numberPart.ToString(),
    						firstCharacter.ToString(), 
    						secondCharacter.ToString(),
    						thirdCharacter.ToString());
    	 else
    		 strPartNumber = rndNumber->Next(100000, 999999).ToString();
    
    	 // Display the new number in the Part # text box
    	 this->txtPartNumber->Text = strPartNumber;
    	 this->cboYears->Focus();
    }
  19. Execute the application to test it
  20. Add a few parts as follows (let the computer generate part numbers):
     
    Year Make Model Part Category Part Name Unit Price
    2002 Audi A4 Quattro 1.8L Turbo Exhaust Exhaust Gasket 1.55
    2004 Dodge Neon SE 2.0L L4 Cooling System Radiator Fan Assembly 125.95
    2002 Audi A4 Quattro 1.8L Turbo Drivetrain Axle Differential Bearing - Left 10.25
    2000 Ford Escort 2.0L L4 Ignition Crankshaft Position Sensor 18.65
    2002 Chevrolet Silverado 2500 5.3L V8 Ignition Spark Plugs 1.55
    2004 Dodge Neon SE 2.0L L4 Engine Oil Pump 112.85
    2004 Dodge Neon SE 2.0L L4 Engine Exhaust Valve 5.85
    1986 Acura Integra LS 1.8L L4 Electrical Alternator 110.75
    1998 Toyota Corolla 1.8L L4 Cooling System Radiator 95.95
    2002 Dodge Dakota 3.9L V6 Electrical Starter Motor 145.95
    2004 Honda Civic EX 1.7L L4 Emission Oxygen Sensor 90.55
    2002 Audi A4 Quattro 1.8L Turbo Electrical Alternator 305.50
    2002 Acura NSX 3.0L V6 Engine Oil Filter 7.05
    1998 Jeep Wrangler 2.5L L4 Transfer Case Input Shaft Seal Transfer Case 6.45
    1986 Acura Integra LS 1.8L L4 Fuel/Air Fuel Cap (Regular) 4.15
    2000 Ford Escort 2.0L L4 Brake System Right Caliper Assembly Front 32.85
    2004 Dodge Neon SE 2.0L L4 Clutch Clutch Release Bearing 25.75
    1998 BMW 325I 2.5L L6 Steering Rack and Pinion Bellow Kit 19.25
    2001 Acura Integra GS 1.8L L4 Electrical Voltage Regulator 215.75
    2001 Audi S4 2.7L V6 Engine Timing Belt 35.95
    2002 Audi A4 Quattro 1.8L Turbo Exhaust Muffler Hanger 3.35
    2002 Chevrolet Silverado 2500 5.3L V8 Cooling System Radiator w/Air Tube - w/TOC 215.75
    2002 Acura NSX 3.0L V6 Engine Oil Drain Plug 1.35
    2002 Dodge Dakota 3.9L V6 Electrical Circuit Breaker 3.25
    2004 Dodge Neon SE 2.0L L4 Brake System Brake Pad 20.55
    2004 Honda Civic EX 1.7L L4 Electrical Fusible Link 3.35
    2002 Dodge Dakota 3.9L V6 Electrical Circuit Breaker 3.45
    2004 Honda Civic EX 1.7L L4 Transmission-Manual Differential Bearing 36.75
    1998 Toyota Corolla 1.8L L4 Cooling System Thermostat Standard Temperature 9.35
    2002 Audi A4 Quattro 1.8L Turbo Electrical Cooling Fan Sensor 8.65
    2002 Acura NSX 3.0L V6 Engine Oil Pump Seal 12.55
    2004 Dodge Neon SE 2.0L L4 Brake System Master Cylinder w/o ABS w/2 Wheel 102.95
    2002 Acura NSX 3.0L V6 Engine Valve Stem Oil Seal 1.75
    2002 Dodge Dakota 3.9L V6 Electrical Fuse 0.40
    1998 Toyota Corolla 1.8L L4 Cooling System Regular Thermostat 11.15
  21. Close the forms and return to your programming environment
 

Previous Copyright © 2004-2016, FunctionX, Inc. Next