Programming Microsoft Web Forms (Pro Developer)
The GridView Control
Developers of ASP.NET 1.x were initially thrilled because ASP.NET rescued them from the tedium of manually reading through result sets and building tables to display tabular data. As time passed, however, the limitations of the DataGrid control became obvious. Although it was possible to do many things with the DataGrid control, it was not easy to do many things well. To maintain backward compatibility, the DataGrid control is still available. However, there is no reason I can think of for using it for new Web Forms development. Why? Because ASP.NET 2.0 introduces the new GridView control.
The GridView control replaces the DataGrid control. The GridView control offers all of the features of the DataGrid control, and it adds several features that improve the ability to display and edit data without adding any code.
Let's drop a GridView control onto the Default.aspx form, created when the DataBinding project was created. The GridView Tasks menu appears next to the GridView control. This menu allows you to complete most of the tasks required to configure the GridView control. From top to bottom, we will step through those menu items.
Clicking the Auto Format menu option opens the Auto Format dialog box. You can scroll through and preview the possible schemes (a fairly large number). I like the Slate scheme, shown in Figure 5-14.
The next option on the GridView Tasks menu is Choose Data Source. Select the data source just added (named SqlDataSource1 by default), and the GridView Tasks menu expands a bit, as shown in Figure 5-15.
The next two menu options allow you to configure the data source, stepping through the same wizard that you used to create the data source, and refresh the schema, useful when data types or the number of columns returned change. The next menu option that I selected is Edit Columns. I selected columns to appear in SqlDataSource, but at least one of those fields (BlogEntryID) is not something that you generally want to show, although having the columns available in the returned data is useful. BlogEntryID is not a meaningful column for the end user, but the developer might use it when, for instance, creating a hyperlink column. Often hyperlinks need to identify a row in the database, and BlogEntryID is a good candidate for that.
When you click Edit Columns, the resulting dialog box displays a list of the currently selected fields, with a variety of ways to add and remove them from the display. Click one of the fields (for instance, BlogEntryID), and the dialog box looks like Figure 5-16.
Look at the properties of the field currently selected (in this case, BlogEntryID). Presuming you follow best practices for naming database columns (no spaces, no special characters), one property you will often modify is the HeaderText property. In this example, "Blog #" might be a better column name than "BlogEntryID" if we want to keep this column in the display. Another property that might be useful is the NullDisplayText property. For instance, if I had included the DateModified column for display in the GridView control, setting NullDisplayText to "Not Modified" could be useful.
Here's something interesting to consider when using the GridView control. Note that the ReadOnly property is generally set based on the column constraints. Because BlogEntryID is an IDENTITY column, and also the primary key for the BlogEntry table, it is reasonable that the field be set to ReadOnly, and it is. The DataField property will be set to the correct column when the GridView control is associated with the data source. A useful related property is the DataFormatString property. For an integer value such as BlogEntryID, the default formatting is generally reasonable; however, a common field type that requires special formatting is the date field type. The default formatting for a DateTime column is (in the U.S.) MM/dd/yyyy hh:mm:ss. This might be appropriate, or it might not be. For this example, mostly to show the available formatting flexibility, I set the DataFormatString property for the DateEntered column to "{0:ddd, MM/dd/yyyy}," which means that the first value passed in (in this case, the single field DateEntered) should be formatted showing the three-character day of the week ("ddd"), followed by a comma (the literal "," after "ddd"), followed by "MM/dd/yyyy" (for two-digit month, a slash, two-digit day, a slash, and four-digit year). A large number of character strings are possible for the DataFormatString property. A search on MSDN for "Formatting Overview" should get you to a page that contains links to all sorts of details on the DataFormatString property.
On the GridView Tasks menu shown in Figure 5-15, the next item is Add New Column. This option is a little redundant, because the previous menu option, Edit Columns, also allows for the addition of a column. The next five menu items are check boxes that specify how the GridView control will allow users to control the page. The check boxes are:
-
Enable Paging Shows only a page of data at a time, allowing the user to get to the next and previous page (if next and previous pages are available).
-
Enable Sorting Makes the heading text a hyperlink that allows the user to sort the column. Click the column once, and it is sorted in ascending order; click it again, and it is sorted in descending order.
-
Enable Editing Adds a column with a hyperlink that, when clicked, allows the user to edit the information in the GridView control in place. This sounds more useful than it often really is, because to control the look of the row while editing, you have to do so much work that you might just want to do the editing in one of the numerous other ways that ASP.NET offers. I will explain more about this later.
-
Enable Deleting Adds a column with a hyperlink that, when clicked, allows the user to delete a row.
-
Enable Selection Adds a column with a hyperlink that, when clicked, allows the user to select the row. What happens when the row is selected is up to the developer.
For now, leave all of these check boxes cleared. We will discuss each of these options shortly.
Edit Template Mode
The final menu option on the GridView Tasks menu is Edit Templates. When you click this option, the display changes quite a bit, as shown in Figure 5-17.
One of the maddening aspects of using the DataGrid control in ASP.NET 1.x was the need to do special processing to display an appropriate message when no data was present. Figure 5-17 shows one of the two templates that can be edited, EmptyDataTemplate, which is displayed when no data is present. In this case, I simply typed "No Blog Entries to Display" into the template, but you can drag and drop any control into the template, and you can enter any HTML directly into the template by using Source view if you prefer.
The other template that can be edited is PagerTemplate, as shown in Figure 5-18.
The PagerTemplate template allows you to control the look and feel of the pager in grid views that allow paging. I left this template blank. (Paging will also be discussed in the next section.) To exit Template Editing Mode, click End Template Editing on the smart tag menu.
Before experimenting with any additional properties, it might be useful to see the GridView control in action. On the Debug menu, choose Start Debugging. If this is the first time you have run this Web site, a message asks whether you want to create a Web.config file to be modified to allow debugging. You should leave the default selected (which will modify the Web.config file) and click OK. The resulting page should look like the screen shown in Figure 5-19.
One thing to notice about the page shown in Figure 5-19 is that the individual entries are rather long. With the screen resolution used in Figure 5-19, less than seven complete entries are visible. In a real application, there might be several hundred entries. When the number of rows gets that high, it is unreasonable to send all rows from the server to the browser each time the page is requested. In addition to the fact that the user might be using a slow connection, finding particular data among so many entries is difficult.
Paging
The solution is to use the GridView control's automatic paging. The GridView control can be configured to show a certain number of rows on each of multiple pages. The automatic paging support offered by the GridView control might be all you will ever need when it comes to paging a large result set.
Close the browser and go back to the GridView Tasks menu (by clicking the smart tag arrow on the right side of the control), where you can select the check box marked Enable Paging. If you run the application again, you will see no difference. The reason for this is the PageSize property of the GridView control. Figure 5-20 shows the Properties dialog box for the GridView control.
The PageSize property defaults to 10. If all rows in a GridView control are a single line in length, using 10 as a PageSize value is entirely reasonable. However, in this example, some of the entries are four rows long (and a real blog site might have even longer entries), so paging based on 10 rows is not quite enough. Changing the PageSize property to 4 is a reasonable choice here. Figure 5-21 shows Default.aspx with paging enabled. Note the links at the bottom right, indicating that the entries are split among two pages.
When you click 2 at the bottom of the page, the page looks like Figure 5-22.
Sorting
Another useful feature of the GridView control is the ability to sort the grid view. Very often, the row you are looking for can be found by sorting the rows in one order or another. To enable sorting, all you have to do is select the Enable Sorting check box on the GridView Tasks menu. Enabling sorting on the grid view in Default.aspx in the DateBinding Web site results in the screen shown in Figure 5-23. In this figure, I clicked Subject once to sort the entries in ascending order.
Editing
The next thing to try in the grid view is editing. Select the Enable Editing check box, as shown in Figure 5-24.
An additional column appears with an Edit hyperlink. When the page is run and the Edit link is clicked on one of the rows in the GridView control, the screen looks like Figure 5-25.
The first thing you should notice is that the Edit link in the row you are editing has been replaced with Update and Cancel links. When the user has made changes, the Update link saves the changes, and the Cancel link ignores the changes. Also notice that the Blog # column is not editable; that column was marked as read-only. In a real Web application, fields such as DateEntered and EnteredBy might also be read-only.
You will also notice that the editing view is not very good. The text boxes for the Subject and Message fields are not appropriately sized. They should both be multiline text boxes. Finally, when the GridView control is placed in edit mode, the line is formatted so that the GridView control is wider than the screen, making a horizontal scroll bar necessary. Although it is not a firm rule, restricting a page so that it does not scroll horizontally at your target resolution is a good idea.
One solution to the problems caused when a GridView control is placed in edit mode is to create a custom editing template. This can work for certain kinds of data. Later in this chapter, I will explain several options for editing data selected from a GridView control, as well as the custom editing templates.
Deleting
Looking back at the GridView Tasks menu shown in Figure 5-24, the next option is Enable Deleting. To make the grid fit a little better, select the Enable Deleting check box, and clear the Enable Editing check box. The page in Design view should look like Figure 5-26.
When the page is run, the Delete link appears, just like the Edit link in Figure 5-25.
Selecting
The last check box in the GridView Tasks menu is Enable Selection. Selecting this check box (and clearing Enable Deleting to allow the grid to fit better) replaces the Delete links with Select links, as shown in Figure 5-27.
When you run the page, the most interesting thing to note is that clicking the Select link posts back the page and changes the color of the row selected. This is not a very interesting feature; you can do several more interesting things with the Select feature. The section of this chapter on the DetailsView control will use the Select feature to edit the data in different ways.
Using a Custom EditItemTemplate
The GridView control provides a default appearance when a row in the GridView control is being edited. Often this default appearance is not sufficient. For those occasions, the developer can customize the appearance when editing by creating custom EditItemTemplate markup. The markup inside an EditItemTemplate is used whenever an item is being edited, and it can contain any number of controls. The easiest way to create an EditItemTemplate in a GridView control is to use the Edit Columns option on the GridView Tasks menu. To demonstrate how editing templates work, I created a new page named EditTemplate.aspx. I dragged new SqlDataSource and GridView controls onto the page, connected the SqlDataSource control to the BikeBlog database, and connected the GridView control to the SqlDataSource control.
When you come to the Fields dialog box, the Auto-generate Fields check box is selected by default. Clear this option, and then add the fields that you want to appear in the GridView control. I added the fields shown in Figure 5-28.
Note in Figure 5-29 that, in the Selected Fields list, the Subject and Message fields have a slightly different icon next to them. The different icon means that these fields are template fields. The Subject field should always be filled in, so adding a RequiredFieldValidator control is a good idea. The Message field can contain a great deal of text, so the default behavior when editing (creating a short, single-line text box) is not always appropriate. In Figure 5-29, I clicked Convert This Field Into A TemplateField for both the Subject field and the Message field. I also made the EnteredBy field read-only by using the properties window in the Fields dialog box.
If you want to allow editing, one more column must be added in the Fields dialog box. In the Available Fields list, expand the CommandField element and add an Edit, Update, Cancel field, and move it so that it is the first field in the Selected Fields list in the bottom left of the Fields dialog box, as shown in Figure 5-29. Click OK to accept the changes.
After you have converted the two fields into templates, the GridView control markup will be similar to the following.
<asp:GridView runat="server" AutoGenerateColumns="False" BackColor="White" BorderColor="#E7E7FF" Border BorderWidth="1px" CellPadding="3" DataSource GridLines="Horizontal"> <FooterStyle BackColor="#B5C7DE" ForeColor="#4A3C8C" /> <Columns> <asp:CommandField ShowEditButton="True" /> <asp:BoundField DataField="DateEntered" HeaderText="DateEntered" SortExpression="DateEntered" /> <asp:BoundField DataField="EnteredBy" HeaderText="EnteredBy" ReadOnly="True" SortExpression="EnteredBy" /> <asp:TemplateField HeaderText="Subject" SortExpression="Subject"> <EditItemTemplate> <asp:TextBox runat="server" Text='<%# Bind("Subject") %>'></asp:TextBox> </EditItemTemplate> <ItemTemplate> <asp:Label runat="server" Text='<%# Bind("Subject") %>'> </asp:Label> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="Message" SortExpression="Message"> <EditItemTemplate> <asp:TextBox runat="server" Text='<%# Bind("Message") %>'></asp:TextBox> </EditItemTemplate> <ItemTemplate> <asp:Label runat="server" Text='<%# Bind("Message") %>'></asp:Label> </ItemTemplate> </asp:TemplateField> </Columns> <RowStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" /> <SelectedRowStyle BackColor="#738A9C" Font-Bold="True" ForeColor="#F7F7F7" /> <PagerStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" HorizontalAlign="Right" /> <HeaderStyle BackColor="#4A3C8C" Font-Bold="True" ForeColor="#F7F7F7" /> <AlternatingRowStyle BackColor="#F7F7F7" /> </asp:GridView>
Note | In addition to the EditItemTemplate markup block, an ItemTemplate markup block is also present for each field. It is rare that the ItemTemplate provided by default is not sufficient. |
Inside the <EditItemTemplate> tags for the controls converted to templated fields is a single TextBox control. In each case, the Text property is set to the return of the Bind method, with the field name passed as a parameter. By modifying the tags that describe the controls used for editing, we can modify the look and feel of the GridView control while editing. I added a RequiredFieldValidator control to the EditItemTemplate for the Subject field, resulting in the following.
<asp:TemplateField HeaderText="Subject" SortExpression="Subject"> <EditItemTemplate> <asp:TextBox runat="server" Text='<%# Bind("Subject") %>'> </asp:TextBox> <asp:RequiredFieldValidator runat="server" ControlToValidate="TextBox2" ErrorMessage="*" Text="*" /> </EditItemTemplate> <ItemTemplate> <asp:Label runat="server" Text='<%# Bind("Subject") %>'></asp:Label> </ItemTemplate> </asp:TemplateField>
Next, I modified the EditItemTemplate for the Message field, making the TextBox control a multiline text box, and set a height and width that would not cause the GridView control to grow wider than the screen in edit mode. The resulting markup for the Message EditItemTemplate is shown here.
<asp:TemplateField HeaderText="Message" SortExpression="Message"> <EditItemTemplate> <asp:TextBox runat="server" TextMode="MultiLine" Height="120" Width="220" Text='<%# Bind("Message") %>'></asp:TextBox> </EditItemTemplate> <ItemTemplate> <asp:Label runat="server" Text='<%# Bind("Message") %>'></asp:Label> </ItemTemplate> </asp:TemplateField>
When run and placed in edit mode by clicking the Edit link, EditTemplate.aspx looks like Figure 5-30.