ASP.NET’s GridView is one of the workhorse controls in AVR browser-based apps. It generally serves as the primary replacement for a subfile; used for navigating to a row and then selecting something to do with that row. This article shows how to fix a nagging challenge with the GridView: how to make multiple columns clickable and associate actions with those columns for the corresponding row. The full example project can be downloaded from the link at the end of this article.

Figure 1a below shows how we often use the GridView to select a customer for update. To make the customer name clickable, a ButtonField is used to render the customer name from the data source. Setting that ButtonField’s CommandName property to “select” causes the GridView’s SelectedIndexChanged event to fire.

Figure 1. GridView with single selectable column.

Figure 1a. A GridView with a single selectable column.

In the SelectedIndexChanged event, we could interrogate the GridView’s SelectedIndex to determine which row was clicked. Figure 1b below shows the SelectedIndexChanged event and how it is coded for this single selectable column. This is pretty standard use of the GridView and is featured in many AVR examples.

Figure 1b. The SelectedIndexChanged event for a single selectable column.

With the selected row determined, we could read values associated with the row (generally using the GridView’s DataKey’s property (which is simply a fancy word for hidden columns in the GridView). This model provided a quick, good way to select a row and do something with it. However, because there is only one clickable column. the code was written without regard for which column was selected. That’s OK in this simple example, but what if the user needs two or more actions available. For example, what if your users need to be able able to update or delete a row. This requires that your logic be able to determine which row and which column column got clicked. This is easy to do, but it’s not very obvious.

Changing the GridView to have multiple selectable columns

Figure 2 below shows the first pass at the result we’re after. We want to invoke multiple actions against any row. In this case we’re doing Edit and Delete actions, but we could do any number of actions with this model.

Figure 2. A GridView with multiple clickable columns.

To use this model, first we’re going to make the customer name a simple BoundField column. It won’t be clickable anymore (it could be, but we’re not doing that here). Then we add two ButtonField columns.  As shown below in Figure 3.

Figure 3a. Changing the customer to a BoundField and adding two buttons.

Two properties, Text and CommandName, need to be set for these two buttons. For the button that offers the update action, set its Text property to "Update" and its CommandName to "ActionUpdate"; for the button that offers the delete action, set its Text property to "Delete" and its CommandCommand property to "ActionDelete." The CommandName property can be a little confusing. There are several reserved command names that impose special-case behavior on the GridView. These commands are generally used with the GridView’s interoperability with SQL Server and I’ve not found much use for them with AVR. Avoid using these reserved command names. When one of these reserved command names is provided, the button fires the SelectedIndexChanged event when it is clicked, but when you provide your own command name, the RowCommand event is fired when the button is clicked. I generally start my command names with the word “Action” to ensure a distinction from my command names and the reserved command names.

With the two buttons added, a server-side click event handler needs to be added for them. The event needed is the RowCommand event. Its code is shown below in Figure 4.

Figure 4. The RowCommand Event.

The RowCommand handler gets fired when a button is clicked that has a CommandName not among the previously-discussed reserved command names. This event’s e argument provides two properties, CommandName and CommandArgument, that make it possible to determine the row and column clicked. The CommandName property is obvious–just compare it against the command names you assigned (ActionUpdate or ActionDelete, in this case). The CommandArgument is a little more subtle–and not nearly as obvious. The button field’s documentation explains that the CommandArgument for a button field is always the zero-based integer index of the row selected. (In older AVR examples, you can see two or three different hoops we used to jump through to provide this value. None of those hoops are necessary!)

This code in Figure 4 above shows that now it’s easy to determine which column and which row were selected. The CommandName indicates the column (and the action) selected (as indicated by the CommandName property we provided) and the selected row is read from the CommandArgument. This provides us with a GridView that looks like the one shown below in Figure 5a.

Figure 5a. The GridView with two clickable columns with text to indicate the actions available.

Using icons instead of words

This is nice, but let’s take things one step further and change the “Update” and “Delete” text to icons, as shown below in Figure 5b. For my money this not only makes things more professional looking, but also makes room for more clickable columns.

Figure 5b. The GridView with icons to indicate the actions available.

Adding icons without using any images!

If you’ve never heard of FontAwesome, you’re going to be stunned at how easy it is to change our text to icons–without using images. To do this, first, add the two lines below in Figure 6a to your ASPX page or master page before any other CSS:

Figure 6a. Pull in FontAwesome CSS from the Twitter Bootstrap CDN. (note the line is artifically wrapped. Make each link tag be one line in your code)

Now to swap out the previously provided Text properties for the HTML to render FontAwesome’s icons. FontAwesome renders its icons with HTML’s i tag. Specifying HTML for the Text property isn’t possible through the GridView’s column editor (because it encodes it improperly), so switch to the page markup source and change the values there. You’ll want to swap out these two lines:

Figure 6b. The original Text property values.

for these two lines:

Figure 6c. HTML provided in the Text property to show the FontAwesome icons

What’s happening here is CSS3 magic of the highest order. At runtime, FontAwesome (it’s all free!) uses CSS3 tricks to inject a special-case font character into your markup—no JavaScript needed. The FontAwesome site provides a full listing of all of the icons available and how to use them. You can find all of the font characters available and additional instructions at the FontAwesome site. This example fetches the necessary CSS from the Twitter Bootstrap CDN, but you can also download it from their website and load it locally.

I did also make one other minor change to the FontAwesome fonts—I changed their default blue color to match the GridView’s colors by including these CSS rules in my project’s home.master.css file (as shown below in Figure 6d).

Figure 6d. CSS to change the color of the FontAwesome fonts.