Select a Row in A Gridview by Clicking Anywhere on it
I want to give my users the ability to select a row by clicking anywhere on it - as opposed to explicitly clicking on a SELECT link button. I've found several articles on how to do it most notably the basic technique posted here and here.
In short the code is...
e.Row.RowType = DataControlRowType.DataRow Then
"onclick", Page.ClientScript.GetPostBackEventReference(sender , "Select$" & e.Row.RowIndex.ToString))
But when I try it, ASP throws an error indicating that 'Invalid postback or callback argument' related to Event Validation being enabled. From what I've read, turning off Event Validation isn't a good idea from a security standpoint.
So are there anyother options out there? Where do I go from here?
If a add a SELECT link is it possible to trigger the select event using client side script?
Here's the alternative that doesn't require messing with the validation. I basically looked at how the a SELECT command field works and then worked to emulate it.
When you add a SELECT, it renders on the client as
Thus, all we have to do is create a script that will execute the same function. The server has no way of knowing if you clicked the hyperlink or the row and it doesn't matter. All that matters is that the _doPostBack() function is called.
Thus my solution is this...
Sub gridView_ShowList_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
Dim functionName As String
'Note that the gridview name is hard coded, the original code uses the sender object, but I couldn't get it to work
'in concatenating the string
If e.Row.RowType = DataControlRowType.DataRow Then
It is quite similar to the original code. I tried adding the original code in to look at what the Page.ClientScript.GetPostBackEventReference() function renders in HTML, however for some reason I wasn't able to get it to work. Not to mention that I only spent a couple of minutes on it and that I'm not in the mood to chance rabbits. Suffice to say that I have a solution that works.
Last edited by Chyron; 02-26-2009 at 09:42 PM.
Well I thought that this would work, but it doesn't. I realized that I wasn't thoroughly shaking it down so back to the drawing board. I did figure out that it's entirely possible to use client side script to simulate clicking on a <a href> tag which is how a Link Button works and I've had some success but I'm not quite there yet.
Originally Posted by Chyron
The "trick" to doing this will be to look at the HTML that ASP.NET generates for your GridView control. Here is a "for instance":
If you see something like that, then you can just add something like this to your page:
<table id="GridView1" ...>
In short, keep ASP.NET out of the JS business so far as possible. It doesn't play well, especially cross-browser. But I do have to admit I'm somewhat of a Luddite when it comes to ASP.NET.
function addRowClicks( )
var tbl = document.getElementById("GridView1");
var trs = tbl.rows; // I think this is right...you'd want to test it in MSIE and FF
var trs = tbl.getElementsByTagName("tr"); // but this might work better in one or other
for ( var t = 0; t < trs.length; ++ t )
var tr = trs[t];
tr.onclick = trClickHandler;
function trClickHandler( evt )
... write code to handle clicks from either MSIE or all other browsers ...
... not hard...many online sites show how ...
<body onload="addRowClicks( )">
Well, I figured out that the issue with .ClientId only supplying ctl00, ctl01, etc was because I was referencing it in the _RowCreated or _RowBound event. Referencing it in _SelectedIndexChanged produces the correct client side id.
The technique that I found that selects the row only works with a commandField, which (in)conveniently can be used directly with a cross page post back similar to a LinkButton's PostBackURL.
I'm now entertaining the idea of putting the LinkButton's doPostBack function in the onClick of the gridView Row (instead of the Command Field's as demonstrated above). So that clicking anywhere on the row becomes the same as clicking on the Link Button.
Then in the onRowCommand using code to select the row in the gridview (as if the SELECT command was clicked). This should select the row, highlight it and then cause the cross page post to fire. Basically encapsulating the select in the Link Button's onclick.
Funny how things come full circle. I had to temporarily shelve what I was working on that led to the orginal post. Months later and a bit more ASP.NET savy here's what I have.
The same basic principle should world for the other table-type controls like a gridview.
Protected Sub RepeaterDirectory_ItemDataBound(ByVal sender As Object, ByVal e As RepeaterItemEventArgs)
'The CSS class for an Item has a background color of #FFFFFF
'The CSS class for an AlternatingItem has a backgroundcolor of #EEEEEE
Dim OriginalBackgroundColor As String = "#FFFFFF"
'Which control are we going to add the events to
Dim TargetItem As Object
TargetItem = e.Item.FindControl("DirectoryDetail")
'Automatically change the CssClass if we're on an Alternating Item, given the complexity of the markup in the repeater, it only makes use of the ItemTemplate. If both the ItemTemplate and AlternatingItemTemplate keeping the two in sync would be quite difficult. By simply changing the CssClass we eliminate that problem.
If e.Item.ItemType = ListItemType.AlternatingItem Then
OriginalBackgroundColor = "#EEEEEE"
TargetItem.CssClass = "DirectoryDetailAlternatingItem"
'This is probably an oops as TargetItem points to the same object, but its quite late and its been a busy week
Dim DetailRow As Table = CType(e.Item.FindControl("DirectoryDetail"), Table)
'Using "this.className" directly greatly improves the response time of turning on or off the highlighting as opposed to .getElementById (or spinning everything out to a function). getElementById
'has to search through each element on a page, there is a noticable performance hit as the number of records on the page increases
'DirectoryDetailHighlight is identical to DirectoryDetail and DirectoryDetailAlternatingItem except for different values for color, backgroundColor and cursor (cursor:hand is used to provide a further visual cue
DetailRow.Attributes.Add("onmouseout", "this.className='" & DetailRow.CssClass & "';")
'Get a reference to the SELECT link button for the Item
Dim RowSelectButton As LinkButton = CType(e.Item.FindControl("SelectRow"), LinkButton)
Dim functionName As String
Keywords: Repeater, Gridview, Select Row, Select Row Click Anywhere, Select Gridview Row, Select Repeater Row, Highlight Row, Highlight Row Repeater, Highlight Gridview Row, Highlight Row Mouseover, ASP.NET, click on a row, click anywhere on a row
Last edited by Chyron; 06-13-2009 at 11:50 PM.
Oh, I just noticed the bottom where you had an error on this...
I was doing the page for an Intranet and wasn't too worried about the security that it was complaining about, so I ended up adding this attribute to the Page directive:
That turned off the security check and everything ran fine. If you want to do the "right" way, look up ClientScriptManager.RegisterForEventValidation
Found the MSDN page about it: PagesSection..::.EnableEventValidation Property
Hope that does it!
Last edited by Ryan6491; 06-14-2009 at 09:23 PM.
Reason: And YES - Metallica Rules!
Odd, because the page is working just fine without EnableEventValidation set to false.
That's exactly what I was trying on the GridView and it threw the exception. It knows you're trying to fake it out.
So you're saying the page works or no?
Last edited by Ryan6491; 06-14-2009 at 10:50 PM.