Introduction:
In the previous 62nd chapter, "The GridView batch update data", we have customized a batch editing interface with the GridView control, and we can also customize a batch add interface. Assuming this is the case, we accept a shipment of goods from Tokyo (Tokyo): 6 different tea varieties and Coffee, if a user enters one product at a time in a DetailsView control, he will repeatedly enter many of the same values, such as the same kind (beverages), the same supplier (Tokyo traders), the same discontinued value ( False), and the same order value (0). Repetitive input These same values are not only tiring, but also error prone. With just a little extra work, we can create a batch add interface. Users can simply select supplier and category at a time, enter names and unit prices for a range of products, and then click a button to add these new products to the database (as shown in Figure 1). The ProductName of these added products and UnitPrice data is specified by 2 DropDownList controls above the interface, and discontinued and UnitsOnOrder values are specified by "hard edit", false and 0 respectively.
Figure 1: Batch Add interface
In this tutorial, we will create a batch add interface as shown in Figure 1. On the basis of the previous 2 chapters we will encapsulate the addition process with transactions to ensure atomic operation. Let's get started!
First step: Create a display interface
We'll create a single page with 2 areas: the presentation area and the Add area. What we created in this step is the display area, which contains a GridView control for displaying the product and a title "Process Product Shipment" button. When the button is clicked, the display interface is replaced with an add interface as shown in Figure 1. If you click the Add product from Shipment or Cancel button, the display page is returned. The add interface will be completed in the second step.
This page, which contains 2 interfaces, can only make one interface visible at a time. We will include these 2 interfaces as containers with 2 panel Web controls--a panel Web control that contains an interface.
First open the Batchinsert.aspx page in the Batchdata folder, drag a Panel control from the Toolbox to the page in designer mode (as shown in Figure 2), Set its ID to displayinterface. When you drag a Panel control to the page, its height and width properties are 50px and 125px respectively. Clear these properties in the Properties window.
Figure 2: Dragging a Panel control from the Toolbox to the page
Then drag a button and the GridView control into the Panel control. Set the button's ID to processshipment and the Text property to Process Product Shipment. Set the GridView ID to Productsgrid and bind it from its smart tag to a ObjectDataSource named Productsdatasource. Set the ObjectDataSource call PRODUCTSBLL The GetProducts method for class classes. Because the GridView control is used only to display data, select "(None)" From Update, INSERT, delete label. Click Finish to complete the setup
Figure 3: Calling the Productsbll class GetProducts method to display the data
Figure 4: In Update, INSERT, delete tab select (None)
When the ObjectDataSource setting is complete, Visual studio automatically adds some BoundFields and a checkboxfield. Only keep ProductName, CategoryName, SupplierName, UnitPrice, and discontinued these columns. You can do some more cosmetic improvements. I customized the UnitPrice column to a currency value, sorted the columns again, and modified the HeaderText values for some of the columns. And then in the GridView smart tag, "paging" and "sorting" are enabled. "function. After the above work, the page's declaration code should look similar to the following:
<asp:panel id= "Displayinterface" runat= "Server" > <p> <asp:button id= "processshipment" runat= "Server" T ext= "Process Product Shipment"/> </p> <asp:gridview id= "Productsgrid" runat= "Server" allowpaging= "True" Al lowsorting= "True" autogeneratecolumns= "False" datakeynames= "ProductID" datasourceid= "Productsdatasource" > < columns> <asp:boundfield datafield= "ProductName" headertext= "Product" sortexpression= "ProductName"/> <a
Sp:boundfield datafield= "CategoryName" headertext= "Category" readonly= "True" sortexpression= "CategoryName"/> <asp:boundfield datafield= "SupplierName" headertext= "Supplier" readonly= "True" sortexpression= "SupplierName"/ > <asp:boundfield datafield= "UnitPrice" dataformatstring= "{0:c}" headertext= "Price" htmlencode= "False" SortExp ression= "UnitPrice" > <itemstyle horizontalalign= "right"/> </asp:BoundField> <asp:checkboxfield Da Tafield= "Discontinued" headertext= "DiscontiNued "sortexpression=" discontinued "> <itemstyle horizontalalign=" Center "/> </asp:CheckBoxField>
;/columns> </asp:GridView> <asp:objectdatasource id= "Productsdatasource" runat= "Server" oldvaluesparameterformatstring= "original_{0}" selectmethod= "GetProducts" typename= "ProductsBLL" > </asp:O
Bjectdatasource> </asp:Panel>
We notice that the declaration code for the button and GridView control appears inside the <asp:Panel> tag, because the controls are placed inside the Panel control named Displayinterface, we can add the Panel control's visible property to False to hide these controls. We'll see in the third step that when you click on a button, programmatically change the Visible property of the Panel control to display the add interface.
Take the time to log in to the page in the browser. As shown in Figure 5, you will see a button that appears as Process Product Shipment, with the GridView control listing 10 products at a time.
Figure 5:gridview lists the products and enables sorting and paging functionality
Step Two: Create an Add interface
After creating the presentation interface, we will create the add interface. In this tutorial, our add interface allows users to add 5 products at the same time, and the category and supplier of these 5 products are the same, while names and NIT The price value is different. Under the Panel control with ID displayinterface, drag a Panel control from the Toolbox to the page, set its ID to insertinginterface,visible property to False, and clear its height and Width property values. We will add code in step three to change its Visible property to true.
Next we will create the add interface as shown in Figure 1. The interface could have been created with some HTML technology, but here we'll use a very simple table of 4 columns and 7 rows.
Note: Although you can use toolbox tools in Designer mode to add <table> elements elements, it automatically adds some style property settings that we don't need. So I prefer to add HTML <table> in Source view mode Elements element. When you write a class <table> declare code, I like to switch to designer mode immediately, add Web controls, and set their properties. When I had a good idea, I thought I'd like to use static HTML (static HTML) instead of the table Web control when I want to create rows and columns, because if we use the Table Web control, we have to pass FindControl ("ControlID") Way to access the Web controls that are placed inside. But then again, if you want to create a dynamically changing table (dynamically-sized tables)--for example, the rows and columns of the table are bound to a database or a standard format based on user customization, I still want to use the table Web control for the simple reason that we can programmatically create the table Web control.
Enter the following declaration code in the <asp:Panel> tab of the Panel control with ID insertinginterface:
<table class= "Datawebcontrolstyle" cellspacing= "0" > <tr class= "Batchinsertheaderrow" > <td class= " Batchinsertlabel ">Supplier:</td> <td></td> <td class=" Batchinsertlabel ">category:</ td> <td></td> </tr> <tr class= "Batchinsertrow" > <td class= "Batchinsertlabel" > product:</td> <td></td> <td class= "Batchinsertlabel" >Price:</td> <td></td > </tr> <tr class= "Batchinsertalternatingrow" > <td class= "Batchinsertlabel" >product:</td > <td></td> <td class= "Batchinsertlabel" >Price:</td> <td></td> </tr> &L T;tr class= "Batchinsertrow" > <td class= "Batchinsertlabel" >Product:</td> <td></td> <td class= "Batchinsertlabel" >Price:</td> <td></td> </tr> <tr class= " Batchinsertalternatingrow "> <td class=" Batchinsertlabel ">Product:</td> <td></td> <td class= "Batchinsertlabel" >Price:</td> <td></td> </tr> <tr class= "Batchinsertrow" > <td class= "Batchinsertlabel" >Product:</td> <td></td> <td class= "Batchinsertlabel" >Price:</td> <td></td> </tr> <tr class= "Batchinsertfooterrow
"> <td colspan=" 4 "> </td> </tr> </table>
The <table> declaration code does not contain any Web controls for the time being. We notice that each <tr> element has a clear CSS class setting: The "Top row" of the Dropdownlists control named supplier and category corresponds to the Batchinsertheaderrow ; the "bottom row" of the "ADD products from Shipment" and "Cancel" buttons corresponds to Batchinsertfooterrow; those containing product and unit The line of the TextBox control for Price is alternately used by Batchinsertrow and Batchinsertalternatingrow. I've created the corresponding CSS classes in the Styles.css file, the code is as follows:
/*** Styles for ~/batchdata/batchinsert.aspx tutorial ***/
. Batchinsertlabel
{
font-weight:bold;
Text-align:right
}
. Batchinsertheaderrow TD
{
color:white;
Background-color: #900;
padding:11px
}
. Batchinsertfooterrow TD
{
text-align:center;
padding-top:5px
}
. Batchinsertrow
{
}
. Batchinsertalternatingrow
{
background-color: #fcc;
}
After you enter the code, switch to Design view, which <table> looks like a 4-column 7-row table, as shown in Figure 6:
Figure 6: Adding a table with an interface of 4 columns and 7 rows
Now we add Web controls to the add-in interface. Drag 2 DropDownList from the Toolbox to the corresponding square in the table-one to display the supplier and another to display the category.
Set the ID of the DropDownList used to display supplier as suppliers, and bind it to a ObjectDataSource named Suppliersdatasource. Set the ObjectDataSource call SUPPLIERSBLL The Getsuppliers method for class classes. and select "(None)" In the Update tab and click Finish to complete the Setup wizard.
Figure 7: Setting the Getsuppliers method for ObjectDataSource call SUPPLIERSBLL class classes
Sets the DropDownList to display CompanyName columns, and the values passed are SupplierID columns.
Figure 8: Displaying the CompanyName column, passing the value of the SupplierID column
Set the ID of the 2nd DropDownList to categories, and bind it to a ObjectDataSource named Categoriesdatasource. The ObjectDataSource invokes the GetCategories method of the Categoriesbll class class. Select "(None)" In the Update tab and click Finish to complete the setup. Finally, the DropDownList control is set to display the CategoryName column, passing the value of the CategoryID column.
When you add these 2 DropDownList controls and bind to the corresponding objectdatasources, your screen should look similar to Figure 9:
Figure 9: Header row contains DropDownList controls that display suppliers and categories
We now need to create a TextBox control that collects the name and price information for each product. Drag and drop a TextBox control in the corresponding name and price squares of each line below. Set their IDs to ProductName1, Unitprice1,productname2, UnitPrice2, and so on.
Add a CompareValidator control to each price textboxes, Set its ControlToValidate property to the corresponding control's ID value. Set the Operator property to the Greaterthanequal,valuetocompare property set to "0", The Type property is set to currency. This ensures that the entered price is a valid currency value greater than or equal to 0. The Text property is also set to "*", and the ErrorMessage property is "the prices must be greater than or equal to zero. Also, please omit any currency symbols. ".
Note: We do not include any RequiredFieldValidator controls in the add interface, even if the ProductName of the database table products is not allowed to be null. For example, if the user only wants to enter the name and unit of the product in the first 3 lines Price, and the last 2 act is empty, we just add 3 products to the database. Since ProductName is required, when the name value is entered, we only need to programmatically check whether the user has entered the unit price value for the product. We'll do the check in step fourth.
When the user enters data, but if the input value contains a currency symbol, the CompareValidator control reports invalid data. Add a "$" match before each unit price Textboxe control, prompting the user to ignore the currency symbol when entering data.
Finally, add a ValidationSummary control to the Insertinginterface Panel control and set its ShowMessageBox property to True. The ShowSummary property is false. With these settings, when the user enters an invalid unit price value, an asterisk appears next to the TextBox control, and the ValidationSummary control displays a message box for the client. Displays the appropriate error message.
At this point, your screen looks similar to Figure 10.
Figure 10: The Add interface now contains a TextBox control that displays the names and prices of the product
Next we're going to add "add products from Shipment" and "Cancel" at the bottom row. button. Drag 2 button controls from the toolbox to the bottom of the interface, set their IDs to Addproducts and CancelButton respectively, and set their Text property to "ADD products from Shipment" and "Cancel." In addition, the The CausesValidation property of the CancelButton button is set to False.
Finally, we need to add a label Web control to display status information about these 2 interfaces. For example, when a user successfully adds a batch of products, we want to switch to the display interface and display a confirmation message. Of course, if the user enters the product information with price only and does not provide name information, we need to display a warning message prompting the user ProductName is required. Because we need to display information about these 2 interfaces, place the control above the 2 Panel controls.
Drag a label Web control from the toolbox to the top of the page, set its ID to Statuslabel, clear its Text property, and set its Visible property and EnableViewState property to False. As we've discussed in previous tutorials, if you set the EnableViewState property to False, we can programmatically change the value of the Label control's property and return to its default state when the page returns. When some user action occurs, the The status information is displayed, and when the page is returned, the status information disappears again. The CssClass attribute of the last set Statuslabel is "Warning", which is the CSS class name we defined in the Styles.css file.
The following illustration shows the appearance of adding and setting a Label control
Figure 11: Placing the Label control with ID Statuslabel above the Panel control
Step three: Switch between the presentation interface and the Add interface
Here we have finished showing and adding interfaces, but we still have 2 tasks to do:
1. Switch between the presentation interface and the Add interface
2. Add the product to the database
Currently, the presentation interface is visible and the add interface is hidden. This is because the Visible property of the Displayinterface Panel control is true (the default), and Insertinginterface The Panel control's Visible property is false.
When you click the Process Product Shipment button, we switch from the display interface to the add interface. To do this, create the Click event handler for the button, which contains the following code:
protected void Processshipment_click (object sender, EventArgs e)
{
displayinterface.visible = false;
Insertinginterface.visible = true;
}
The code simply hides the Displayinterface panel and displays the Insertinginterface panel.
Next, we add "add products to Shipment" and "Cancel" in the interface. button to create an event handler. When any button is clicked, we need to switch to the display interface. Create the Click event handler for these 2 buttons to invoke the Returntodisplayinterface method-we are about to create the method.
In addition to hiding the Insertinginterface panel and displaying the Displayinterface panel, the method also needs to return the Web control to its pre-edit state (pre-editing). That is, set the property SelectedIndex of the DropDownList control to 0 to clear the Text property of the TextBox control.
Note: Think about what happens if we don't return the controls to the pre-edit state before we return to the presentation interface. For example, the user clicks on the "Process products from Shipment" button, and then enter the product information, and then click the "Add Products from Shipment" button, which will add the product and return to the display page. If the user wants to add another batch of products, it will switch to the add interface once the Process product Shipment button is clicked, but the value of the DropDownList control and the value of the TextBox control remain the previous value.
protected void Addproducts_click (object sender, EventArgs e) {//Todo:save the Prod
Ucts//Revert to the Display interface Returntodisplayinterface (); } protected void Cancelbutton_click (object sender, EventArgs e) {//Revert to the display interface Returntodisplayint
Erface ();
const int firstcontrolid = 1;
const int lastcontrolid = 5; private void Returntodisplayinterface () {//Reset the control values in the inserting interface Suppliers.selectedindex
= 0;
Categories.selectedindex = 0; for (int i = Firstcontrolid i <= lastcontrolid; i++) {(TextBox) Insertinginterface.findcontrol ("ProductName" + i.to String ()). Text = string.
Empty; ((TextBox) Insertinginterface.findcontrol ("UnitPrice" + i.tostring ()). Text = string.
Empty;
} displayinterface.visible = true;
Insertinginterface.visible = false; }
The above 2 Click event handlers simply invoke the Returntodisplayinterface method, but we will complete the click event of the "Add products from Shipment" in step fourth, adding code to save the product.
The Returntodisplayinterface method initially returns the DropDownList control of suppliers and categories to its first item The constants firstcontrolid and Lastcontrolid are used to set the start and end index values of the Textboxe control that indicate the product name and unit price in the Add interface, respectively. Set the Text property of these controls to an empty string in a for loop. Finally reset the Visible property of the panels control to show the display interface and hide the add interface.
Take the time to test the page in the browser, and when you first log in you will see the picture shown in Figure 5, the "Process Product Shipment" button, and the page will return and switch to the add interface shown in Figure 12, regardless of the point "add products from Shipment "or" Cancel "button will return to the display interface.
Note: When browsing the Add interface, test the validation controls that correspond to the unit price textbox. If you enter a currency value or a price smaller than 0, a client warning message pops up when you click the "ADD products from Shipment" button.
Figure 12: After clicking on the process Product Shipment button, you will switch to the add interface.
Fourth Step: Add the Product
The only thing left to do is add the product to the database in the Click event handler of the "Add products from Shipment" button. To do so, we can create a productsdatatable and add a productsrow for the product to be inserted Instance instance. Once the productsrows is added, we call and pass productsdatatable to the Updatewithtransaction method of the Productsbll class class. Remember we were in the 61st chapter The Updatewithtransaction method created in the encapsulation of database modifications in a transaction, This method passes productsdatatable to the Updatewithtransaction method of ProductsTableAdapter. A ado.net transaction is initiated, Tableadatper is sent to the database for each productsrow added An insert command. If all additions are correct, commit the transaction or roll back the transaction.
When encoding the Click processor of the "Add products from Shipment" button, you should perform some error checking because we do not use the Requiredfieldvalidators control in the add interface. A user may have entered the price of the product and ignored its name. Since the name of the product is required, if this happens, we need to alert the user and interrupt the inserts operation. The complete code is as follows:
protected void Addproducts_click (object sender, EventArgs e) {//Make sure this UnitPrice comparevalidators Valid data ... if (!
Page.IsValid) return;
ADD new productsrows to a productsdatatable ...
Northwind.productsdatatable products = new northwind.productsdatatable (); for (int i = Firstcontrolid i <= lastcontrolid, i++) {//Read in the ' values for the ' Product name and unit Price St Ring ProductName = ((TextBox) Insertinginterface.findcontrol ("ProductName" + i.tostring ()).
Text.trim (); String UnitPrice = ((TextBox) Insertinginterface.findcontrol ("UnitPrice" + i.tostring ()).
Text.trim (); Ensure that if UnitPrice has a value, so does productName if (unitprice.length > 0 && productname.length = = 0) {//Display a warning and exit this event handler Statuslabel.text = ' If you provide a unit price you must also
"+" include the name of the product. ";
Statuslabel.visible = true;
Return }//Only add the product if a product NAMe value is provided if (Productname.length > 0) {//ADD a new productsrow to the productsdatatable northwind.pr Oductsrow newproduct = products.
Newproductsrow ();
Assign the values from the Web page newproduct.productname = ProductName;
Newproduct.supplierid = Convert.ToInt32 (Suppliers.selectedvalue);
Newproduct.categoryid = Convert.ToInt32 (Categories.selectedvalue);
if (Unitprice.length > 0) newproduct.unitprice = convert.todecimal (UnitPrice);
ADD any "default" values newproduct.discontinued = false;
Newproduct.unitsonorder = 0; Products.
Addproductsrow (newproduct); }//If we are here, check if there were any of the products added if. Count > 0) {//ADD the new products to the database using a transaction PRODUCTSBLL PRODUCTSAPI = new PRODUCTSBLL ()
;
Productsapi.updatewithtransaction (products);
Rebind the data to the "grid so" PRODUCST just added are displayed (); Display a confirmation (doN ' t use the Warning CSS class, though) Statuslabel.cssclass = string.
Empty; Statuslabel.text = string. Format ("{0} products from supplier {1} have been added and filed under" + "category {2}."
Count, Suppliers.SelectedItem.Text, Categories.SelectedItem.Text);
Statuslabel.visible = true;
Revert to the Display interface Returntodisplayinterface ();
else {//No products supplied! Statuslabel.text = "No products were added."
Please enter the product "+" names and unit prices in the textboxes. ";
Statuslabel.visible = true;
}
}
The event handler at the start checks to see if the value returned by the Page.IsValid property is true. If you return false, it means that at least one of the comparevalidators controls has found invalid data. At this point, we either stop adding the product or assign a value to the Productsrow's UnitPrice property by the user's typed unit price value. To throw an abnormally end.
Next, create a new Productsdatatable instance instance (that is, products) and traverse the TextBox control for name and unit price in a for loop. and reads its Text property into local variables ProductName and UnitPrice. If the user enters the unit price value of the product without entering the product's name value, the Statuslabel control displays the message "If you provide a Unit price You must also include the name of the product and exits the event handler.
If the user enters the name of the product, a new productsrow is created using the Productsdatatable Newproductsrow method Instance instance. For the ProductName property of the instance, the corresponding TextBox is used to assign the value, and for the SupplierID and CategoryID properties, is assigned the value of the SelectedValue property of the corresponding DropDownList control at the top of the interface, and if the user enters the price of the product, the UnitPrice property of the Productsrow instance instance is assigned. If the user does not enter the price then empty, the value of UnitPrice when adding data to the database is a null value. Finally, the discontinued and UnitsOnOrder properties are assigned the hard-coded value "false" and "0" respectively.
When you have finished assigning related properties to the Productsrow instance instance, add them to the productsdatatable.
After completing the For loop we will check to see if the product has been added. After all, the user may not enter any information to click on the "Add products from Shipment" button. If there is at least one product in the productsdatatable, the Updatewithtransaction method of the Productsbll class is invoked, Next, the GridView control named Productsgrid is bound again, and the most recently added product appears in the display interface. Statuslabel will be updated to display a confirmation message, and then call Returntodisplayinterface to hide the add interface and show the display interface.
If no product is added, the add interface will still be hidden, but will display a message "No products were added." Please enter the product names with the prices in the textboxes.
Figure 13 shows that the user entered the unit price value without entering the corresponding product name, and Figure 14 shows the display interface after 3 products were successfully added. Figure 15 shows the interface of 2 products (and 1 on the previous page).
Figure 13: The name of the product is also required when the unit price value is entered
Figure 14:3 Veggies Products provided by Vendor Mayumi are added
Figure 15: The newly added product can be found on the last page of the GridView
Note: The batch add logic used in this article encapsulates inserts in a transaction. To be confirmed, we can intentionally import a database-level error (database-level error). For example, for the CategoryID attribute of the Productsrow instance instance, we do not assign the value of the DropDownList value of the categories selected control as above, but instead use the i * 5 assign a value to it. Here I refer to the circular index value (loop indexer) between 1 and 5. Therefore, when 2 or more products are added, the CategoryID value (5) of the first product is valid, and the CategoryID value of the following product is invalid. Because the value does not match the CategoryID value in the table categories (because the 2nd product has a CategoryID value of 10; the 3rd is 15, and so on). The consequence was that the first product was successfully insert and the subsequent operation failed, Because the foreign key constraint is violated. Because our batch addition is atomic, the first insert is rolled back and the database is returned to the state before the start batch is added
Conclusion:
In this and the first 2 chapters, we create an interface for batch updates, batch deletions, and batch additions to the data. All of these interfaces use transactions. The transaction, which we added in the data access layer, in the 61st chapter, "Encapsulation of database modifications in a transaction", is layer. In some cases, these batch data processing interfaces can greatly enhance the efficiency of end users.
The review of processing batch data ends here. In the next series, we'll look at a variety of more advanced scenarios in the data access layer in layer. This includes the use of stored procedures in the TableAdapter method, the setting of connection and command-level (Connection-and command-level) in the DAL, and the encryption of connection strings.
I wish you a happy programming!
Author Introduction
The author of this series of tutorials, Scott Mitchell, has six asp/asp. NET book, is the founder of 4GuysFromRolla.com, has been applying Microsoft Web technology since 1998. You can click to see all Tutorials "[translation]scott Mitchell asp.net 2.0 data tutorial," I hope to learn asp.net help.