In this post, I am going to show how we can make a GridView row clickable. What I mean by this is when the user clicks on a row, it will fire a postback to the server that the programmer can handle.
There are endless uses for this functionality. You may want to toggle a row into edit mode or display/bind another GridView on your page when a user clicks on a row. I actually use this feature a lot. In my opinion it is easier on the user if they can simply click on a row to perform a desired action.
RowClickGridView Class/Control:
In order to make rows clickable, we are going to create a custom GridView control. We are going to inherit from System.Web.UI.WebControls.GridView because we want all the functionality of the basic GridView plus our own enhancements. We will name the control "RowClickGridView".
'key that is used for our RowClicked event handler
Private Shared ReadOnly RowClickedEventKey As Object = New Object()
<DefaultValue(False), Description("Indicates whether or not rows are clickable.")> _
Public Property RowClick_Enabled() As Boolean
Get
If Not IsNothing(ViewState("RowClick_Enabled")) Then
Return DirectCast(ViewState("RowClick_Enabled"), Boolean)
Else
Return False
End If
End Get
Set(ByVal value As Boolean)
ViewState("RowClick_Enabled") = value
End Set
End Property
<DefaultValue(""), Description("Specifies the ToolTip for clickable rows."), Category("Appearance")> _
Public Property RowClick_ToolTip() As String
Get
If Not IsNothing(ViewState("RowClick_ToolTip")) Then
Return ViewState("RowClick_ToolTip").ToString()
Else
Return String.Empty
End If
End Get
Set(ByVal value As String)
ViewState("RowClick_ToolTip") = value
End Set
End Property
Here we create 2 properties and 1 class variable. The RowClickedEventKey in line 2 is later used for our event handling. We have 2 properties. I want the RowClicked functionality to not trigger postbacks unless I enable it. I would also like to be able to set ToolTips on the row if it is clickable. We persist the properties via the ViewState so that if the default values get changed across postbacks programmatically, our control will remember them.
Protected Overrides Sub PrepareControlHierarchy()
MyBase.PrepareControlHierarchy()
'wire RowClick event & RowClick tooltip for rows if RowClicked is enabled
If Me.RowClick_Enabled Then
Dim argsData As String = String.Empty
For Each row As GridViewRow In Me.Rows
'if row is a data row & it's not the edit row
If row.RowType = DataControlRowType.DataRow And Me.EditIndex <> row.RowIndex Then
'create argument - pass the row index
argsData = "rc" & row.RowIndex.ToString()
'wire javascript to the row for the RowClicked event
row.Attributes.Add("onClick", Me.Page.ClientScript.GetPostBackEventReference(Me, argsData))
'if the RowClick ToolTip is supplied
If Not String.IsNullOrEmpty(Me.RowClick_ToolTip) Then
'apply tooltip to row
row.ToolTip = Me.RowClick_ToolTip
End If
End If
Next
End If
End Sub
The PrepareControlHierarchy() method is new in .NET 2.0. What this method does is basically establishes the control hierarchy. So before we tap into the GridView's control hierarchy, we call the MyBase.PrepareControlHierarchy(). We only want to make rows clickable if we've enabled it, so we check that irst on line 5. After the hierarchy is ready, we loop through the rows of the GridView and acquire the rows we wish to make clickable (line 9). Once we have a row we wish to make clickable, we form the argument data and wire the row to fire a postback when clicked. We also add our row click tooltip if supplied.
Protected Overrides Sub RaisePostBackEvent(ByVal eventArgument As String)
'if a row clicked event
If eventArgument.StartsWith("rc") Then
'get the index of the row that raised the event
Dim index As Integer = Int32.Parse(eventArgument.Substring(2))
'create our instance of GridViewRowClickedEventArgs passing the GridViewRow clicked
Dim args As GridViewRowClickedEventArgs = New GridViewRowClickedEventArgs(Me.Rows(index))
'raise the RowClicked event
OnRowClicked(args)
Else
'raise any other event (not row clicked)
MyBase.RaisePostBackEvent(eventArgument)
End If
End Sub
In order to raise our custom event if the row clicked, we need to override the GridView's RaisePostBackEvent method. This method raises the GridView's events when it posts back to the server. We check to see if the row clicked event was the trigger in line 3. We then acquire the row index that fired the event by stripping it out of the eventArgument string in line 5. We want to be able to tap into the entire row when the event is fired later, so we are going to create a custom event argument class (posted below). We instantiate the GridViewRowClickedEventArgs class by passing in the GridViewRow. and then call our OnRowClicked() method to raise the event.
Protected Overridable Sub OnRowClicked(ByVal e As GridViewRowClickedEventArgs)
'raise the RowClicked event
RaiseEvent RowClicked(Me, e)
End Sub
Here is the OnRowClicked() helper method mentioned above. We simply raised the RowClicked event.
'setup our EventHandler for RowClicked
Public Custom Event RowClicked As EventHandler(Of GridViewRowClickedEventArgs)
AddHandler(ByVal value As EventHandler(Of GridViewRowClickedEventArgs))
Events.AddHandler(RowClickedEventKey, value)
End AddHandler
RemoveHandler(ByVal value As EventHandler(Of GridViewRowClickedEventArgs))
Events.RemoveHandler(RowClickedEventKey, value)
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As GridViewRowClickedEventArgs)
Dim ev As EventHandler(Of GridViewRowClickedEventArgs) = TryCast(Events(RowClickedEventKey), EventHandler(Of GridViewRowClickedEventArgs))
If Not IsNothing(ev) Then
ev(sender, e)
End If
End RaiseEvent
End Event
This is the EventHandler for our RowClicked event. You can see the add, remove, and raise event implementations above. The important thing to note here is the use of our custom event argument class (GridViewRowClickedEventArgs).
GridViewRowClickedEventArgs Class:
In our RowClickGridView control, you noticed we used a custom event argument class for our event handler. Here is the code:
'our custom event argument class for the RowClicked event
Public Class GridViewRowClickedEventArgs
Inherits EventArgs
Private _row As GridViewRow
Public ReadOnly Property Row() As GridViewRow
Get
Return _row
End Get
End Property
Public Sub New(ByVal row As GridViewRow)
_row = row
End Sub
End Class
You notice that we inherit from EventArgs and add a property to tap into the GridViewRow that was clicked. The class requires the row clicked in its constructor.
RowClickGridView In Action:
Now that we have our control developed, we can use it. We first add it to our aspx page and setup our 2 properties:
<p>Row Index Clicked: <asp:Label ID="Label1" runat="server" /></p>
<cc1:RowClickGridView ID="RowClickGridView1" runat="server"
AutoGenerateColumns="False" DataKeyNames="CategoryID"
DataSourceID="SqlDataSource1" RowClick_Enabled="true" RowClick_ToolTip="Row Click ToolTip">
<Columns>
<asp:BoundField DataField="CategoryID" HeaderText="CategoryID"
InsertVisible="False" ReadOnly="True" SortExpression="CategoryID" />
<asp:BoundField DataField="CategoryName" HeaderText="CategoryName"
SortExpression="CategoryName" />
<asp:BoundField DataField="Description" HeaderText="Description"
SortExpression="Description" />
</Columns>
</cc1:RowClickGridView>
Notice we enable row clicking and also set the tooltip we want on clickable rows. To see what index we clicked, we want to capture the event and set a label control in the code behind.
Protected Sub RowClickGridView1_RowClicked(ByVal sender As Object, ByVal e As GridViewRowClickedEventArgs) Handles RowClickGridView1.RowClicked
Me.Label1.Text = e.Row.RowIndex.ToString()
End Sub
And that's it! We've created a custom GridView control that has row click functionality. I've attached the code for your pleasure. Enjoy!
Examples_Soln.zip (102.13 kb)