An Extensive Examination of the DataGrid Web Control: Part 10, Part 2By Scott Mitchell
In Part 1 we looked at adjusting the
subroutine so that it would accept an input parameter and, when called, display a DataGrid that contained
the FAQs with a particular
FAQCategory value. In this part we'll look at designing the
user interface to allow the end user to determine which categories FAQs they wish to view.
Displaying Hyperlinks for Each FAQ Category
As discussed in Part 1 of this article, an ideal way to allow the user to decide what FAQ category she wished to view the FAQs of would be to provide a listing of all of the FAQ categories at the top of the page in hyperlink form. When one of these hyperlinks was clicked, the ASP.NET page would postback, the
BindData(FilterOnFAQCategoryID)subroutine would be called with the proper
FilterOnFAQCategoryIDpassed in, and the DataGrid would have the proper subset of FAQs displayed.
One way to accomplish this would be to just add a hyperlink for each FAQ category, like so:
CommandArgument property corresponds to the particular FAQ category's
value. That is, all FAQs that fall under the "Application Object" category have a
value of 7; all FAQs that fall under the "Array" category have a
value of 1; etc. The DataGrid shown in the above code snippet is the actual DataGrid that
BindData(FilterOnFAQCategoryID) subroutine binds its results to - that is, it
is the DataGrid that will display the FAQs for the particular FAQ category.
Given the above code, all that we would need to do is add an event handler named
for the various LinkButtons'
Command events. The code for this event handler would be
insanely short and simple, consisting of just one line of code: namely, it would make a call to
BindData(FilterOnFAQCategoryID) subroutine passing in the value of
CommandArgument property as the input parameter. In code, it would look like:
When a user clicks on of these LinkButtons, the ASP.NET page is posted back, and the
event of the clicked LinkButton is raised. This triggers the
FilterData event handler
to run, which calls the
BindData(FilterOnFAQCategoryID) subroutine, passing in the
value of the clicked LinkButton's
CommandArgument property as the
parameter, which has the effect of having the DataGrid display those FAQs of that particular
Improving the Code - Removing the Hardcoded LinkButtons
The above code that uses a hardcoded LinkButton for each FAQ category will work, but it's messy for two reasons. First of all, had I actually taken the time to write the code for this page, I'd have to create a LinkButton for each FAQ - all 21 of them. Additionally, I'd have to find out the
FAQCategoryIDassociated with each FAQ and set the LinkButton's
CommandArgumentproperty accordingly. On top of this, if I added or removed any FAQ categories from the database, I'd have to edit this Web page (adding new LinkButtons when new FAQ categories were added and removing LinkButtons when FAQ categories were removed).
A better approach would be to have the FAQ category LinkButtons generated dynamically. Recall from
Dynamic Controls in ASP.NET that controls can be added dynamically
Add method of the
Controls collection (a collection each and every
Web control has). To add our needed LinkButtons dynamically we'll first create a PlaceHolder control
to mark where these LinkButtons should be added in the HTML content. Next, we'll perform a SQL query
that will populate a
SqlDataReader with the various FAQ categories. We can then iterate
SqlDataReader adding a LinkButton for each row.
The following code provides a subroutine (
AddFilterButtons()) that dynamically creates the needed LinkButtons. It adds
each LinkButton to a PlaceHolder named
phFilterLinkButtons, which appears in the HTML
section (see the code at the bottom of the live demo for more
details). Also note that some HTML markup (namely, a pipe symbol (
|)) is added between
each LinkButton to make it easier to read.
AddFilterButtons() subroutine needs to be called in the
handler so that the LinkButtons are created on each page load. By default, dynamically created
controls are not saved to the Page's ViewState, meaning that they are lost across postbacks.
If you want to save a dynamically created control in the ViewState you must do it explicitly, using
ViewState("ViewStateKey") = ControlName.PropertyToSave to save one of the
control's properties, and
ControlName.PropertyToSave = ViewState("ViewStateKey")
to restore it. Without saving the LinkButtons in the ViewState you are having to incur a database access
every page view to grab the list of FAQ categories.
Take a moment to check out the live demo. Note that the
AddFilterButtons() subroutine is indeed called in the
Page_Load event handler,
and where the
phFilterLinkButtons PlaceHolder control appears in the HTML markup.
In this article we saw how to create filtering buttons for a DataGrid control. Once we made a slight edit to our original
BindData()function this added feature was as easy as adding the LinkButtons to complete the user interface and providing a (one-line) event handler for the LinkButtons'
Commandevents. In addition, we saw how to dynamically add a LinkButton for each unique FAQ category in the database. Dynamically adding the controls has the advantage of saving time from typing in hardcoded LinkButtons and, more importantly, saves us editing time when the
FAQCategoriestable is added to or deleted from.