Handling events in ASP.NET is not always as straightforward as it seems. One particular pattern that often occurs is that there’s several items in a row in a GridView control that trigger commands. Now the GridView supports several standard commands such as Select and Delete, but what if you want to issue your own command?
As an example, here’s my situation. I have a GridView that displays relationships between contacts, such as in the picture below.
Here, the left part triggers another use case to update the relationship, but the second part needs to start a use case to view the other contact in the relationship. How did I implement this?
First of all, you will need to add a DataCommand to the control (in my case a LinkButton. Here I specified it with “OtherContact”.
When you now click on the LinkButton you will be able to capture this command from the event arguments of the RowCommand event, which fires upon clicking the button. So first you will need to add a handler to the event.
1: this.grdRelationship.RowCommand += new GridViewCommandEventHandler(grdRelationship_RowCommand);
The RowCommand event comes with event arguments, which is an instance of the GridViewCommandEventArgs class. As you might expect this class has a property CommandName you will be able to verify.
Now for the somewhat harder part. My GridView is bound to a collection of Relationship objects, and I need to find out which of the rows is actually clicked to be able to pass the right Relationship to the next use case. Hence, I need to get hold of the index of the row that was clicked. Unfortunately, this index is not a valid property of the GridViewCommandEventArgs, nor on any of its properties properties.
However, there is an additional property available that might help, and that is the CommandArgument property. Just like the CommandName this property can be set on the LinkButton in the GridView. The trick here is to set it (for example) to the index of the row it is in. I’ve used the following expression to achieve this.
1: CommandArgument='<%# DataBinder.Eval(Container, "RowIndex")%>'
Of course there’s alternatives such as putting in the Id for the actual Relationship object, but RowIndex seems fine to me – this way the object’s identification at least doesn’t show up in HTML.
Putting it together
The last step here is to put it all together in handling the RowCommand event. The remaining code isn’t hard to understand.
1: void grdRelationship_RowCommand(object sender, GridViewCommandEventArgs e)
3: if (e.CommandName == "OtherContact")
5: Relationship r = Relationships[Convert.ToInt32(e.CommandArgument)];
I simply validate the CommandName and use the CommandArgument to identify the relationship that was clicked as pass that relationship to the underlying use case (in the MyTask property of the page).