Click here to Skip to main content
Email Password   helpLost your password?

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

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
Generaldoes this work in firefox?
nooblet88
15:07 29 Dec '09  
does this work in firefox?
GeneralRe: does this work in firefox?
nooblet88
15:11 29 Dec '09  
nvm
QuestionHow to create click event or dlbclick event on GridView column header and deals with the event? [modified]
worstnews
22:24 10 Dec '08  
How to create click event or dlbclick event on GridView column header and deals with the event?


when the GridView column header was clicked,got the all cell value and
all cell backcolor were changed of the column you clicked

modified on Thursday, December 11, 2008 3:31 AM

AnswerRe: How to create click event or dlbclick event on GridView column header and deals with the event?
worstnews
22:29 10 Dec '08  
when the GridView column header was clicked,gets the all cell value
and all cell bankground of the colmun you clicked
Generalhow to brodcast the screen picture to client with C#?
lockepeak
22:19 20 Nov '08  
i want to capture full screen pictures of the host in span time ,and then broadcast it to clients. just as a teaching tool.
GeneralStyles Changes when selection changes
Member 1712333
0:43 3 Sep '08  
My GridView (SPGridView because of SharePoint) changes styles when I select the gridview for a second time. Filling the gridview causes no problem, selecting a row the first time also. But when I select a row the second time my style is gone and I see a plain gridview without styles.
QuestionI am clicking a row in gridview rather buttons...
sarahshafqat
20:06 15 Jul '08  
I am clicking a row in gridview rather buttons. And to get it working I was using EventValidation=false in page directive. But reading ur article I tried to make overload method render() but how would I know what value shall I give in place of "$ctl00"?

My code is:

protected void gv_RowDataBound(object sender,
GridViewRowEventArgs e)
{
//check the item being bound is actually a DataRow, if it is,
//wire up the required html events and attach the relevant JavaScripts
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Attributes["onmouseover"] =
"javascript:setMouseOverColor(this);";
e.Row.Attributes["onmouseout"] =
"javascript:setMouseOutColor(this);";
e.Row.Attributes["onclick"] =
ClientScript.GetPostBackClientHyperlink
(this.gv2, "Select$" + e.Row.RowIndex);
}
}

Please, help me...
AnswerRe: I am clicking a row in gridview rather buttons...
Declan Bright
22:50 15 Jul '08  
To see how asp.net has named the controls on the client side, you need to look at the source of the page it generates.
So, in your browser have look at the html of Gridview rows and you will see that each control has an id which ends with something like "$ctl00".

Once you have identified the controls which are generating the events you can register them with Page.ClientScript.RegisterForEventValidation
Hope this helps


Generalhow about navigating with arrow keys?
zekester
15:26 3 Apr '08  
Thanks for this tutorial, it really came in handy a while back when I was working on a project. Now I am working on a grid where I need to have single/doubleclicks, got that thanks to you. Now I need to be able to use the up and down arrow keys on the keyboard to move up and down the rows. Do you have anything on that handy? Thanks again!
QuestionRow click with Link click
kirianno
7:50 25 Mar '08  
Hi,
I have a DataList with rows that highlight when they have been clicked (which is working nicely) but I also have text links in one column of the row that I want to use to populate an iframe in a different column of the row. When i click on the text links, the row highlights but does not read my target or href information. Is there a way to make the links override the row onclick event?
Confused
GeneralRe: Row click with Link click
Declan Bright
9:23 25 Mar '08  
If the click event is on the row then it will always fire first. What you can do instead is assign the click event to each of the individual cells, except the cells with the links.

So instead of doing this:
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Get javascript link
string _jsSingle = ...

e.Row.Attributes["onclick"] = _jsSingle;
}
do this:
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Get javascript link
string _jsSingle = ...

// loop through the required cells
for (int columnIndex = 2; columnIndex < e.Row.Cells.Count; columnIndex++)
{
e.Row.Cells[columnIndex].Attributes["onclick"] = _jsSingle;
}
}
Hope this helps Smile


Generalhow to redirect
xiaota
2:59 21 Oct '07  
Hi,
After clicking, is that possible to redirect to another web page? (such as an HyperLinkField & to recover the Id of the selected row with the Request.QueryString)

best regards

bruno
GeneralRe: how to redirect
Declan Bright
22:44 21 Oct '07  
Hi Bruno

Yes it it possible. When binding the gridview rows in the RowDataBound event you can set the NavigateUrl property of a HyperLinkField column and include the Id in the querystring.


GeneralRe: how to redirect
xiaota
22:51 21 Oct '07  
Hi,

Thanks a lot for replying to me so quickly.

In fact I am actually using a RowDataBound on my Gridview:
-------------------
protected void GridView2_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Attributes["onmouseover"] = "this.style.cursor='hand';this.style.textDecoration='underline';this.style.background='#FFF5E6'";
e.Row.Attributes["onmouseout"] = "this.style.textDecoration='none';this.style.background='none'";
e.Row.Attributes["onclick"] = ClientScript.GetPostBackClientHyperlink(this, "Select$" + e.Row.RowIndex);
}
}
-------------------
Click on row works but of course nothing happens!

So I would like to code a GridView2_SelectedIndexChanged event but I don't know how to open another page (mypage.aspx?Id={0})

Is that possible to do it?

Best regards

Bruno
AnswerRe: how to redirect
Declan Bright
2:12 22 Oct '07  
Hi Bruno

In your GridView2_SelectedIndexChanged event you will need to retrieve the id which will probably be in a label control and then you can call Response.Redirect like so:
GridViewRow selectedRow = GridView2.SelectedRow;
Label idLabel = (Label)selectedRow.FindControl("myControl");
Response.Redirect("mypage.aspx?Id=" + idLabel.Text);



GeneralRe: how to redirect
xiaota
5:20 22 Oct '07  
Hi,

Thks to u it works fine now!

I just transformed my Id field into Template Field with a Label1 Id
and I added the following code in my SelectedIndexChanged event:

{
GridViewRow selectedRow = GridView2.SelectedRow;
Label idLabel = (Label)selectedRow.FindControl("Label1");
Response.Redirect("editStructure.aspx?StructureId=" + idLabel.Text);

}

Hope to see u at home in Cognac & to invite u to drink a glass.

best regards

bruno
GeneralRow Update
shacharonishere
9:46 2 Jun '07  
Hi ' i liked your article ' and i am usinh your code, but i got some problems.
after i doublie click the row
1 how do i get the values from the selected row
2 how do i save it to the gridview

in a normal way it works fine .

thsnks

david
GeneralRe: Row Update
shacharonishere
10:09 2 Jun '07  
another thing, i dont use the edit button.
i want the doublie click to be the trigger , so i cant use the OnRowUpdating event


Generalcancel postback when clicked on same row
shabbs1983
6:00 8 May '07  
Hi,

how can i cancel postback when i click on same row in grid view.
lets suppose i have two textbox in a row. when i clicked anyone first it should do postback but if i click the same row again, i do want to postback to occur, accutally i dont want anything to happend.

any suggestion or help would be appreciated.

thanks
GeneralRe: cancel postback when clicked on same row
Declan Bright
10:39 9 May '07  
Hi

What you need to do here is keep track of which row indexes were clicked with something like an object array, this could then be stored as a session object.
Within GridView1_RowDataBound as each row is being bound check if that row index is in the object array and if it is then don't add the onclick and ondblclick attributes.

Hope this helps Smile


AnswerRe: cancel postback when clicked on same row
aamehdi
23:30 14 Jul '08  
Hi,
I've test the folowing code and it works.
You should change the Render method, so it should looks like this:

    
protected override void Render(HtmlTextWriter writer)
{
// The client scripts for GridView1 were created in GridView1_RowDataBound
foreach (GridViewRow r in GridView1.Rows)
{
if (r.RowType == DataControlRowType.DataRow)
{
if((r.RowState & DataControlRowState.Selected) > 0)
r.Attributes["onclick"] = "";
Page.ClientScript.RegisterForEventValidation(r.UniqueID + "$ctl00");
Page.ClientScript.RegisterForEventValidation(r.UniqueID + "$ctl01");
}
}
base.Render(writer);
}

As you see the underlined codes was added.

Good Luck.
Generaldouble-click/single-click postback
michael ison
5:11 7 May '07  
First of all, your article is great and it solved some of my requirements for my project.

I have a question regarding the double-click and single-click behavior. When you do a double-click, it gets fired only when the single-click event doesn't fire first (which is the reason for the timer).

The problem is that this results in 2 postbacks. First for the double-click then for the single-click (due to the timer). Is there a way for the single-click postback to don't fire when the user double-clicks?

Thanks.
GeneralRe: double-click/single-click postback
michael ison
11:00 8 May '07  
Found the solution to my problem. Thanks.
GeneralRe: double-click/single-click postback
silo4
2:50 16 Mar '08  
Hi, Can you tell me how you fixed it? Thanks
GeneralRe: double-click/single-click postback
Cpajoe2001
5:17 8 Jul '08  
Did you ever get a response on how this was fixed I am getting the same issue


Last Updated 20 Dec 2006 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010