An Extensive Examination of the DataGrid Web Control: Part 10, Part 2
By Scott Mitchell
In Part 1 we looked at adjusting the BindData()
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 FilterOnFAQCategoryID passed 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:
|
The CommandArgument property corresponds to the particular FAQ category's FAQCategoryID
value. That is, all FAQs that fall under the "Application Object" category have a FAQCategoryID
value of 7; all FAQs that fall under the "Array" category have a FAQCategoryID
value of 1; etc. The DataGrid shown in the above code snippet is the actual DataGrid that
the 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 FilterData
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
the BindData(FilterOnFAQCategoryID) subroutine passing in the value of
the 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 Command
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 FilterOnFAQCategoryID
parameter, which has the effect of having the DataGrid display those FAQs of that particular
FAQCategoryID.
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
FAQCategoryID
associated with each FAQ and set the LinkButton's CommandArgument property 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
via the 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
through this 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.
|
The AddFilterButtons() subroutine needs to be called in the Page_Load event
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.
Conclusion
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'
Command events. 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 FAQCategories
table is added to or deleted from.
Happy Programming!




