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".
1: 'key that is used for our RowClicked event handler
2: Private Shared ReadOnly RowClickedEventKey As Object = New Object()
3:
4: <DefaultValue(False), Description("Indicates whether or not rows are clickable.")> _
5: Public Property RowClick_Enabled() As Boolean
6: Get
7: If Not IsNothing(ViewState("RowClick_Enabled")) Then
8: Return DirectCast(ViewState("RowClick_Enabled"), Boolean)
9: Else
10: Return False
11: End If
12: End Get
13: Set(ByVal value As Boolean)
14: ViewState("RowClick_Enabled") = value
15: End Set
16: End Property
17:
18: <DefaultValue(""), Description("Specifies the ToolTip for clickable rows."), Category("Appearance")> _
19: Public Property RowClick_ToolTip() As String
20: Get
21: If Not IsNothing(ViewState("RowClick_ToolTip")) Then
22: Return ViewState("RowClick_ToolTip").ToString()
23: Else
24: Return String.Empty
25: End If
26: End Get
27: Set(ByVal value As String)
28: ViewState("RowClick_ToolTip") = value
29: End Set
30: 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.
1: Protected Overrides Sub PrepareControlHierarchy()
2: MyBase.PrepareControlHierarchy()
3:
4: 'wire RowClick event & RowClick tooltip for rows if RowClicked is enabled
5: If Me.RowClick_Enabled Then
6: Dim argsData As String = String.Empty
7: For Each row As GridViewRow In Me.Rows
8: 'if row is a data row & it's not the edit row
9: If row.RowType = DataControlRowType.DataRow And Me.EditIndex <> row.RowIndex Then
10: 'create argument - pass the row index
11: argsData = "rc" & row.RowIndex.ToString()
12:
13: 'wire javascript to the row for the RowClicked event
14: row.Attributes.Add("onClick", Me.Page.ClientScript.GetPostBackEventReference(Me, argsData))
15:
16: 'if the RowClick ToolTip is supplied
17: If Not String.IsNullOrEmpty(Me.RowClick_ToolTip) Then
18: 'apply tooltip to row
19: row.ToolTip = Me.RowClick_ToolTip
20: End If
21: End If
22: Next
23: End If
24: 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.
1: Protected Overrides Sub RaisePostBackEvent(ByVal eventArgument As String)
2: 'if a row clicked event
3: If eventArgument.StartsWith("rc") Then
4: 'get the index of the row that raised the event
5: Dim index As Integer = Int32.Parse(eventArgument.Substring(2))
6:
7: 'create our instance of GridViewRowClickedEventArgs passing the GridViewRow clicked
8: Dim args As GridViewRowClickedEventArgs = New GridViewRowClickedEventArgs(Me.Rows(index))
9:
10: 'raise the RowClicked event
11: OnRowClicked(args)
12: Else
13: 'raise any other event (not row clicked)
14: MyBase.RaisePostBackEvent(eventArgument)
15: End If
16: 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.
1: Protected Overridable Sub OnRowClicked(ByVal e As GridViewRowClickedEventArgs)
2: 'raise the RowClicked event
3: RaiseEvent RowClicked(Me, e)
4: End Sub
Here is the OnRowClicked() helper method mentioned above. We simply raised the RowClicked event.
1: 'setup our EventHandler for RowClicked
2: Public Custom Event RowClicked As EventHandler(Of GridViewRowClickedEventArgs)
3: AddHandler(ByVal value As EventHandler(Of GridViewRowClickedEventArgs))
4: Events.AddHandler(RowClickedEventKey, value)
5: End AddHandler
6:
7: RemoveHandler(ByVal value As EventHandler(Of GridViewRowClickedEventArgs))
8: Events.RemoveHandler(RowClickedEventKey, value)
9: End RemoveHandler
10:
11: RaiseEvent(ByVal sender As Object, ByVal e As GridViewRowClickedEventArgs)
12: Dim ev As EventHandler(Of GridViewRowClickedEventArgs) = TryCast(Events(RowClickedEventKey), EventHandler(Of GridViewRowClickedEventArgs))
13: If Not IsNothing(ev) Then
14: ev(sender, e)
15: End If
16: End RaiseEvent
17: 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:
1: 'our custom event argument class for the RowClicked event
2: Public Class GridViewRowClickedEventArgs
3: Inherits EventArgs
4:
5: Private _row As GridViewRow
6:
7: Public ReadOnly Property Row() As GridViewRow
8: Get
9: Return _row
10: End Get
11: End Property
12:
13: Public Sub New(ByVal row As GridViewRow)
14: _row = row
15: End Sub
16: 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:
1: <p>Row Index Clicked: <asp:Label ID="Label1" runat="server" /></p>
2: <cc1:RowClickGridView ID="RowClickGridView1" runat="server"
3: AutoGenerateColumns="False" DataKeyNames="CategoryID"
4: DataSourceID="SqlDataSource1" RowClick_Enabled="true" RowClick_ToolTip="Row Click ToolTip">
5: <Columns>
6: <asp:BoundField DataField="CategoryID" HeaderText="CategoryID"
7: InsertVisible="False" ReadOnly="True" SortExpression="CategoryID" />
8: <asp:BoundField DataField="CategoryName" HeaderText="CategoryName"
9: SortExpression="CategoryName" />
10: <asp:BoundField DataField="Description" HeaderText="Description"
11: SortExpression="Description" />
12: </Columns>
13: </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.
1: Protected Sub RowClickGridView1_RowClicked(ByVal sender As Object, ByVal e As GridViewRowClickedEventArgs) Handles RowClickGridView1.RowClicked
2: Me.Label1.Text = e.Row.RowIndex.ToString()
3: 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)