Click here to Skip to main content
Click here to Skip to main content

Extended ASP.NET GridView with cell click events

By , 21 Jan 2010
 

Download Code and Demo Solution  - 184.4 KB

Introduction

The ASP.NET GridView is an excellent control and is widely used, but still lacks some features. This article demonstrates extending the GridView to add cell click event handling by inheriting from the base GridView class, overriding and changing some of the properties and behaviour.

Background

After doing some research, there seems to be not a lot of resources with regards to cell click event handling in the ASP.NET GridView. I have found one or two articles where you have to add some JavaScript functions to the RowDataBound() event of the GridView. I wanted an out-of-the-box gridview with this functionality. Finally, I came across a blog post by Jonni Teemu Keiski called Developing a row-clickable GridView, and started from there by applying the same principle to the cells of the GridView.

Using the code

Adding a designer property: Enable cell-click

Since we opt to have a generic control, we add a property that the programmer can set to enable postback events when a cell is clicked.

<DefaultValue(False)> _
Public Property EnableCellClick() As Boolean
    Get
        Dim ret As Boolean = False
        Dim obj As Object = ViewState("EnableCellClick")
        If obj IsNot Nothing Then
            ret = CBool(obj)
        End If
        Return ret
    End Get
    Set(ByVal value As Boolean)
        ViewState("EnableCellClick") = value
    End Set
End Property

Adding a class for the arguments of the cell-click event

In order to return the properties of the cell that was clicked, we create a new custom event argument that inherits the base event argument class. We will return the custom event argument in the custom event handler CellClicked() that we'll create in the next section.

Public Class GridViewCellClickedEventArgs _
        Inherits EventArgs
    Private mobjCell As TableCell
    Private mobjRow As GridViewRow
    Private mintColumnIndex As Integer
    Public Sub New(ByVal Cell As TableCell, _
                   ByVal row As GridViewRow, _
                   ByVal ColumnIndex As Integer)
        mobjCell = Cell
        mobjRow = row
        mintColumnIndex = ColumnIndex
    End Sub
    Public ReadOnly Property Cell() As TableCell
        Get
            Return mobjCell
        End Get
    End Property
    Public ReadOnly Property Row() As GridViewRow
        Get
            Return mobjRow
        End Get
    End Property
    Public ReadOnly Property ColumnIndex() As Integer
        Get
            Return mintColumnIndex
        End Get
    End Property
End Class

Creating an event for the cell click

In the next section, we will add a custom event which will return our custom event argument created previously for the programmer to use:

Protected Sub XGridView1_CellClicked(ByVal sender As Object, _
           ByVal e As CustomControls.GridViewCellClickedEventArgs) _
           Handles XGridView1.CellClicked
    'Do Something
     Response.Write("Contents of cell clicked: " & e.Cell.Text)
     Response.Write("Zero based column index of clicked cell: " & e.ColumnIndex)
End Sub

Adding the custom event

The custom event contains AddHandler, a RemoveHandler which simply tells the call to attach or remove the given event handler from the cell's click event.

Lastly, we'll use a RaiseEvent implementation to raise the event as in the previous section (e.g., XGridView1_CellClicked()).

Public Custom Event CellClicked As EventHandler(Of GridViewCellClickedEventArgs)
  AddHandler(ByVal value As EventHandler(Of GridViewCellClickedEventArgs))
      Events.AddHandler(CellClickedEventKey, value)
  End AddHandler
  RemoveHandler(ByVal value As EventHandler(Of GridViewCellClickedEventArgs))
      Events.RemoveHandler(CellClickedEventKey, value)
  End RemoveHandler
  RaiseEvent(ByVal sender As Object, ByVal e As GridViewCellClickedEventArgs)
      Dim ev As EventHandler(Of GridViewCellClickedEventArgs) = _
      TryCast(Events(CellClickedEventKey), _ 
       EventHandler(Of GridViewCellClickedEventArgs))
      If ev IsNot Nothing Then
         ev(sender, e)
      End If
  End RaiseEvent
End Event

Protected Overridable Sub OnCellClicked(ByVal e As GridViewCellClickedEventArgs)
  RaiseEvent CellClicked(Me, e)
End Sub

Adding the attributes of the base control (GridView) to the child controls (TableCell)

The next step is to apply the click event and event arguments to the child control which is the TableCell of the GridView. This is done by overriding the PrepareControlHierarchy() method of the base class.

For i As Integer = 0 To Rows.Count - 1
     For j As Integer = 0 To Rows(i).Cells.Count - 1
         'Row Index                                'Column Index              
         Dim argsData As String = "cc" & ";" & Rows(i).RowIndex.ToString & _
           ";" &   j.ToString
         Me.Rows(i).Cells(j).Attributes.Add("onclick", _ 
         Page.ClientScript.GetPostBackEventReference(Me, argsData))
     Next
Next

Handling the postback

Finally, we override the RaisePostBackEvent() event. In this method, the GridView's events are raised when a postback happens on the server. We will override the method to determine from the EventArgument whether the event was caused by clicking a cell. From here, we use the event data to create a new instance of GridViewCellClickedEventArgs and pass it to the OnCellClicked() method.

Protected Overrides Sub RaisePostBackEvent(ByVal eventArgument As String)
    If eventArgument.StartsWith("cc") Then      'Cell click
       Dim lcolIndices() As String = eventArgument.Split(";")
       Dim lintRowIndex As Integer = lcolIndices(1).ToString()
       Dim lintColumnIndex As Integer = lcolIndices(2).ToString()
       Dim args As New GridViewCellClickedEventArgs(Me.Rows(lintRowIndex). _
           Cells(lintColumnIndex), Me.Rows(lintRowIndex), lintColumnIndex)
       OnCellClicked(args)
     Else
        MyBase.RaisePostBackEvent(eventArgument)
     End If
End Sub

Adding the control to a webpage

<%@ Register Assembly="XGridView" 
   Namespace="CustomControls" TagPrefix="cc1" %>
<cc1:XGridView ID='XGridView' runat="server" EnableCellClick="True" 
        DataSourceID="XmlDataSource1" >
</cc1:XGridView>

Note that we have enabled the cell click in the markup, but it can also be set in the property designer in the IDE.

Adding some code to the CellClicked() event

Protected Sub XGridView_CellClicked(ByVal sender As Object, _
         ByVal e As CustomControls.GridViewCellClickedEventArgs) _
         Handles XGridView.CellClicked
   lblResult.Text = "Index of the cell clicked was:  " & e.ColumnIndex.ToString  
   lblResult0.Text = "Value of cell clicked:  " & e.Cell.Text.ToString 
   lblResult1.Text = "Index of the row clicked was:  " & e.Row.RowIndex
End Sub

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Divan van der Watt
Software Developer
South Africa South Africa
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionHow to fixed headermembermanish_rcc15-Feb-13 18:35 
This is very good example to bind gridview with dynamic and row and column
i am trying to fix the header .
can you please let me know how to fixed the header.
AnswerRe: How to fixed headermembermanish_rcc17-Feb-13 22:07 
can you please let me know how to fixed the header.
QuestionGracias!!! ThanKsmembermhorkpheus11-Dec-12 9:47 
The only help that helps thanks a lot just one little think, i had to use only the dll included at the source, cause the code it self didnt work, there was a problem wen i was trying to add the new control at the web page be cause it saids that wasnt posible to add it buecause it weasnt declared... any way thanks im just starting at .Net and this helped me a lot Smile | :)
QuestionThank you!membercodemachine9993-Dec-11 2:11 
You can't know how long I have searched for this simple solution!
Thank you so very much!!!
 
One request though: is it possible to disable the underlining of the cell content when you place your mouse on them?
AnswerRe: Thank you!memberDivan van der Watt3-Dec-11 11:02 
Cool glad I could help Smile | :)
 
Yeah you can disable the underlining by commenting the following lines out in XGridView.vb (line 162):
 
                        Me.Rows(i).Cells(j).Attributes("onmouseover") = "this.style.cursor='hand';this.style.textDecoration='underline';"
                        Me.Rows(i).Cells(j).Attributes("onmouseout") = "this.style.textDecoration='none';"
 
Enjoy!
GeneralRemove cell click from individual cellsmemberchriskellerx1018-Jun-10 3:47 
Hello, Thank you very much for the control. It has been very helpful to me. Is there a way to only add cell-click to certain cells or columns, or even better just add cell-click to a particular cell when databinding?
Thanks
QuestionSorting/Paging?memberlastusernameleft25-Jan-10 8:35 
Excellent control, with the exception of missing sorting and paging events. Any ideas to implement? I'm guessing has to be handled in the RaisePostBackEvent, event argument begins with either "Sort" or "Page", but wondering what the most elegant handling would be. Any pointers would be greatly appreciated.
 
Thanks!
AnswerRe: Sorting/Paging?memberDivan van der Watt25-Jan-10 20:11 
Cool thanks! Will check out the sorting and paging will let you know a.s.a.p. Smile | :)
QuestionCan I retrieve column headers?memberMember 193577021-Jan-10 8:32 
This is a very cool control. Thanks for publishing it.
Is there a way to retrieve the column header of the cell clicked?
I can retrieve any cell from a row clicked by using
Dim Cell1 As String = e.Row.Cells(0).Text
 
But I wouold like to get a value of the HeaderText for the Cell clicked.
 
thanks
Jakub
AnswerRe: Can I retrieve column headers?memberDivan van der Watt21-Jan-10 20:26 
Hi Jakub
 
Thanks Smile | :) Yes it is indeed possible.
 
Here's a suggestion on what you could do:
 
Add the following lines in the PrepareControlHierarchy method which will add the HeaderText to the argsdata.
 
lstrHeaderText = HeaderRow.Cells(j).Text
     Dim argsData As String = "cc" & ";" & Rows(i).RowIndex.ToString & ";" & j.ToString & ";" & lstrHeaderText
 

Change the constructor of the CellClickedEventArgs class:
 
   Private mstrHeaderText As String
        Public Sub New(ByVal Cell As TableCell, ByVal row As GridViewRow, ByVal ColumnIndex As Integer, ByVal HeaderText As String)
            mobjCell = Cell
            mobjRow = row
            mintColumnIndex = ColumnIndex
            mstrHeaderText = HeaderText
        End Sub
 

In the RaisePostBackEvent() for the Cell click event, retrieve the Headertext from the argsdata added in the PrepareControlHierarchy() method.
 
    If eventArgument.StartsWith("cc") Then
 
                Dim lcolIndices() As String = eventArgument.Split(";")
                Dim lintRowIndex As Integer = lcolIndices(1).ToString()
                Dim lintColumnIndex As Integer = lcolIndices(2).ToString()
                Dim lstrHeaderText As String = lcolIndices(3).ToString()
                Dim args As New GridViewCellClickedEventArgs(Me.Rows(lintRowIndex).Cells(lintColumnIndex), Me.Rows(lintRowIndex), lintColumnIndex, lstrHeaderText)
                OnCellClicked(args)
            Else
                MyBase.RaisePostBackEvent(eventArgument)
            End If
 
Lastly add the following property to the GridViewCellClickedEventArgs class, which will enable you to retrieve the HeaderText from event argument when a cell is clicked:
 
Public ReadOnly Property HeaderText() As String
            Get
                Return mstrHeaderText
            End Get
        End Property
 

Hope it helps, I have posted the new code to the article.
 

Enjoy
 
Regards
 
Divan

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130627.1 | Last Updated 22 Jan 2010
Article Copyright 2010 by Divan van der Watt
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid