To register for an Internet.com membership to receive newsletters and white papers, use the Register button ABOVE.
To participate in the message forums BELOW, click here
When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles [1.x] [2.0]
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search















internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers
ASP ASP.NET ASP FAQs Message Board Feedback ASP Jobs
Go Back   ASP Message Board > ASP Technology > ASP.NET

ASP.NET This forum is for questions on ASP.NET. If you've got a question about building a Web application on the Microsoft platform, this is the forum to use!

Reply
 
Thread Tools Display Modes
  #1  
Old 02-25-2009, 11:13 PM
Chyron Chyron is offline
Senior Member
 
Join Date: Jan 2009
Posts: 171
Default 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...
[onRowCreated]
If
e.Row.RowType = DataControlRowType.DataRow Then

e.Row.Attributes.Add(
"onclick", Page.ClientScript.GetPostBackEventReference(sender , "Select$" & e.Row.RowIndex.ToString))

End If

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?
Reply With Quote
  #2  
Old 02-26-2009, 08:40 PM
Chyron Chyron is offline
Senior Member
 
Join Date: Jan 2009
Posts: 171
Default

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
<a href="javascript:__doPostBack('gridView_ShowList', 'Select$0')" style="color:Black;">

It is a simple hyperlink that calls the _doPostBack() javascript function.

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
functionName = "javascript:__doPostBack('gridView_ShowList'" + "," + "'" + "Select$" & e.Row.RowIndex.ToString + "')"

If e.Row.RowType = DataControlRowType.DataRow Then
e.Row.Attributes.Add("onclick", functionName)
End If

End Sub

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 08:42 PM.
Reply With Quote
  #3  
Old 02-28-2009, 10:05 PM
Chyron Chyron is offline
Senior Member
 
Join Date: Jan 2009
Posts: 171
Default

Quote:
Originally Posted by Chyron View Post
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
<a href="javascript:__doPostBack('gridView_ShowList', 'Select$0')" style="color:Black;">

It is a simple hyperlink that calls the _doPostBack() javascript function.

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
functionName = "javascript:__doPostBack('gridView_ShowList'" + "," + "'" + "Select$" & e.Row.RowIndex.ToString + "')"

If e.Row.RowType = DataControlRowType.DataRow Then
e.Row.Attributes.Add("onclick", functionName)
End If

End Sub

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.
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.
Reply With Quote
  #4  
Old 02-28-2009, 10:27 PM
Bill Wilkinson Bill Wilkinson is offline
Senior Member
 
Join Date: Dec 1969
Posts: 93,281
Default

I would try just using JavaScript to add the ONCLICK to each row.

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":
Code:
<table id="GridView1" ...>
<tr>....</tr>
<tr>...</tr>
...
</table>
If you see something like that, then you can just add something like this to your page:
Code:
<head>
<script>
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
// or
    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 ...
}
</script>

<body onload="addRowClicks( )">
....
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.
Reply With Quote
  #5  
Old 03-02-2009, 06:43 PM
Chyron Chyron is offline
Senior Member
 
Join Date: Jan 2009
Posts: 171
Default

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.

I was able to get a javascript working that simulated clicking on the HREF for the LinkButton and to cause the cross page post to work. The overall picture is to click anywhere on the GridView to select a master record and then do a CrossPagePost to display the Detail.

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.
Reply With Quote
  #6  
Old 03-02-2009, 10:49 PM
Chyron Chyron is offline
Senior Member
 
Join Date: Jan 2009
Posts: 171
Default

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.
Reply With Quote
  #7  
Old 06-13-2009, 10:37 PM
Chyron Chyron is offline
Senior Member
 
Join Date: Jan 2009
Posts: 171
Default

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 page to which this code belongs features a repeater that uses a asp:table for the layout. In the _ItemDataBound event, the code gets a reference to the table control. It then adds three events to the table - onclick, onmouseover, and onmouse out. The onmouseover and onmouseout events serve to highlight the table row that the cursor is over by simply changing the CSS class. In the asp:table on the page, there's a asp:linkbutton which SELECTs the row. To enable the row to be SELECTed by clicking anywhere on the row, the onclick event adds the same Javascript to the table control that powers the SELECT linkbutton. Thus when the row is clicked, ASP.NET thinks that the SELECT button was clicked. Granted a much more gracefull way of doing this would be to figure out when ASP.NET actually attaches the Javascript to the LinkButton and then copy the Javascript over directly. This would ensure that the code would still work in the event that Billy and the Boys make any changes to how the LinkButton's Javascript operates.

The CSSClass for the SELECT linkbutton hides the linkbutton via display:none. If the visible property of the button is explicity set as in <asp:linkbutton visible=false... ASP.NET will not render the button. As such the Javascript that the code adds to the page will result in a 'Invalid postback or callback argument' when the row is clicked. ASP.NET throws the error as a security precaution.

Code:
    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"
        End If

        '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("onmouseover", "this.className='DirectoryDetailHighlight';")
        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
        'This code was derived from viewing the PageSource to see the JavaScript that ASP.NET attaches to the SELECT link button when its rendered
        functionName = "javascript:__doPostBack('" & RowSelectButton.UniqueID & "'" + "," + "'')"

        DetailRow.Attributes.Add("onclick", functionName)

    End Sub
The same basic principle should world for the other table-type controls like a gridview.

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 10:50 PM.
Reply With Quote
  #8  
Old 06-14-2009, 08:18 PM
Ryan6491 Ryan6491 is offline
Senior Member
 
Join Date: Feb 2009
Posts: 443
Default

Oh, I just noticed the bottom where you had an error on this...

I had a similar situation with a GridView. I injected my own javascript and expected ASP.NET to handle it since I was just copying functionality that ASP.NET had put into the page for other controls, but somehow it knew that I had added something and threw a security exception.

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:

EnableEventValidation="false"

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 08:23 PM. Reason: And YES - Metallica Rules!
Reply With Quote
  #9  
Old 06-14-2009, 09:30 PM
Chyron Chyron is offline
Senior Member
 
Join Date: Jan 2009
Posts: 171
Default

Odd, because the page is working just fine without EnableEventValidation set to false.

Did you catch that the Javascript that I'm adding to the table is identical to that of the SELECT link button?
Reply With Quote
  #10  
Old 06-14-2009, 09:36 PM
Ryan6491 Ryan6491 is offline
Senior Member
 
Join Date: Feb 2009
Posts: 443
Default

javascript:__doPostBack....

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 09:50 PM.
Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -5. The time now is 12:07 AM.

More ASP Resources

Reference:
-- ASPFAQs.com
-- VBScript Reference
-- JScript Reference
-- SQL Books Online
-- Official Docs
-- Commonly Asked Messageboard Questions

Resources:
-- Recent ASP Articles
-- ASP.NET Information
-- 4Guys ASP F.A.Q.
-- ASPFAQs.com
-- ASP Internet Resource
-- ASP.NET Internet Resource
-- ASP Coding Tips
-- Newsletter
-- Related Web Technologies
-- User Tips!!
-- ASP-related ListServs

Information:
-- Advertise
-- Author an Article
-- Feedback
-- ASP Messageboard F.A.Q.

Windows Technology
Check out these Web sites for articles, tutorials, FAQs, and code on ASP and related technologies!
-- 15Seconds.com
-- ASP101.com
-- ASPFAQs.com
-- ASPMessageboard.com
-- ASPWire.com

[Complete List of Sites]




Acceptable Use Policy

Internet.com
The Network for Technology Professionals

Search:

About Internet.com

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | E-mail Offers

Powered by vBulletin® Version 3.7.3
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.