Select a Row in A Gridview by Clicking Anywhere on it

Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: Select a Row in A Gridview by Clicking Anywhere on it

  1. #1
    Join Date
    Jan 2009
    Posts
    173

    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?

  2. #2
    Join Date
    Jan 2009
    Posts
    173

    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.

  3. #3
    Join Date
    Jan 2009
    Posts
    173

    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.

  4. #4
    Join Date
    Dec 1969
    Posts
    95,997

    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.


  5. #5
    Join Date
    Jan 2009
    Posts
    173

    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.

  6. #6
    Join Date
    Jan 2009
    Posts
    173

    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.

  7. #7
    Join Date
    Jan 2009
    Posts
    173

    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.

  8. #8
    Join Date
    Feb 2009
    Posts
    452

    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!

  9. #9
    Join Date
    Jan 2009
    Posts
    173

    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?

  10. #10
    Join Date
    Feb 2009
    Posts
    452

    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


More ASP Resources

Resources:
-- ASP Articles
-- ASP.NET Information
-- 4Guys ASP F.A.Q.
-- ASPFAQs.com
-- ASP Coding Tips
-- Related Web Technologies
-- User Tips!!
-- JavaScripts


Development Centers
-- HTML5 Development Center
-- Windows Mobile Development Center
-- Android Development Center
-- Cloud Development Project Center


Development Technology
Check out these sites for more articles, tutorials, FAQs, discussions, and code!
-- CodeGuru.com
-- VBForums.com
-- DevX.com
-- Developer.com
-- HTMLGoodies