An Extensive Examination of the DataGrid Web Control: Part 7By Scott Mitchell and Matthew Rouse
|The Seventh Part in a Multi-Part Series|
This article is the seventh piece of a multi-part series on using the DataGrid Web control that will span
several months. The ASP.NET DataGrid Web control, which displays database information in an HTML table, is
highly versatile. The basics of the DataGrid were discussed in Part 1;
information on specifying display properties of the DataGrid was discussed in
Part 2. In Part 3
we examined how to associate custom events with the DataGrid.
In Part 4 we looked at how to extend
Part 3 to provide custom sorting on the results of a DataGrid. In
Part 5 we examined how to use templates to further customize
the DataGrid's appearance. Part 6 examined how to use the
DataGrid's built-in editing capabilities. In this part we will extend Part 6 and examine how to
customize the editing interface of the DataGrid!
In Part 6 of the DataGrid article series we looked at how to use the DataGrid's built-in editing features. One could add inline editing to the DataGrid's contents by simply adding an EditCommandColumn along with event handlers for the
OnUpdateCommand. By performing these steps, the DataGrid is enhanced to include an "Edit" button on each row. When clicked, the columns in that particular row that are not marked as readonly are transformed into TextBoxes populated with the column values. The user can then edit these values and click the "Update" button. (See this screenshot, as well as this one, for an idea of what this would look like.)
These TextBoxes are the default editing interface, but you can customize this editing interface to allow for more flexibility. For example, if one of your DataGrid columns is a True/False field, you could have the DataGrid display a True/False pair of radio buttons instead of the default TextBox. Likewise, if one column was a foreign key to a lookup table, you might want to present the user with a DropDownList of applicable choices, as opposed to letting them type in a value in the TextBox. Note that to customize the DataGrid's editing interface requires a bit of extra markup in the DataGrid Web control as well as some light additional code. The code and markup, I think you'll find, is relatively simple; the difficulty, in my opinion, lies in understand what, exactly, is happening behind the scenes!
Customizing the Editing Interface with EditItemTemplate
In order to customize the DataGrid's editing interface you have to be using a TemplateColumn. Recall from Part 5 of the series that TemplateColumns can be added to a DataGrid to allow for additional customization of the HTML output that is rendered when the DataGrid is
DataBinded to its
DataSource. If you use a BoundColumn to represent a column in the DataGrid, the editing interface will be the default TextBox.
In this article we will work through a real-world example. In the previous articles in this series,
we've used live demos against the FAQ database over at ASPFAQs.com.
This database is comprised of a number of tables, the main one being
tblFAQ, which has a
row for each FAQ. One of the columns in the
tblFAQ table is called
and is a foreign key to the
tblFAQCategory table, which has a row for each FAQ category
(these categories include Array, Appilcation Object, Email, ASP.NET, Forms, etc.). Specifically, the
important parts of these tables are defined as follows:
Using the knowledge you have attained in the past 6 installments of this article series, you should be able to quickly and easily create a DataGrid that displayed a row for each FAQ, including the FAQ's category name (as opposed to an integer). The following SQL statement would be sufficient to tie in the appropriate category name for each FAQ:
In fact, I have whipped up a simple live demo to illustrate this. Nothing too fancy here, obviously. Now, imagine that you wanted to let the user edit the DataGrid. You may think, "Well, I've read Part 6 of this article series, so I know what to do! Let me just add an EditCommandColumn and go from there!" This is definitely the correct first step, but we have more to do after this due to the undesirable editing interface the BoundColumns create when in edit mode. Check out this live demo and be sure to click on Edit for a row. What do you see?
In case you're too lazy to try out the live demo, the
screenshot to the right shows the result. Note that the Category
column has been transformed into the default TextBox in editing mode. At first this may not seem like
that bad of a proposal. If someone wanted to change the Category for FAQ #2 from Strings to Arrays,
they could simply type in Arrays. Of course this is not optimal for a number of reasons. First, recall
that the Category for each FAQ is stored as a foreign key to the
tblFAQCategory table, not
as a string (such as "Arrays"). While you could scan the
tblFAQCategory for an
appropriate category name, and then use that row's corresponding
FAQCategoryID to update
tblFAQ row, that would be messy; furthermore, what if the user made a typo, typing
in "String" instead of "Strings?" Would you display an error message? Assume they meant to enter Strings?
Create a new row in
Clearly the ideal approach would be not to display a TextBox for the Category when the row was edited, but instead a listbox with the appropriate category values for the user to select from. To accomplish this we can customize the HTML outputted when a row is selected to be edited by specifying an EditItemIndex control in a TemplateColumn. Recall that for a DataGrid column to have a customized editing interface, the column must be a TemplateColumn, not a BoundColumn; so, the first thing we need to do is transform the BoundColumn that displays the category name into a TemplateColumn. The following simple TemplateColumn and ItemTemplate pair will do the trick (be sure to read Part 5 of this article series for more information on using TemplateColumns):
Here we simply display the result of the
CategoryName column from the DataSource.
We are not done yet; currently if the user clicks the "Edit" button there will be no special
rendering for the category name column. That is, they will just see the text of the category name,
no TextBox, no DropDownList, etc. This is because when we don't use a BoundColumn we need to specify
the HTML to use when the row is in edit mode. We do this by using the EditItemTemplate control
inside the TemplateColumn control (much like the ItemTemplate control to display the HTML to render
when the row is not in edit mode).
Since we want to show a DropDownList for the category names in edit mode, let's start by simply adding an ASP.NET DropDownList Web control to the EditItemIndex, like so:
Since this DropDownList will contain a list of the existing FAQ categories, we will be using databinding
to bind the DropDownList to a DataSource that is comprised of the contents of the
table. When using a databound DropDownList, you need to specify the what column from the DataSource
you wish to have displayed as the text for each DropDownList option, and what value you want tied to these
textual labels. Since we want to display a DropDownList item for each row in the
table, it makes sense to have the name of the category (the
Name column) displayed as the
textual part of the DropDownList item, and the actual
FAQCategoryID as the value of the
DropDownList item. (If you are utterly confused by this, I'd highly encourage you to read:
Creating Databound DropDown Lists in ASP.NET.)
This is the reason I set the
DataTextFields to the given
column names above.
Of course, realize that while we've specified the columns to bind to the DropDownList, we've yet to
specify where the DropDownList's DataSource is coming from. Essentially, we need to construct a
DataSet with the rows from the
tblFAQCategory table. Before I delve into the specifics
on this, let's take a step back and examine what's happening behind the scenes when a DataGrid is
edited in Part 2. (I highly encourage that you read the following section, but if you just want to "get it working"
first and understand why later, then you may skip the next section; however, you may find yourself
a little confused with latter parts of the article... Regardless of your choice, continue on to
Part 2 to continue with the article!)