Brief introduction
The GridView and DetailsView controls simplify the production of data-editing interfaces by binding columns and checkbox columns, rendering read-only, editing, and adding interfaces, and we can get these interfaces without adding element tags or writing any additional code. However, the interface between the bound columns and the checkbox columns lacks the customization features that are often used in the actual application. In order to customize the GridView and DetailsView editing and new interface, you need to replace the original column with a template column (TemplateField).
In the previous tutorial we discussed how to add validation controls to customize the data editing interface, and this tutorial demonstrates how to use Web controls to customize the actual data collection by replacing the default TextBox and CheckBox controls in bound columns and checkbox columns with other input controls. To do this, we will create an editable GridView and allow editing of the name, category, provider, and obsolete status of the product to be updated. And when editing a row, the category category and provider supplier we will use DropDownList to display it for the user to choose from. In addition, the default CheckBox control in the checkbox column is replaced with the RadioButtonList control, and 2 radio options are available: Active and discontinued. As shown in Figure 1:
Figure 1: Using the DropDownList and RadioButton controls in the editing interface of the GridView
UpdateProduct method of heavy load
In this tutorial, we will create an editable GridView and allow editing of the name, category, provider, and obsolete status of the product to be updated. Therefore, we will overload the UpdateProduct method and accept 5 Input parameters: 4 Product parameter values plus a product ID. As before, this overload will:
1. Obtain product information from the database according to the specified ProductID;
2. Update Productname,categoryid,supplierid and Discontinued fields;
3. Issue an update request to the data Access layer DAL through the TableAdapter update () method.
For simplicity, this overloaded method omits an important business logic-checking and ensuring that a product that will be marked as discontinued is not the only product provided by its provider. You can add it, or do it better, and write this logic into a separate method.
The following code is the new UpdateProduct overload method that we add in the PRODUCTSBLL class:
[System.ComponentModel.DataObjectMethodAttribute ( System.ComponentModel.DataObjectMethodType.Update, false)] public bool UpdateProduct (string productName, int?) CategoryID, int? SupplierID, BOOL discontinued, int ProductID) {northwind.productsdatatable products = Adapter.getproductbyproductid (pr
Oductid); if (products.
Count = = 0)//No matching record found and return false to false;
Northwind.productsrow product = Products[0]; Product.
ProductName = ProductName; if (SupplierID = = null) product.
Setsupplieridnull (); else product.
SupplierID = Supplierid.value; if (CategoryID = = null) product.
Setcategoryidnull (); else product.
CategoryID = Categoryid.value; Product.
Discontinued = discontinued;
Update the product record int rowsaffected = adapter.update (product);
Return true if precisely one row is updated, otherwise false return rowsaffected = = 1; }
Ii. manual processing of an editable GridView
After writing the updateproduct overloaded method, the next thing to do is to create an editable GridView: Open the Customizedui.aspx page in the EditInsertDelete folder in the Designer window and add a GridView control to it; Then create a new ObjectDataSource with the GridView Smart Tag, configure this ObjectDataSource to use the Productbll class GetProducts () method to get product information, and have them use the UpdateProduct overload method created above to update the product. On the new and deleted labels, select (None) from the Drop-down list.
Figure 2: Configuring ObjectDataSource using the UpdateProduct overload method created above
As in the "Data modification" tutorial, Visual Studio creates ObjectDataSource element tags and specifies that the OldValuesParameterFormatString property is original_{0}. Because the method we write does not support the original ProductID value passed in, the business logic layer does not take effect. So, as in the previous tutorial, we need to remove these attributes from the element tags, or set them.
The modified ObjectDataSource element tag will look like the following:
<asp:objectdatasource id= "ObjectDataSource1" runat= "selectmethod=" getproducts "Typename="
PRODUCTSBLL "
updatemethod=" updateproduct ">
<UpdateParameters>
<asp:parameter name=" ProductName "type=" String "/> <asp:parameter name=" CategoryID "type=
" Int32 "/>
<asp:parameter Name= "SupplierID" type= "Int32"/> <asp:parameter name= "discontinued"
type= "Boolean"/>
<asp: Parameter name= "ProductID" type= "Int32"/>
</UpdateParameters>
</asp:ObjectDataSource>
Note that oldvaluesparameterformatstring has been removed from the above code and provides a parameter for each entry parameter of the UpdateProduct overloaded method in the UpdateParameters collection.
Although ObjectDataSource is configured to update only part of the information in the product, the GridView displays all product information. We need to adjust the GridView according to the following points:
1. Include only the ProductName, SupplierName, CategoryName fields, and the checkbox columns of the Discontinued field.
2. CategoryName and SupplierName fields appear in front of discontinued (left)
3. Change the title of CategoryName and SupplierName to "Category" and "Supplier" respectively
4. Enable edit mode (select the Enable Edit checkbox in the GridView smart tag)
After these adjustments, the page in the designer is shown in Figure 3:
Figure 3: Removing useless fields from the GridView
The element tags of the GridView are also shown as follows:
<asp:gridview id= "GridView1" runat= "Server" autogeneratecolumns= "False"
datakeynames= "ProductID" Datasourceid= "ObjectDataSource1" >
<Columns>
<asp:boundfield datafield= "ProductName"
headertext= "ProductName" sortexpression= "ProductName"/> <asp:boundfield datafield=
"CategoryName" headertext= "Category"
readonly= "True"
sortexpression= "CategoryName"/>
<asp:boundfield Datafield= "SupplierName" headertext= "Supplier"
readonly= "True"
sortexpression= "SupplierName"/>
<asp:checkboxfield datafield= "discontinued"
headertext= "Discontinued" sortexpression= "discontinued"/>
</Columns>
</asp:gridview>
Then the GridView read-only interface was changed. When viewing data, each product acts as a row in the GridView and displays the Name,category,supplier and discontinued status of the product.
Figure 4:gridview Adjusted read-only interface
Using DropDownList to display category and supplier in the editing interface
We note that the Productsrow object contains the Categoryid,categoryname,supplierid and SupplierName properties of the product, but the products database only holds the foreign keys. The corresponding name is saved in the categories and suppliers tables. The CategoryID and SupplierID in the Productsrow object can be read and written, while the CategoryName and SupplierName properties are marked as read-only.
Because of the read-only state of CategoryName and SupplierName, the readonly properties of the corresponding bound columns are also set to true to prevent their values from being modified when a row is edited. Although you can also turn these bound columns into a textbox in the editing state by setting the ReadOnly property to False, the system throws an exception when the user tries to update the product information. CategoryName and SupplierName parameters are not accepted in the upateproduct overload. In fact, we do not want to write this overload method for the following reasons:
1. The Products table does not have SupplierName and CategoryName fields, but corresponds to the foreign key SupplierID and CategoryID. Therefore, we want to pass the foreign key ID in the Update method instead of looking for the value in the Foreign key table.
2. It is also unreasonable to ask the user to type the name of supplier or category, which requires the user to know the legal category and supplier, and the spelling is correct.
We intend to display the category and provider names separately in the read-only mode supplier and category columns, while editing displays the available options through the Drop-down list. In this way, users can quickly view the effective category and supplier and can be easily intuitive to choose from.
To do this, you need to convert the binding columns for SupplierName and CategoryName to template columns, and to display SupplierName and CategoryName in the ItemTemplate template. The eidtitemtemplate template, however, uses the DropDownList control to list valid cagegory and supplier.
Add categories and Suppliers DropDownList controls
We first convert the SupplierName and CategoryName bound columns to template columns: Click the ' Edit Columns ' link in the GridView smart tag, select the lower-left BoundField, and click the "Convert this field to TemplateField" link, The conversion process creates a template column, including ItemTemplate and EditItemTemplate, and the final element tag is roughly as follows:
<asp:templatefield headertext= "Category" sortexpression= "CategoryName" >
<EditItemTemplate>
<asp:label id= "Label1" runat= "server" text=
' <%# Eval ("CategoryName")%> ' ></asp:Label>
</EditItemTemplate>
<ItemTemplate>
<asp:label id= "Label1" runat= "server"
text= ' <%# Bind ("CategoryName")%> ' ></asp:Label>
</ItemTemplate>
</asp:TemplateField>
Because bound columns are marked as read-only, ItemTemplate and EditItemTemplate display related data (such as the CategoryName above) with the Text property of the label control. Therefore, you need to modify the EditItemTemplate template and replace the original label control with the DropDownList control.
As the previous tutorial says, you can edit the template in the designer or modify the template's element tags directly. To modify in the designer, you can click the Edit Template link through the GridView Smart tag and select the EditItemTemplate template for the category field. Remove the label control with the DropDownList control and set the DropDownList ID property to categories.
Figure 5: Delete the textbox in the EditItemTemplate template and add a DropDownList
Next we need to bind category for DropDownList. Click the "Select Data Source" link from the smart tag and choose to create a new ObjectDataSource named Categoriesdatasource.
Figure 6: Creating a new ObjectDataSource control Categoriesdatasource
To enable ObjectDataSource to display all the category, we bind it to the GetCategories () method of the Categoriesbll class.
Figure 7: Binding the ObjectDataSource control with the GATEGORIESBLL getcategories () method
Finally, configure DropDownList to use the CategoryName field as the Display field and CategoryID as the Value field.
Figure 8: Using CategoryName as the Display field and CategoryID as the Value field
The CategoryName template item will have a DropDownList control and a ObjectDataSource after the change, and the element tags are roughly as follows:
<asp:templatefield headertext= "Category" sortexpression= "CategoryName" >
<EditItemTemplate>
<asp:dropdownlist id= "Categories" runat= "datasourceid=" Categoriesdatasource "datatextfield="
CategoryName "datavaluefield=" CategoryID ">
</asp:DropDownList>
<asp:objectdatasource id=" Categoriesdatasource "runat=" Server "
oldvaluesparameterformatstring=" original_{0} "
selectmethod=" GetCategories "typename=" CATEGORIESBLL ">
</asp:ObjectDataSource>
</EditItemTemplate>
<ItemTemplate>
<asp:label id= "Label1" runat= "server"
text= ' <%# Bind ("CategoryName")% > ' ></asp:Label>
</ItemTemplate>
</asp:TemplateField>
Note: The DropDownList in the EditItemTemplate template must enable view state. Below we will add data-binding syntax and data-binding commands such as eval () and bind () in the DropDownList element tag, which requires view state to be enabled or will not be displayed.
Repeat the steps above to add the DropDownList control to the EditItemTemplate template in the SupplierName template column and name suppliers. This includes adding DropDownList controls and creating another ObjectDataSource, noting that the new ObjectDataSource calls the Getsuppliers () method of the Suppliersbll class. In addition, the display field of the Configuration Suppliers drop-down box is companyname,value field SupplierID.
After the two Drop-down boxes are added, view the page in the browser and click the Edit button for the "Chef Anton ' Cajun seasoning" product. As shown in Figure 9, the category and supplier columns of the product become Drop-down boxes and contain the corresponding category and supplier option sets. However, you will find that the default selection in the dropdown box is the first item in the dropdown box (category is Beverages,supplier is exotic liquids), in fact they should be condiment and New Orleans Cajun Delights.
Figure 9: The Drop-down list defaults to the first item selected
In addition, if you click on the update, you will find that the CategoryID and SupplierID of the product have become null. These are because the drop-down boxes in the EditItemTemplate template are not bound according to the actual data in the database.
Binding CategoryID and SupplierID data for DropDownList
For the category and supplier Drop-down lists in the product edit state to select the actual data and make it possible to update the database based on the UpdateProduct method that the user chooses to invoke BLL. We need to bind the SelectedValue of the two dropdown boxes to CategoryID and SupplierID respectively. For example, for the Categories Drop-down box, we add selectedvalue= ' <%# Bind ("CategoryID")%> to the element tag directly.
Another approach is to set the data binding for the Drop-down box in the Edit template by clicking the "Edit DataBinding" link in the designer, using the smart tag of the Drop-down box. Next, specify SelectedValue binding to the CategoryID field in dual mode (see Figure 10). Repeat one of the above methods to bind the SupplierID data for the Suppliers Drop-down box.
Figure 10: SelectedValue Attribute Binding CategoryID value to DropDownList
Once you have completed the data binding of the two Drop-down box SelectedValue properties, the category and supplier of the product will default to the actual option selected. When you click the Update button, the selection in the dropdown box is also passed to the UpdateProduct method exactly. Figure 11 shows the code to increase the data binding; Note how to select items in the Drop-down list: Chef Anton ' s Cajun seasoning product categories and providers selected the correct condiment and New Orleans Cajun options respectively.
Figure 11: After the modification Categroy and supplier correctly selected the actual data for the product
Handling Null values
The CategoryID and SupplierID columns in the product table are allowed to be null, while the Drop-down list in the edit template does not have null. So there are two kinds of problems:
1. Users cannot set a product Non-empty category or supplier to NULL in the current interface
2. If the CategoryID or SupplierID of the product is null, the program throws an exception when the Edit button is clicked. This is because when CategoryID (or SupplierID) in the bind () expression returns a null value, SelectedValue cannot find the null list item and thus throws an exception.
To support null values for CategoryID and SupplierID, you need to add a null value option for two DropDownList. In the Master/detail filtering with a DropDownList tutorial, we demonstrated adding list items for the DropDownList of the binding. The method is to set the DropDownList AppendDataBoundItems property to True and manually add a list item with a value of-1. In asp.net data-binding logic, an empty string is automatically converted to a Null,null value, or it can be converted to an empty string. Therefore, in this tutorial we will add a list item with an empty string value.
Set the AppendDataBoundItems property of these two DropDownList to true first. Next, add a null list item with the <asp:ListItem> element, and the element tags are roughly as follows:
<asp:dropdownlist id= "Categories" runat= "datasourceid=" Categoriesdatasource "datatextfield=" CategoryName "datavaluefield=" CategoryID "Selectedvalue= ' <%# Bind (" CategoryID ")%> ' appenddatabounditems= ' True ">
<asp:listitem value=" "> (None) </asp:ListItem>
</asp:DropDownList>
We chose to use "(None)" As the text display for the list item, and you can also empty strings or other characters.
Note: The "Master/detail filtering with a DropDownList" tutorial demonstrates how to add DropDownList list items- In the designer, click the Item property in the DropDownList Properties window (F4) (The ListItem collection Editor will be displayed). This time we'll add a null list item directly in the element tag. If you use the collection editor, the element tag you create will ignore the value of the null character, such as:<asp:listitem> (None) </asp:ListItem>. It doesn't seem to be a big deal, but DropDownList uses text instead for items with no value, so when "None" is selected, "None" is given CategoryID and the system generates an exception. By explicitly setting value= "", select this item, CategoryID is updated to a null value.
Repeat the previous steps to set the Supplier Drop-down control.
With this additional list item, the editing interface can set null values for the CategoryID and SupplierID of product, as shown in Figure 12
Figure 12: Specify a null value for the category or supplier of the product by selecting (None).
Four, use RadioButton to express discontinued state
The Discontinued field of product is rendered as a CheckBox column, and the read-only mode is disabled, and only in edit mode. Depending on the needs of the package, we can customize it using the template column. In this tutorial, we will use the template column with the RadioButtonList control instead of the original checkbox column with two options-"Active" and "discontinued"-to let the user select the discontinued value of the product.
The Discontinued CheckBox column is converted to a template column, and the ItemTemplate and EditItemTemplate two templates are used. They use a checkbox and bind the Discontinued field through the Checked property, except that the Enabled property of the checkbox in the ItemTemplate template is false.
Replace the checkbox controls in the original ItemTemplate and EditItemTemplate templates with the RadioButtonList control and set their ID properties to Discontinuedchoice. Then, set the two radio button entries for radiobuttonlists, one as "Active", the value "False" and the other "discontinued", and the value is "True." These operations can add <asp:ListItem> elements directly to element tags, or they can be handled by ListItem the collection editor in the designer. Figure 13 shows the ListItem collection editor after the two radio buttons are specified.
Figure 13: Adding active and discontinued options for RadioButtonList
Setting the Enabled property to False because the RadioButtonList in the normal item template ItemTemplate should not be an edit state. The Enabled property of the RadioButtonList in the EditItemTemplate template for the edit state should be set to true. In this way, the radio button in the non-edit row is displayed as read-only, while the edit state allows the user to make a selection.
You still need to bind the RadioButtonList control's SelectedValue property with the discontinued data of product in the database. As before the tutorial in this section, you can add binding syntax directly or through the ' Edit DataBinding ' link in the RadioButtonList smart tag.
After adding the two RadioButtonList and making the appropriate configuration, the discontinued template column element tags are roughly as follows:
<asp:templatefield headertext= "discontinued" sortexpression= "discontinued" >
<ItemTemplate>
<asp:radiobuttonlist id= "Discontinuedchoice" runat= "Server" enabled= "False" selectedvalue= ' <%# ' Bind (" Discontinued ")%> ' >
<asp:listitem value= ' False ' >Active</asp:ListItem>
<asp:listitem Value= "True" >Discontinued</asp:ListItem>
</asp:RadioButtonList>
</ItemTemplate>
<EditItemTemplate>
<asp:radiobuttonlist id= "Discontinuedchoice" runat= "Server" Selectedvalue= ' <%# Bind ("discontinued")%> ' >
<asp:listitem value= ' False ' >Active</asp:ListItem>
<asp:listitem value= "True" >Discontinued</asp:ListItem>
</asp:RadioButtonList>
</ Edititemtemplate>
</asp:TemplateField>
At this point, the Discontinued column transitions from the checkbox column to a pair of radio buttons (see Figure 14). When you enter the product editing interface, the Discontinued radio button is selected, and when you click on the update, the new status is updated to the database.
Figure 14: The checkbox representing discontinued is replaced with a pair of radio buttons
Note: Because the Discontinued field in the product database does not allow null values, NULL is not considered in the display interface. However, if discontinued allows nulls, add the 3rd single option to the list, with the value set to an empty string (value= ""), just like the category and supplier Drop-down boxes.
Summary
Because bound columns and checkbox columns automatically render read-only, edited, and new interfaces, there is a lack of customization capabilities. However, we often need to customize the new and editing interfaces, such as adding validation controls (the previous tutorial) or customizing the dataset's user interface (tutorial in this section). The custom interface with the template column TemplateField is summarized in the following steps:
1. Add template columns or convert existing bound columns and checkbox columns to template columns.
2. Add controls to the interface as needed
3. Data binding to related fields for newly added controls.
The customization process can also use custom controls, compiled server controls, and user controls in the template column, in addition to the built-in ASP.net controls.
I wish you a happy programming!
Author Introduction
Scott Mitchell, with six asp/asp. NET book, is the founder of 4GuysFromRolla.com, has been applying Microsoft Web technology since 1998. Scott is an independent technical consultant, trainer, writer, recently completed a new book to be published by Sams Press, "proficient in asp.net 2.0 within 24 hours" (English). His contact email is mitchell@4guysfromrolla.com, or he can contact him through his blog http://scottonwriting.net/.