Click here to Skip to main content
11,502,201 members (64,136 online)
Click here to Skip to main content

Clickable and Double Clickable Rows with GridView and DataList Controls (ASP.NET 2.0)

, 19 Dec 2006 CPOL 374K 5.1K 162
Rate this:
Please Sign up or sign in to vote.
Handle single and double clicks with both the GridView and DataList Controls. Also, use ClientScript.RegisterForEventValidation to register the events and avoid disabling event validation.

Introduction

There are several online sources describing how to make a GridView row clickable anywhere on the row. There are also a few which describe how to make a row double-clickable. I haven't come across any which handle both events or deal with event validation errors in ASP.NET 2.0.

Here I will describe how to handle single and double clicks with the GridView, DataList and ListBox controls. I will also show how to deal with event validation without disabling it.

Background

While developing an ASP.NET application to replace an old Windows application, I was asked to keep the user experience relatively close to the original. The original application let a user select a row and perform an action on that row from a toolbar. By double clicking on a row the user could open another form with a details view of that row. This type of functionality could easily be achieved with two separate buttons on each row of a GridView but I needed something better than that.

Single and Double Clicking with a GridView

Create an new web application with a default page. For now, add EnableEventValidation="false" to the page directive. We will remove it later. Add a GridView and bind some data to it. Add two asp:ButtonField controls using the edit columns option on the GridView. Give these button fields command names of SingleClick and DoubleClick. (A select button could also be used for the SingleClick event but I've decided to use asp:ButtonField for both.)

<Columns>
    <asp:ButtonField Text="SingleClick" CommandName="SingleClick" />
    <asp:ButtonField Text="DoubleClick" CommandName="DoubleClick" />
</Columns>

Create a RowCommand event for the GridView with a switch block to capture the separate events.
For the demo, this code will write out a history of the events fired. The SingleClick command will also set the SelectedIndex of the row.

protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
    GridView _gridView = (GridView)sender;

    // Get the selected index and the command name
    int _selectedIndex = int.Parse(e.CommandArgument.ToString());
    string _commandName = e.CommandName;

    switch (_commandName)
    {
        case ("SingleClick"):
            _gridView.SelectedIndex = _selectedIndex;
            this.Message.Text += "Single clicked GridView row at index "
            + _selectedIndex.ToString() + "<br />";
        break;
        case ("DoubleClick"):
            this.Message.Text += "Double clicked GridView row at index "
            + _selectedIndex.ToString() + "<br />";
        break;
    }
}

Create a RowDataBound event to modify each row as it is bound. Now we need to take the client script which is used by the SingleClick button for postback and assign it to the entire row.

if (e.Row.RowType == DataControlRowType.DataRow)
{
    // Get the LinkButton control in the first cell
    LinkButton _singleClickButton = (LinkButton)e.Row.Cells[0].Controls[0];
    // Get the javascript which is assigned to this LinkButton
    string _jsSingle = 
    ClientScript.GetPostBackClientHyperlink(_singleClickButton, "");
    // Add this javascript to the onclick Attribute of the row
    e.Row.Attributes["onclick"] = _jsSingle;
}

We can also do the same for the DoubleClick button, however both of these will not work together.

if (e.Row.RowType == DataControlRowType.DataRow)
{
    // Get the LinkButton control in the second cell
    LinkButton _doubleClickButton = (LinkButton)e.Row.Cells[1].Controls[0];
    // Get the javascript which is assigned to this LinkButton
    string _jsDouble = 
    ClientScript.GetPostBackClientHyperlink(_doubleClickButton, "");
    // Add this JavaScript to the ondblclick Attribute of the row
    e.Row.Attributes["ondblclick"] = _jsDouble;
}

If we implement both these events together we will only get the functionality of the single click. This is because when the user starts a double click, the first click is taken as a single click and the page is posted back before the second click can happen. The JavaScript setTimeout method can be used to set a timeout on the first click, therefore giving the user a chance to complete a double click.

Looking at the source of the page, we can see the onclick event on the <tr> tags:

onclick="javascript:__doPostBack('GridView1$ctl02$ctl00','')"

Add a setTimeout method and give it a timeout of 300 milliseconds:

onclick="javascript:setTimeout
        ("__doPostBack('GridView1$ctl02$ctl00','')", 300)"

So the entire RowDataBound code looks like:

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // Get the LinkButton control in the first cell
        LinkButton _singleClickButton = (LinkButton)e.Row.Cells[0].Controls[0];
        // Get the javascript which is assigned to this LinkButton
        string _jsSingle = 
        ClientScript.GetPostBackClientHyperlink(_singleClickButton, "");
        // To prevent the first click from posting back immediately
        // (therefore giving the user a chance to double click) 
    // pause the postbackfor 300 milliseconds by 
        // wrapping the postback command in a setTimeout
        _jsSingle = _jsSingle.Insert(11, "setTimeout(\"");
        _jsSingle += "\", 300)";
        // Add this javascript to the onclick Attribute of the row
        e.Row.Attributes["onclick"] = _jsSingle;

        // Get the LinkButton control in the second cell
        LinkButton _doubleClickButton = (LinkButton)e.Row.Cells[1].Controls[0];
        // Get the javascript which is assigned to this LinkButton
        string _jsDouble = 
        ClientScript.GetPostBackClientHyperlink(_doubleClickButton, "");
        // Add this javascript to the ondblclick Attribute of the row
        e.Row.Attributes["ondblclick"] = _jsDouble;
    }
}

The buttons no longer need to be visible so hide them by adding Visible="false":

<Columns>
    <asp:ButtonField Text="SingleClick" CommandName="SingleClick" 
                            Visible="false" />
    <asp:ButtonField Text="DoubleClick" CommandName="DoubleClick" 
                            Visible="false" />
</Columns>

We can now single click and double click on a row and the appropriate action will be captured in the RowCommand code.

Register the postback or callback data for validation

Everything is working fine, but remember that we added EnableEventValidation="false" to the page directive. This is not the most secure option so we should remove it. This will cause an "Invalid postback or callback argument" error when a row is clicked or double clicked. The error tells us to use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation. (The purpose of EventValidation is well documented elsewhere and beyond the scope of this article.)

The ClientScriptManager.RegisterForEventValidation can be called by overriding the Render method. The trick here is to register the unique id of both the buttons for each row of the GridView. The UniqueID of the row is returned by GridViewRow.UniqueID. The UniqueID of the first button can be generated by appending "$ctl00" to the row's UniqueID and for the second button append "$ctl01".

The overridden Render method is as follows:

protected override void Render(HtmlTextWriter writer)
{
    foreach (GridViewRow r in GridView1.Rows)
    {
        if (r.RowType == DataControlRowType.DataRow)
        {
            Page.ClientScript.RegisterForEventValidation
                    (r.UniqueID + "$ctl00");
            Page.ClientScript.RegisterForEventValidation
                    (r.UniqueID + "$ctl01");
        }
    }

    base.Render(writer);
}

Now we will not get any "Invalid postback or callback argument" errors.

Other Controls

In the source code, I also demonstrate how to achieve this functionality with a DataList and ListBox controls. The code is quite similar so I won't show it here.

Single and Double Clicking with a DataList

With the DataList, the contents of the ItemTemplate are wrapped in an asp:Panel, giving something to assign the onclick and ondblclick events to.

Single and Double Clicking with a ListBox

With the ListBox, there are no Row or Item events but the onclick and ondblclick attributes can be added to the control.

In the SelectedIndexChanged event handler, Request.Form["__EventArgument"] will return the command name.

Conclusion

By looking closely at the JavaScript which is written out by ASP.NET we can extend the functionality of the GridView and DataList controls. To keep your applications secure, you should not use EnableEventValidation="false" if at all possible. Once you understand how EventValidation works, you can use ClientScript.RegisterForEventValidation to ensure your code works as intended.

History

  • v1.0 - 23rd Sep 2006
  • v1.1 - 25th Sep 2006
  • v1.2 - 12th Nov 2006
    Addition of a ListBox control to the demo
  • v1.3 - 20th Dec 2006
    VB.NET version of demo added to download

License

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

Share

About the Author

Declan Bright
Architect
Ireland Ireland
I have been designing and developing business solutions for the aviation and telecommunications industries since 1999. My experience covers a wide range of technologies and I have delivered a variety of web and mobile based solutions.

Comments and Discussions

 
GeneralMy vote of 2 Pin
Suman.Cha1-Dec-14 16:15
memberSuman.Cha1-Dec-14 16:15 
QuestionUse controls in such datalist Pin
Cheta Pandya28-Mar-14 17:41
memberCheta Pandya28-Mar-14 17:41 
Questiondouble click with paging enabled Pin
Xavier0112-Dec-12 15:23
memberXavier0112-Dec-12 15:23 
SuggestionSolution Pin
Vimalan JG16-Sep-12 19:41
memberVimalan JG16-Sep-12 19:41 
QuestionIn the Gridview I want Perticular Cell of Perticuler row want to be hide Pin
Member 822666512-Sep-12 18:30
memberMember 822666512-Sep-12 18:30 
GeneralMy vote of 4 Pin
Nitindev1239-Feb-11 20:19
memberNitindev1239-Feb-11 20:19 
Questiondoes this work in firefox? Pin
nooblet8829-Dec-09 14:07
membernooblet8829-Dec-09 14:07 
AnswerRe: does this work in firefox? Pin
nooblet8829-Dec-09 14:11
membernooblet8829-Dec-09 14:11 
nvm
QuestionHow to create click event or dlbclick event on GridView column header and deals with the event? [modified] Pin
worstnews10-Dec-08 21:24
memberworstnews10-Dec-08 21:24 
AnswerRe: How to create click event or dlbclick event on GridView column header and deals with the event? Pin
worstnews10-Dec-08 21:29
memberworstnews10-Dec-08 21:29 
Questionhow to brodcast the screen picture to client with C#? Pin
lockepeak20-Nov-08 21:19
memberlockepeak20-Nov-08 21:19 
GeneralStyles Changes when selection changes Pin
Member 17123332-Sep-08 23:43
memberMember 17123332-Sep-08 23:43 
QuestionI am clicking a row in gridview rather buttons... Pin
sarahshafqat15-Jul-08 19:06
membersarahshafqat15-Jul-08 19:06 
AnswerRe: I am clicking a row in gridview rather buttons... Pin
Declan Bright15-Jul-08 21:50
memberDeclan Bright15-Jul-08 21:50 
Questionhow about navigating with arrow keys? Pin
zekester3-Apr-08 14:26
memberzekester3-Apr-08 14:26 
QuestionRow click with Link click Pin
kirianno25-Mar-08 6:50
memberkirianno25-Mar-08 6:50 
GeneralRe: Row click with Link click Pin
Declan Bright25-Mar-08 8:23
memberDeclan Bright25-Mar-08 8:23 
Questionhow to redirect Pin
xiaota21-Oct-07 1:59
memberxiaota21-Oct-07 1:59 
AnswerRe: how to redirect Pin
Declan Bright21-Oct-07 21:44
memberDeclan Bright21-Oct-07 21:44 
GeneralRe: how to redirect Pin
xiaota21-Oct-07 21:51
memberxiaota21-Oct-07 21:51 
AnswerRe: how to redirect Pin
Declan Bright22-Oct-07 1:12
memberDeclan Bright22-Oct-07 1:12 
GeneralRe: how to redirect Pin
xiaota22-Oct-07 4:20
memberxiaota22-Oct-07 4:20 
GeneralRow Update Pin
shacharonishere2-Jun-07 8:46
membershacharonishere2-Jun-07 8:46 
GeneralRe: Row Update Pin
shacharonishere2-Jun-07 9:09
membershacharonishere2-Jun-07 9:09 
Generalcancel postback when clicked on same row Pin
shabbs19838-May-07 5:00
membershabbs19838-May-07 5:00 
GeneralRe: cancel postback when clicked on same row Pin
Declan Bright9-May-07 9:39
memberDeclan Bright9-May-07 9:39 
AnswerRe: cancel postback when clicked on same row Pin
aamehdi14-Jul-08 22:30
memberaamehdi14-Jul-08 22:30 
Generaldouble-click/single-click postback Pin
michael ison7-May-07 4:11
membermichael ison7-May-07 4:11 
GeneralRe: double-click/single-click postback Pin
michael ison8-May-07 10:00
membermichael ison8-May-07 10:00 
GeneralRe: double-click/single-click postback Pin
silo416-Mar-08 1:50
membersilo416-Mar-08 1:50 
GeneralRe: double-click/single-click postback Pin
Cpajoe20018-Jul-08 4:17
memberCpajoe20018-Jul-08 4:17 
GeneralRe: double-click/single-click postback Pin
bud442-Dec-08 2:53
memberbud442-Dec-08 2:53 
AnswerRe: double-click/single-click postback Pin
Paolo Fulgoni20-Apr-10 3:35
memberPaolo Fulgoni20-Apr-10 3:35 
GeneralThanks Pin
cykophysh3911-Apr-07 23:13
membercykophysh3911-Apr-07 23:13 
GeneralRe: Thanks Pin
Declan Bright12-Apr-07 0:38
memberDeclan Bright12-Apr-07 0:38 
Questiondisable control in grid when on click is pressed Pin
shabbs19835-Apr-07 1:43
membershabbs19835-Apr-07 1:43 
AnswerRe: disable control in grid when on click is pressed Pin
Declan Bright7-Apr-07 9:09
memberDeclan Bright7-Apr-07 9:09 
QuestionEditing the fields Pin
greg.boudreau22-Mar-07 3:58
membergreg.boudreau22-Mar-07 3:58 
GeneralRe: Editing the fields Pin
Declan Bright22-Mar-07 8:26
memberDeclan Bright22-Mar-07 8:26 
QuestionRe: Editing the fields Pin
greg.boudreau22-Mar-07 9:10
membergreg.boudreau22-Mar-07 9:10 
AnswerRe: Editing the fields Pin
Declan Bright22-Mar-07 9:35
memberDeclan Bright22-Mar-07 9:35 
GeneralRe: Editing the fields Pin
greg.boudreau23-Mar-07 3:48
membergreg.boudreau23-Mar-07 3:48 
QuestionProblem when LinkButton Changed to TemplateField Pin
walterdbn14-Mar-07 3:35
memberwalterdbn14-Mar-07 3:35 
QuestionRe: Problem when LinkButton Changed to TemplateField [modified] Pin
walterdbn14-Mar-07 3:39
memberwalterdbn14-Mar-07 3:39 
AnswerRe: Problem when LinkButton Changed to TemplateField Pin
Declan Bright20-Mar-07 9:22
memberDeclan Bright20-Mar-07 9:22 
GeneralChange cursor when hovering over gridview rows Pin
Holfling5-Mar-07 3:54
memberHolfling5-Mar-07 3:54 
GeneralRe: Change cursor when hovering over gridview rows Pin
Declan Bright5-Mar-07 5:21
memberDeclan Bright5-Mar-07 5:21 
GeneralExample ListBox won't work independently ... Pin
Member #31829965-Feb-07 6:23
memberMember #31829965-Feb-07 6:23 
GeneralRe: Example ListBox won't work independently ... Pin
Declan Bright5-Feb-07 8:39
memberDeclan Bright5-Feb-07 8:39 
QuestionVB version Pin
rasmorgan18-Dec-06 13:33
memberrasmorgan18-Dec-06 13:33 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150520.1 | Last Updated 20 Dec 2006
Article Copyright 2006 by Declan Bright
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid